Skip to main content
Glama

riddle_builder_update

Edits an existing Riddle of any type with the same build configuration riddle_builder_create takes - but as a merge, not a rebuild: only the fields you send are touched, an omitted one is left exactly as it is. Blocks are addressed by their "id", added with "$create": true, removed with "$delete": true and reordered with "$blocksOrder"; the same grammar edits a block's "items"/"fields" and a Personality Test's "personalities", while a Placeholder's "conditions" is replaced as a whole (see each field). Read the Riddle with riddle_get first: what it returns under "build" is exactly the shape this takes, block IDs included. Only Riddles created by the riddle_builder_* tools or by the Riddle AI can be edited here - one built manually in the Creator can hold content this build config cannot express, and is rejected; check context.origin.apiManageable on riddle_get ("origin" on riddle_list) beforehand. Returns the compact build-configuration envelope of riddle_get (riddle://reference/response-format).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
UUIDYesThe UUID of the Riddle to edit, as returned by riddle_list or riddle_get (e.g. "6FA740EW") - the Riddle itself, never a block id or a project id.
omitNoSections of the returned envelope to leave out; omit the parameter for the whole envelope. "uuid"/"type"/"modifiedAt" are always returned, and whatever you leave out is echoed back under "omittedFields", so a missing key never means the Riddle has none of it. Details: riddle://reference/concepts/warnings.
buildYesThe changes to apply, as a partial build configuration in the engine's own key names - the same shape riddle_get returns under "build" and riddle_builder_create takes. Only the fields you send are touched; send at least one. A field only exists for the Riddle types that have it, and unknown keys are rejected rather than ignored.
publishNoWhether to publish the Riddle after the edit; default false, which leaves the changes in the draft. It rides along with an edit, it is not one: publish: true with an empty "build" is rejected. To publish what is already in the draft, call riddle_publish.

Schema Changelog

Changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. Changed18 schema fields changed
    • changedInput schema / properties / UUID / description
      Previous value: -"The UUID of the Riddle to edit (as returned by riddle_list / riddle_get)"New value: +"The UUID of the Riddle to edit, as returned by riddle_list or riddle_get (e.g. \"6FA740EW\") - the Riddle itself, never a block id or a project id."
    • changedInput schema / properties / build / description
      Previous value: -"The changes to apply, as a partial build configuration in the engine's own key names - the same shape riddle_get returns under \"build\" and the riddle_builder_<type> tools take. Only the fields you send are touched; send at least one. A field only exists for the Riddle types that have it, and unknown keys are rejected rather than ignored."New value: +"The changes to apply, as a partial build configuration in the engine's own key names - the same shape riddle_get returns under \"build\" and riddle_builder_create takes. Only the fields you send are touched; send at least one. A field only exists for the Riddle types that have it, and unknown keys are rejected rather than ignored."
    • changedInput schema / properties / build / properties / $blocksOrder / description
      Previous value: -"The new order of the Riddle's blocks, as the complete list of their IDs - [3, 1, 2] puts block 3 first. Complete means every ID the Riddle has after this edit, exactly once: a partial list is rejected, because where the blocks you left out belong is exactly what it does not say. It is applied after everything else in the same call, so a block you delete here must NOT be listed and a block you add here MUST be - give a \"$create\" entry an explicit \"id\" to name it, taken from \"nextBlockId\" in the riddle_get response (count up from it for several new blocks) and never derived from the ids in \"build\", which are shared with the Riddle's results and personalities; claiming a taken id is rejected with an error naming the free one. The same marker works inside a block, next to the collection it orders: {\"id\": 3, \"$itemsOrder\": [2, 1]} reorders that block's items, \"$fieldsOrder\" a Form's fields, and it reaches one level deeper through a merged \"fields\" edit - {\"id\": 3, \"fields\": [{\"id\": 5, \"$itemsOrder\": [2, 1]}]} reorders the items of that one Dropdown field. Only a collection whose entries have ids of their own can be ordered at all, and a few that do still reject the marker because an entry's position carries meaning of its own - riddle://reference/concepts/merge-semantics says which collection is which, and the error says so too if you try."New value: +"The new order of the Riddle's blocks, as the complete list of their IDs - [3, 1, 2] puts block 3 first. Complete means every ID the Riddle has AFTER this edit, exactly once; a partial list is rejected. It runs last, so a deleted block must NOT be listed and an added one MUST be - give the \"$create\" entry an explicit \"id\" from riddle_get's \"nextBlockId\". The same marker orders a collection inside a block (\"$itemsOrder\", \"$fieldsOrder\"). Rules: riddle://reference/concepts/merge-semantics."
    • changedInput schema / properties / build / properties / blocks / description
      Previous value: -"The blocks to change, add or remove - only the ones you touch, everything else stays as it is. To EDIT, pass the block's \"id\" (riddle_get reports it) plus only the properties that change - {\"id\": 3, \"title\": \"New question title\"}. To ADD, pass \"$create\": true instead of an \"id\" plus everything a new block needs, the same shape the riddle_builder_<type> tool of this Riddle's type takes - {\"$create\": true, \"type\": \"SingleChoice\", \"title\": \"New question\", \"items\": [...]}. To REMOVE, pass \"id\" plus \"$delete\": true. A block cannot change its \"type\" in an edit (delete it and add a new one instead), and an unknown \"id\" is rejected with the list of IDs that do exist. The collections INSIDE a block work the same way wherever their entries have ids - {\"id\": 3, \"items\": [{\"id\": 2, \"title\": \"Bonn\"}]} renames one answer and leaves the others alone - and are replaced wholesale where they do not. Which collection is which, what an entry id is scoped to, why an entry without an \"id\" or \"$create\" is rejected, which deletes are refused for still being referenced (custom logic, a hotspot's \"goToImage:\"), and which rules are checked against the merge result rather than against what you sent: riddle://reference/concepts/merge-semantics, with the marker rules themselves in riddle://reference/concepts/editing."New value: +"The blocks to change, add or remove - only the ones you touch, everything else stays as it is. EDIT: the block's \"id\" (riddle_get reports it) plus only the properties that change - {\"id\": 3, \"title\": \"New question title\"}. ADD: \"$create\": true instead of an \"id\", plus everything a new block needs in the shape riddle_builder_create takes - {\"$create\": true, \"type\": \"SingleChoice\", \"title\": \"New question\", \"items\": [...]}. REMOVE: \"id\" plus \"$delete\": true. A block cannot change its \"type\"; an unknown \"id\" is rejected naming the ids that exist. A collection inside a block merges by \"id\" the same way - {\"id\": 3, \"items\": [{\"id\": 2, \"title\": \"Bonn\"}]} renames one answer and leaves the others alone. Which collections merge, which are replaced wholesale, and which deletes are refused for still being referenced: riddle://reference/concepts/merge-semantics (markers: riddle://reference/concepts/editing)."
    • changedInput schema / properties / build / properties / conditions / description
      Previous value: -"Prioritized (first match wins), time-windowed list of routing rules evaluated before the fallback \"riddleId\" (max 100 conditions). Each condition targets either another Riddle or a tag - exactly one of \"riddleId\" (UUID of an existing, non-Placeholder, published Riddle) or \"tag\" (name or numeric id of an EXISTING tag in this Riddle's own scope - a typo'd name is rejected, never auto-created; sending a numeric id reads back as the tag NAME, which is ambiguous if two tags in this scope share a name) is required, never both. No other key is accepted on a condition: unknown keys and \"$create\"/\"$delete\" markers are rejected - \"conditions\" always replaces the whole list, there is no per-entry merge (see \"resend\" below). A \"tag\" condition additionally requires \"tagMode\": \"lastPublished\" (the most recently published Riddle carrying that tag) or \"random\" (a random one, optionally re-picked every \"randomRefreshIntervalSeconds\", a positive integer of seconds, only accepted together with tagMode \"random\"; defaults to 86400 when omitted and that default is written into the read-back, so echo it back on a resend for a byte-identical round-trip). Each condition may also carry a time window, either a date range (\"from\", required; \"to\", optional - open-ended) or a daily time-of-day range (\"dailyFrom\" and \"dailyTo\", both required together) - never both kinds on the same condition, and a condition with neither always matches whenever it is reached. Dates accept \"YYYY-MM-DD\" (midnight UTC) or full ISO 8601 (a trailing \"Z\" allowed) and are canonicalized to \"YYYY-MM-DDTHH:MM:SS+00:00\"; daily times accept \"HH:MM\" or \"HH:MM:SS\" and always come back as \"HH:MM:SS\"; a non-string date/time value (a unix int, a bool) is rejected. A date \"to\" before \"from\" is rejected; an out-of-range daily component (\"25:00:00\", \"12:60\") is rejected too, NOT wrapped - \"dailyTo\" before \"dailyFrom\" is the one legitimate exception, meaning an overnight window (e.g. 22:00-02:00). Normalization: the list is NOT stored or returned in the order you send it. It is sorted into three tiers - date-windowed conditions first, then daily-windowed, then windowless (so a daily window can never outrank a date window) - ascending within a tier by \"from\"/\"dailyFrom\" (windowless entries keep your send order); date and daily windows are never compared against each other, and duplicates are kept, not deduplicated. When two windows of the SAME kind overlap, the earlier condition's \"to\"/\"dailyTo\" is silently rewritten to the later condition's start (the later condition wins the contested interval - this is lossy and unannounced); a \"to\"-less condition that is not last in its tier gets a \"to\" synthesized as the next condition's start, so only the last condition of a tier may stay open-ended. Applying this to an already-normalized list changes nothing (idempotent). Resend safety: because \"conditions\" replaces the whole list, a condition (or the fallback) whose target Riddle was deleted/unpublished, or whose tag was removed, is DROPPED from riddle_get with a warning (reason \"PROPERTY_NOT_SERIALIZABLE\" for a condition, path \"conditions[<target>] (<why>)\"; reason \"RIDDLE_DATA_NOT_EXPRESSIBLE\" for the fallback, path \"riddleId\") while still being RETAINED in storage - it reappears once the target becomes valid again. Sending that damaged read-back straight back to riddle_builder_update therefore PERMANENTLY deletes the hidden dangling condition(s); the fallback is not affected the same way, because an omitted \"riddleId\" means \"don't touch it\" rather than \"clear it\" (see that field)."New value: +"Placeholder only. Prioritized (first match wins), time-windowed routing rules evaluated before the fallback \"riddleId\"; at most 100. Each targets exactly one of \"riddleId\" (UUID of an existing, non-Placeholder, published Riddle) or \"tag\" (name or numeric id of an EXISTING tag in this Riddle's scope - a typo'd name is rejected, never auto-created), never both; a \"tag\" also requires \"tagMode\": \"lastPublished\" or \"random\" (with optional \"randomRefreshIntervalSeconds\", \"random\" only). ONE kind of time window per condition - a date range (\"from\" required, \"to\" optional) or a daily one (\"dailyFrom\" plus \"dailyTo\") - with neither it always matches. No other key is accepted. This REPLACES the whole list, and the stored list is re-sorted into tiers with overlapping windows trimmed, so a read-back is not what you sent. Normalization, and why resending a read-back can delete a condition: riddle://reference/riddle-builder/riddle-types with riddleType [\"Placeholder\"]."
    • changedInput schema / properties / build / properties / leaderboard / description
      Previous value: -"Quiz/Predictor/Minigame only. New leaderboard connection, same shape as in the riddle_builder_<type> tools. Omit to leave the Riddle's leaderboard connections exactly as they are - unlike \"riddleConnections\", this is not resolved into a scalar leaf that could be silently reset: the underlying block only runs, and only ever appends a connection, when you actually send this field, so there is nothing to merge per key."New value: +"Quiz/Predictor/Minigame only. New leaderboard connection: \"connections\" (leaderboard UUIDs), \"identifier\", \"nickname\", as in riddle_builder_create. Omit to leave the Riddle's connections exactly as they are - sending this only ever appends a connection, so there is nothing to merge per key."
    • changedInput schema / properties / build / properties / logic / description
      Previous value: -"New branching logic tree, same shape as in the riddle_builder_<type> tools. Replaces the current logic; omit to keep it. Deleting a block (see \"blocks\") that is still referenced by the Riddle's existing CUSTOM logic is rejected unless the same request resolves it: either send a full replacement tree here that no longer references the deleted block(s), or send \"logic\": {\"$reset\": true} to discard the custom logic and fall back to the default linear flow - mutually exclusive, \"$reset\": true alongside any other key in \"logic\" is rejected. The error names exactly which deleted block(s) are still referenced and by which logic node(s). This guard never fires when the logic is already the default linear one: deleting a block always works there, the linear order is simply regenerated."New value: +"New branching logic tree, same shape as in riddle_builder_create. Replaces the current logic; omit to keep it. Deleting a block the stored CUSTOM logic still references is rejected unless the same call sends a replacement tree without it, or \"logic\": {\"$reset\": true} to fall back to the default linear flow (\"$reset\" with any other key is rejected). Node shapes: riddle://reference/concepts/logic."
    • changedInput schema / properties / build / properties / personalities / description
      Previous value: -"Personality Test only. The personalities to change, add or remove - only the ones you touch, everything else stays as it is, merged entry-by-entry by \"id\" exactly like the Riddle's own \"blocks\" (see EDIT_BLOCKS). To EDIT, pass the personality's \"id\" (riddle_get reports it) plus only the properties that change. To ADD, pass \"$create\": true instead of an \"id\" plus everything a new personality needs (the same shape riddle_builder_personality takes). To REMOVE, pass \"id\" plus \"$delete\": true. An entry with no \"id\" and no \"$create\" is rejected the same way a block is - it has no \"id\"; add \"$create\": true to add it as a new one instead. The order of the personalities is NOT editable: there is no \"$personalitiesOrder\" (sending one is rejected) and, because this collection is merged by id, the order the entries are sent in has no meaning either - a \"$create\" is appended at the end and everything else keeps the place it has. Reorder them in the Creator if the order matters. The minimum of 2 personalities is checked against the result AFTER the merge, so a \"$delete\" that would leave fewer than 2 is rejected. The scores already stored on every answer item follow their personality BY IDENTITY, not by position: a personality that stays keeps its score, a deleted personality takes its scores with it, and a newly created personality starts at 0 on every existing answer item until you say otherwise - resend the affected blocks' \"items\" with their full \"scores\" arrays in the same call to set them yourself (that is applied after this and simply wins)."New value: +"Personality Test only. The personalities to change, add or remove, merged by \"id\" exactly like \"blocks\" - \"id\" plus the changed properties, \"$create\": true plus a full new personality, or \"id\" plus \"$delete\": true. There is no \"$personalitiesOrder\": the order is not editable, and the order you send carries no meaning. The minimum of 2 is checked against the merge result. Answer \"scores\" follow a personality by identity, not position - a new one starts at 0 on every existing answer item, so resend the affected blocks' \"items\" with their full \"scores\" arrays in the same call."
    • changedInput schema / properties / build / properties / preset / description
      Previous value: -"Design and riddle-level behaviour settings to change, same shape as in the riddle_builder_<type> tools. Only the keys you send are applied. A Leaderboard's own display settings are part of this too, the podium colours (color1st/color2nd/color3rd) and isEmailVerificationEnabled among them."New value: +"Design and riddle-level behaviour settings to change, same shape as in riddle_builder_create; only the keys you send are applied. A Leaderboard's podium colours (\"color1st\"/\"color2nd\"/\"color3rd\") and \"isEmailVerificationEnabled\" live here too."
    • changedInput schema / properties / build / properties / publish / description
      Previous value: -"Publish-configuration settings to change, same shape as in the riddle_builder_<type> tools. Only the keys you send are applied. Distinct from this tool's top-level \"publish\" boolean, which publishes the Riddle right away."New value: +"Publish-configuration settings to change, same shape as in riddle_builder_create; only the keys you send are applied. Distinct from this tool's top-level \"publish\" boolean, which publishes right away."
    • changedInput schema / properties / build / properties / result / description
      Previous value: -"New single result page (Poll / Form / Predictor / Personality / Minigame / Story), same shape as in the riddle_builder_<type> tools. Replaces the current result page as a whole - a result page cannot be edited property-by-property or merged by id the way \"blocks\" can; send it complete, exactly as you would when creating the Riddle. Omit to keep the current one untouched."New value: +"New single result page (Poll / Form / Predictor / Personality / Minigame / Story), same shape as in riddle_builder_create. Replaces the current one as a whole - a result page is neither editable property-by-property nor mergeable by \"id\", so send it complete. Omit to keep it untouched."
    • changedInput schema / properties / build / properties / results / description
      Previous value: -"New result pages (Quiz), same shape as in riddle_builder_quiz. Replaces ALL current result pages with what you send, in the order you send it: result pages are deliberately neither editable per entry nor reorderable, so read them with riddle_get first and resend every page you want to keep, including its \"id\", which is honored to keep the page stable across the resend. Omit the field to keep all result pages untouched. Why, and which markers are rejected on a page: riddle://reference/concepts/result-pages."New value: +"New result pages (Quiz), same shape as in riddle_builder_create. Replaces ALL current pages with what you send, in the order you send it - pages are neither editable per entry nor reorderable, so read them with riddle_get first and resend every page you want to keep, including its \"id\", which is honored to keep the page stable. Omit to keep them all untouched. riddle://reference/concepts/result-pages."
    • changedInput schema / properties / build / properties / riddleConnections / description
      Previous value: -"Leaderboard only. The complete list of connected Riddle UUIDs - it REPLACES the stored set wholesale rather than appending (the property has no \"append\" flag and buildRiddleConnections() rebuilds the array from scratch), so to add or drop a single connection, call riddle_get first and resend every UUID you want to keep. Max 10; each target Riddle must already be published and must have Name and Email form fields."New value: +"Leaderboard only. The complete list of connected Riddle UUIDs - it REPLACES the stored set rather than appending, so read the Riddle with riddle_get first and resend every UUID you want to keep. Max 10; each target must already be published and have Name and Email form fields."
    • changedInput schema / properties / build / properties / riddleId / description
      Previous value: -"The fallback target: the UUID of the Riddle to show when no condition matches (or there are none). Must be an existing, non-Placeholder, published Riddle, and cannot be this Placeholder itself. Having no fallback at all is meaningful on its own - a Placeholder with no fallback and no matching condition resolves to nothing, which is a decision the Embed side makes, not this repo. On an EDIT, omitting this field means \"don't touch it\"; send \"riddleId\": null to actually clear the fallback back to none - which is rejected when it would leave the Placeholder with no fallback AND no conditions at all (it could then never display any Riddle), so clear it only while at least one condition remains, or send a replacement \"conditions\" list in the same call. The same rule rejects \"conditions\": [] on a Placeholder that has no fallback. If the target is later deleted/unpublished, the fallback is dropped from riddle_get with a warning (reason \"RIDDLE_DATA_NOT_EXPRESSIBLE\", path \"riddleId\") but stays in storage and reappears once the target is valid again."New value: +"Placeholder only. The fallback target: the UUID of the Riddle to show when no condition matches. Must be an existing, non-Placeholder, published Riddle, and not this Placeholder itself. Having none is meaningful - the Placeholder then resolves to nothing. On an EDIT, omitting it leaves it as it is; \"riddleId\": null clears it, and is rejected if that would leave the Placeholder with no fallback and no conditions at all - as is \"conditions\": [] while this is empty. riddle://reference/riddle-builder/riddle-types with riddleType [\"Placeholder\"]."
    • changedInput schema / properties / build / properties / scoring / description
      Previous value: -"Predictor only. New scoring rules, same shape as in riddle_builder_predictor - only the keys you send are changed, the rest of the stored rules are kept. Applied the same way \"preset\"/\"publish\" are: a merge into the existing nested config, not a wholesale replacement, so e.g. sending only {\"correct\": 50} leaves tendency/difference/wrong exactly as they were."New value: +"Predictor only. New scoring rules, same shape as in riddle_builder_create - only the keys you send are changed, so {\"correct\": 50} leaves \"tendency\"/\"difference\"/\"wrong\" as they were. Omit to keep them."
    • changedInput schema / properties / omit / description
      Previous value: -"Leaves parts of the returned envelope out. Values: \"build\", \"warnings\", \"nextBlockId\", \"published\", \"context\" (whole sections) and \"build.omittedDefaults\" (the per-block maps of properties left at their default, inside every build config in the response). Omit for the whole envelope. \"uuid\"/\"type\"/\"modifiedAt\" are always returned. Reach for omit: [\"build.omittedDefaults\"] on almost every build - it drops ~85-90% of the read-back and loses nothing, since riddle://reference/block-defaults/<block type> states the same defaults; what you must not do either way is resend those values. When you leave anything out the response names it under \"omittedFields\", so a missing key never means the Riddle has none of it. Same parameter as riddle_get's."New value: +"Sections of the returned envelope to leave out; omit the parameter for the whole envelope. \"uuid\"/\"type\"/\"modifiedAt\" are always returned, and whatever you leave out is echoed back under \"omittedFields\", so a missing key never means the Riddle has none of it. Details: riddle://reference/concepts/warnings."
    • changedInput schema / properties / omit / items / enum
      Previous value: -[
      -  "build",
      -  "warnings",
      -  "nextBlockId",
      -  "published",
      -  "context",
      -  "build.omittedDefaults"
      -]New value: +[
      +  "build",
      +  "warnings",
      +  "nextBlockId",
      +  "published",
      +  "context"
      +]
    • changedInput schema / properties / publish / description
      Previous value: -"Whether to publish the Riddle after the edit; default is false, which leaves the changes in the draft. It rides along with an edit, it is not one: this tool with publish: true and an empty \"build\" is rejected with \"Nothing to edit: send at least one of ...\". To publish what is already in the draft, call riddle_publish."New value: +"Whether to publish the Riddle after the edit; default false, which leaves the changes in the draft. It rides along with an edit, it is not one: publish: true with an empty \"build\" is rejected. To publish what is already in the draft, call riddle_publish."
  2. Changed5 schema fields changed
    • changedInput schema / properties / build / properties / $blocksOrder / description
      Previous value: -"The new order of the Riddle's blocks, as the complete list of their IDs - [3, 1, 2] puts block 3 first. Complete means every ID the Riddle has after this edit, exactly once: a partial list is rejected, because where the blocks you left out belong is exactly what it does not say. It is applied after everything else in the same call, so a block you delete here must NOT be listed and a block you add here MUST be - give a \"$create\" entry an explicit \"id\" to name it, taken from \"nextBlockId\" in the riddle_get response (count up from it for several new blocks). Do not derive that id from the ids in \"build\": they are shared with the Riddle's results and personalities and are never reused, so the next one is usually already taken; claiming a taken id is rejected with an error naming the free one. The same marker works inside a block, next to the collection it orders: {\"id\": 3, \"$itemsOrder\": [2, 1]} reorders that block's items, \"$fieldsOrder\" a Form's fields, and so on. It reaches one level deeper through a merged \"fields\" edit: {\"id\": 3, \"fields\": [{\"id\": 5, \"$itemsOrder\": [2, 1]}]} reorders the items of that one Dropdown field. The one limit is that the collection's entries need ids of their own. Collections without ids - reply-to/CC/BCC addresses, selected Riddles/types/tags, a TypeRush item's answers, a reaction scale, a Matrix question's scale, custom symbols, riddle connections, tracking networks, share networks, ad variables, per-block timer times, a personality answer's scores, a Predictor block's items (their id IS their position, 0/1 - resend \"items\" in the order you want instead), a Swiper block's items (their position IS the swipe answer, first card \"dislike\", second \"like\" - swap the two by resending both cards by id) - are simply sent in the order you want them in, and the error says so if you try."New value: +"The new order of the Riddle's blocks, as the complete list of their IDs - [3, 1, 2] puts block 3 first. Complete means every ID the Riddle has after this edit, exactly once: a partial list is rejected, because where the blocks you left out belong is exactly what it does not say. It is applied after everything else in the same call, so a block you delete here must NOT be listed and a block you add here MUST be - give a \"$create\" entry an explicit \"id\" to name it, taken from \"nextBlockId\" in the riddle_get response (count up from it for several new blocks) and never derived from the ids in \"build\", which are shared with the Riddle's results and personalities; claiming a taken id is rejected with an error naming the free one. The same marker works inside a block, next to the collection it orders: {\"id\": 3, \"$itemsOrder\": [2, 1]} reorders that block's items, \"$fieldsOrder\" a Form's fields, and it reaches one level deeper through a merged \"fields\" edit - {\"id\": 3, \"fields\": [{\"id\": 5, \"$itemsOrder\": [2, 1]}]} reorders the items of that one Dropdown field. Only a collection whose entries have ids of their own can be ordered at all, and a few that do still reject the marker because an entry's position carries meaning of its own - riddle://reference/concepts/merge-semantics says which collection is which, and the error says so too if you try."
    • changedInput schema / properties / build / properties / blocks / description
      Previous value: -"The blocks to change, add or remove - only the ones you touch, everything else stays as it is. To EDIT, pass the block's \"id\" (riddle_get reports it) plus only the properties that change - {\"id\": 3, \"title\": \"New question title\"}; the block's other properties, and every block you do not list, are untouched. To ADD, pass \"$create\": true instead of an \"id\" plus everything a new block needs (the same shape the riddle_builder_<type> tool of this Riddle's type takes) - {\"$create\": true, \"type\": \"SingleChoice\", \"title\": \"New question\", \"items\": [...]}. To REMOVE, pass \"id\" plus \"$delete\": true - {\"id\": 3, \"$delete\": true}. Removing a block still referenced by custom logic is rejected unless \"logic\" (see that field) resolves it in the same request. A block cannot change its \"type\" in an edit (delete it and add a new one instead), and an unknown \"id\" is rejected with the list of IDs that do exist. The collections INSIDE a block whose entries have a stable id merge the very same way - a question's \"items\" (of every type: Quiz/Personality answers, Poll answers, Matrix rows, Swiper cards, TierList tiers and items, ThisOrThat contenders, WheelSpinner items), an InteractiveGraphic's \"images\" and the \"hotspots\" inside each of them (deleting an image a hotspot still points at with \"goToImage:\" is rejected the same way a logic-referenced block is - repoint or delete those hotspots in the same request), a FormBuilder's \"fields\" and a Dropdown field's \"items\": {\"id\": 3, \"items\": [{\"id\": 2, \"title\": \"Bonn\"}]} renames one answer and leaves the others alone, {\"$create\": true, ...} adds an entry, {\"id\": 2, \"$delete\": true} removes one - those entry ids are scoped to their own collection and never come from \"nextBlockId\", so they repeat across blocks and only mean anything together with the id of the block holding them. An entry with no \"id\" is rejected rather than added under a new one, so a resend that dropped its ids cannot silently re-create the collection and break references into it (blockId_fieldId identifiers, logic, personality scores) - add \"$create\": true when you do mean a new entry. Every entry of every collection is an object, which is what lets it carry its \"id\" or its marker and so address a stored entry. Minimum/maximum entry counts are checked against the result of the merge, not against what you sent, and so is any rule spanning the whole collection (a question needs a correct answer; a WheelSpinner's item percents must sum to 100, so send the percent of every item you shift weight between). Collections that have NOT opted into this (a question bank's target blocks, a Matrix question's \"scale\") are still replaced wholesale - send every entry you want to keep. A Matrix \"scale\" is keyed by the value each rating stands for and has no ids at all, so a merge-style entry ({\"id\": 2, ...}, \"$create\", \"$delete\") is rejected instead of taken as the new scale: resend the complete scale, e.g. {\"id\": 3, \"scale\": {\"0\": {\"title\": \"Bad\"}, \"1\": {\"title\": \"Okay\"}, \"2\": {\"title\": \"Good\"}}}."New value: +"The blocks to change, add or remove - only the ones you touch, everything else stays as it is. To EDIT, pass the block's \"id\" (riddle_get reports it) plus only the properties that change - {\"id\": 3, \"title\": \"New question title\"}. To ADD, pass \"$create\": true instead of an \"id\" plus everything a new block needs, the same shape the riddle_builder_<type> tool of this Riddle's type takes - {\"$create\": true, \"type\": \"SingleChoice\", \"title\": \"New question\", \"items\": [...]}. To REMOVE, pass \"id\" plus \"$delete\": true. A block cannot change its \"type\" in an edit (delete it and add a new one instead), and an unknown \"id\" is rejected with the list of IDs that do exist. The collections INSIDE a block work the same way wherever their entries have ids - {\"id\": 3, \"items\": [{\"id\": 2, \"title\": \"Bonn\"}]} renames one answer and leaves the others alone - and are replaced wholesale where they do not. Which collection is which, what an entry id is scoped to, why an entry without an \"id\" or \"$create\" is rejected, which deletes are refused for still being referenced (custom logic, a hotspot's \"goToImage:\"), and which rules are checked against the merge result rather than against what you sent: riddle://reference/concepts/merge-semantics, with the marker rules themselves in riddle://reference/concepts/editing."
    • changedInput schema / properties / build / properties / personalities / description
      Previous value: -"Personality Test only. The personalities to change, add or remove - only the ones you touch, everything else stays as it is, merged entry-by-entry by \"id\" exactly like the Riddle's own \"blocks\" (see EDIT_BLOCKS). To EDIT, pass the personality's \"id\" (riddle_get reports it) plus only the properties that change. To ADD, pass \"$create\": true instead of an \"id\" plus everything a new personality needs (the same shape riddle_builder_personality takes). To REMOVE, pass \"id\" plus \"$delete\": true. An entry with no \"id\" and no \"$create\" is rejected the same way a block is - it has no \"id\"; add \"$create\": true to add it as a new one instead. Reorder with \"$personalitiesOrder\": the complete list of personality ids in the new order, the same way \"$blocksOrder\"/\"$itemsOrder\" work (see EDIT_BLOCKS_ORDER). The minimum of 2 personalities is checked against the result AFTER the merge, so a \"$delete\" that would leave fewer than 2 is rejected. The scores already stored on every answer item follow their personality BY IDENTITY, not by position: a personality that stays keeps its score wherever it ends up in the order, a deleted personality takes its scores with it, and a newly created personality starts at 0 on every existing answer item until you say otherwise - resend the affected blocks' \"items\" with their full \"scores\" arrays in the same call to set them yourself (that is applied after this and simply wins)."New value: +"Personality Test only. The personalities to change, add or remove - only the ones you touch, everything else stays as it is, merged entry-by-entry by \"id\" exactly like the Riddle's own \"blocks\" (see EDIT_BLOCKS). To EDIT, pass the personality's \"id\" (riddle_get reports it) plus only the properties that change. To ADD, pass \"$create\": true instead of an \"id\" plus everything a new personality needs (the same shape riddle_builder_personality takes). To REMOVE, pass \"id\" plus \"$delete\": true. An entry with no \"id\" and no \"$create\" is rejected the same way a block is - it has no \"id\"; add \"$create\": true to add it as a new one instead. The order of the personalities is NOT editable: there is no \"$personalitiesOrder\" (sending one is rejected) and, because this collection is merged by id, the order the entries are sent in has no meaning either - a \"$create\" is appended at the end and everything else keeps the place it has. Reorder them in the Creator if the order matters. The minimum of 2 personalities is checked against the result AFTER the merge, so a \"$delete\" that would leave fewer than 2 is rejected. The scores already stored on every answer item follow their personality BY IDENTITY, not by position: a personality that stays keeps its score, a deleted personality takes its scores with it, and a newly created personality starts at 0 on every existing answer item until you say otherwise - resend the affected blocks' \"items\" with their full \"scores\" arrays in the same call to set them yourself (that is applied after this and simply wins)."
    • changedInput schema / properties / build / properties / results / description
      Previous value: -"New result pages (Quiz), same shape as in riddle_builder_quiz. Replaces ALL current result pages with what you send, in the order you send it. Result pages are deliberately not editable and not reorderable: there is no \"$resultsOrder\" marker, no \"$create\"/\"$delete\" on an entry, and a page's \"id\" does not address it for a partial update - a score window, its blocks and the answers it reveals only make sense as one consistent set. Read them with riddle_get first and resend every page you want to keep, including its \"id\", which is honored to keep the page stable across the resend. Omit the field to keep all result pages untouched."New value: +"New result pages (Quiz), same shape as in riddle_builder_quiz. Replaces ALL current result pages with what you send, in the order you send it: result pages are deliberately neither editable per entry nor reorderable, so read them with riddle_get first and resend every page you want to keep, including its \"id\", which is honored to keep the page stable across the resend. Omit the field to keep all result pages untouched. Why, and which markers are rejected on a page: riddle://reference/concepts/result-pages."
    • changedInput schema / properties / omit / description
      Previous value: -"Leaves parts of the returned envelope out. Values: \"build\", \"warnings\", \"nextBlockId\", \"published\", \"context\" (whole sections) and \"build.omittedDefaults\" (the per-block maps of properties left at their default, inside every build config in the response). Omit for the whole envelope. \"uuid\"/\"type\"/\"modifiedAt\" are always returned. Reach for omit: [\"build.omittedDefaults\"] on almost every build - it drops ~85-90% of the read-back and loses nothing, since riddle://reference/riddle-builder/block-defaults states the same defaults; what you must not do either way is resend those values. When you leave anything out the response names it under \"omittedFields\", so a missing key never means the Riddle has none of it. Same parameter as riddle_get's."New value: +"Leaves parts of the returned envelope out. Values: \"build\", \"warnings\", \"nextBlockId\", \"published\", \"context\" (whole sections) and \"build.omittedDefaults\" (the per-block maps of properties left at their default, inside every build config in the response). Omit for the whole envelope. \"uuid\"/\"type\"/\"modifiedAt\" are always returned. Reach for omit: [\"build.omittedDefaults\"] on almost every build - it drops ~85-90% of the read-back and loses nothing, since riddle://reference/block-defaults/<block type> states the same defaults; what you must not do either way is resend those values. When you leave anything out the response names it under \"omittedFields\", so a missing key never means the Riddle has none of it. Same parameter as riddle_get's."
  3. First observed

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the sparse annotations (openWorldHint/idempotentHint/destructiveHint), the description discloses deep behavioral traits: omitted fields remain untouched, blocks merge by id while Placeholder conditions replace wholesale, deletes are rejected if still referenced, and a read-back can differ due to normalization. These details materially shape how an agent should form a request and interpret results. No contradiction with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence earns its place: core merge semantics are front-loaded, the block-edit grammar is condensed, prerequisites and exclusions follow, and the return format is stated last. Despite the density, the prose is structured and free of padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with nested objects, type-specific behaviors, and no output schema, the description covers prerequisites, input-shape provenance, restrictions, reference URLs, and return semantics. An agent has enough context to invoke it correctly and to know where to look for deeper details.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and each property is richly described, so the baseline is 3, but the top-level description adds cross-cutting meaning beyond the schema: the $create/$delete/$blocksOrder grammar common to blocks, items, fields, and personalities, and the merge-vs-wholesale-replacement distinction. It ties the schema fields together into one coherent model.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a precise action: 'Edits an existing Riddle of any type' using the same build configuration as riddle_builder_create, and immediately distinguishes it as a merge rather than a rebuild. This clearly identifies the tool as the update counterpart to the create sibling and removes ambiguity about its role.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit workflow instructions: read the Riddle with riddle_get first because its 'build' output is exactly the expected shape, and check context.origin.apiManageable beforehand. It also states a hard exclusion—only Riddles created by riddle_builder_* tools or the Riddle AI can be edited—while manual Creator Riddles are rejected, so the agent knows when not to invoke it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

TDQS

A4.4/5.0
Disambiguation5/5

Each tool is scoped to a distinct resource/action area: media, palettes, projects, question banks, Riddles, templates, tags, stats, and support. Potentially close pairs like riddle_tag/riddle_tag_delete and question_bank_delete/question_bank_manage are cleanly separated by their descriptions, so an agent can reliably select the right one.

Naming Consistency4/5

The naming is mostly consistent snake_case with strong resource prefixes like riddle_, question_bank_, and template_, followed by clear verbs. Minor deviations such as question_bank_item, riddle_tag, and stats_fetch break the strict verb-noun pattern but remain predictable once the convention is understood.

Tool Count3/5

At 38 tools this is a heavy surface, though the breadth is justified by the many subdomains the server covers: media, palettes, projects, question banks, Riddles, templates, tags, and stats. Most tools earn their place, but the count sits above the range where an agent can quickly survey all options.

Completeness4/5

The set covers the full lifecycle for Riddles, question banks, templates, and tags, including publish/unpublish, move, stats, and media upload/delete. Minor gaps like no media library listing and read-only project settings are workable because media IDs come from upload responses and project permissions are exposed.

Resources