Skip to main content
Glama

update_task

Destructive

Modifies an existing task (title, status, priority, complexity, labels, due date, the block it belongs to, ASSIGNEES). The completion date is set by the database: setting the status to done is enough, there is nothing to write. The response returns url, the DIRECT LINK to the task (the one the human follows). It is also the ONLY way to (un)assign a task: assignees REPLACES the whole list of assignees, and assignees: [] empties it. ⚠️ body and labels ALSO REPLACE what exists: a partial send overwrites the rest, with no signal and no way to recover it. appendBody APPENDS to a note: it ADDS the text at the end of the note (separated by a blank line) without ever overwriting it, atomically on the server side — incompatible with body in the same call, and the resulting note stays capped like body (named refusal otherwise). moveBefore / moveAfter (the id of a SIBLING task — same parentTaskId) place this task right before / after it in the backlog order, without changing its parent; mutually exclusive, refused in batch form, named refusals (target not found, the task itself, another level, no free slot). The response then carries moved (and unchanged: true if nothing needed to move). As with create_tasks, an assignment that will reach nobody can be DECLARED in unreachableAssignees + note (same two cases, same conditions), without ever being refused — assigning an external contact without an account remains perfectly normal. dependsOn ALSO REPLACES the whole list (same semantics as assignees/labels) — a dependency discovered afterwards is added here, create_tasks.dependsOn applying only at creation. Linking parentTaskId to an ARCHIVED user story (US) is never refused — the response SAYS so via archivedParents + archivedParentsNote (create_tasks pattern). taskId ALSO accepts an ARRAY (up to 100): the SAME patch is then applied to each task, each one INDEPENDENTLY — an id not found never prevents the others from succeeding, and the response carries succeeded/failed (the findings above go down PER task into succeeded) instead of the flat fields of the single action, plus batchUrl: ONE link to the tasks updated successfully (batchTitle = the sentence of the banner). ⚠️ arbitrage and arbitrageAction are REFUSED in batch form — they are state transitions PER task: they take ONE single taskId. The same goes for moveBefore/moveAfter (one target, one place). appendBody applies, on the other hand, to EACH task of the batch. DELIVERABLES: addLinks ADDS (without replacing — the deliverables of other agents do not move) and removeLinks REMOVES, one by one, by id or key; 20 at most per task. The key is STABLE and state carries the TRUE state: replaying the same addition does not duplicate, it updates the entry (a PR open becomes merged). The state is the one YOU declare — OrgGen never queries it, the human reads "declared by the agent"; "verified" is a human action. The response carries links (what was added, updated, removed, and the total). In batch form, applied to EACH task, independently.

Input Schema

NameRequiredDescriptionDefault
bodyNoREPLACES the WHOLE note — it is NOT an addition to the existing text. `appendBody` APPENDS to a note (atomic append, without overwriting). `null` clears the note; the OMITTED field touches nothing. Incompatible with `appendBody`.
dueOnNo
titleNo
cellIdNo
labelsNoREPLACES the whole list of labels — same semantics as `assignees`, it is NOT an addition. `[]` removes them all; the OMITTED field touches nothing.
statusNo
taskIdYesONE identifier, or UP TO 100 (array) — the SAME patch is then applied to each task, INDEPENDENTLY: an id not found never prevents the others from succeeding, and the response carries `succeeded`/`failed` instead of the flat fields of the single action. `arbitrage` and `arbitrageAction` are REFUSED in batch form (state transition PER task) — they apply one identifier at a time.
dueTextNo
addLinksNoADDS deliverables to the task (at most 20 per call, and 20 per task in total) — it never REPLACES the list: those of other agents do not move. Idempotent: the same `key` (otherwise the same URL, otherwise the same `(type, ref)`) updates the entry instead of duplicating it. The `key` is stable and `state` carries the TRUE state. In batch form (`taskId` array), applied to EACH task, independently.
executorNoWHO is expected to DO the task: `agent` (an AI agent may take it) or `human` (a person must do it — an agent does not claim it and `list_tasks({executable:true})` leaves it out). This is an instruction, not an identity: it does not say who is ASSIGNED. `null` clears it back to unspecified; omitted = unchanged.
priorityNo
arbitrageNoTurns an ORDINARY task into an ARBITRATION — REFUSED if it already carries one (it then evolves via `arbitrageAction`, not by rewriting this field). A task that has a `cellId` keeps it; without a block, it TAKES the one of its parent task (`inheritedCellId` in the response), otherwise it becomes an arbitration WITHOUT A SUBJECT — visible in the Arbitrations tab, on no card of the canvas — and the response says so (`arbitrageWithoutBlock`). Incompatible with any other field of this call, `arbitrageAction` included.
assigneesNoREPLACES the WHOLE list of assignees — same semantics as `labels`, it is NOT an addition to the existing list. `[]` UNASSIGNS everyone; the OMITTED field touches nothing (the current assignees stay). An identifier or a name of a person of the project is RESOLVED; any other string is kept as is as an unresolved designation, not discarded.
dependsOnNoREPLACES the WHOLE list of dependencies — same semantics as `labels`, it is NOT an addition to the existing list. `[]` removes all dependencies; the OMITTED field touches nothing. Each id must exist in this project.
moveAfterNoPlaces this task RIGHT AFTER the named task in the backlog order — same rules as `moveBefore` (exclusive of it, same parent, refused in batch form).
appendBodyNoADDS this text at the end of the existing note, separated by ONE blank line; the existing note is never overwritten (unlike `body`). Note absent or empty: the text becomes the note. The RESULTING note is capped at 20000 characters (named refusal otherwise, note unchanged). LEADING and trailing spaces of the text are removed (a leading indentation does not survive: a note that depends on one is written with `body`). INCOMPATIBLE with `body` in the same call. In batch form (`taskId` array), applied to EACH task, independently.
batchTitleNoBATCH form (`taskId` as an array, at least two tasks updated): the sentence the view banner will display when the human opens `batchUrl`. Changes nothing about the update. Maximum 120 characters.
claimTokenNoThe token of YOUR claim (returned by `claim_task`) — REQUIRED to write to a task a lease holds: without it, the refusal is `CLAIM_HELD`; a stale token gives `CLAIM_LOST`. A SECRET that stays out of every written text. Any write that carries it extends the lease without touching the declared progress; the end of the task (`done`, archiving, back to `todo`) releases the claim. On a task nobody holds, the field stays empty.
complexityNoRELATIVE order of magnitude in HUMAN TIME: xs = under an hour · s = a few hours · m = half a day to a day · l = a few days · xl = to SPLIT. It is estimated ahead of the pick-up of the work; it is an estimate, not a promise. No value = not estimated. `null` clears the estimate; the OMITTED field touches nothing.
moveBeforeNoPlaces this task immediately ahead of the named task in the backlog order. The target must have the SAME `parentTaskId` (US among USs, subtask among the subtasks of the same parent) — this action never changes the parent. Exclusive of `moveAfter`, refused in batch form; named refusal if the target is not found, is the task itself or has no free slot.
removeLinksNoREMOVES deliverables, each designated by its `id` OR its `key`. Idempotent: a deliverable already removed or never added is not an error (the response lists it in `notFound`). Removals run ahead of the additions of the same call.
parentTaskIdNoLinks this task to its parent grouping ("Part of": a user story (US), another task WITHOUT `parentTaskId`), or DETACHES it. The epic is the BLOCK (`cellId`), not the parent task. `null` = becomes a US again (distinct from the OMITTED field, which touches nothing — unlike `assignees`, an array where `[]` already plays that role). Same depth constraint as at creation: refused if the target is already a subtask, or if this task itself already has subtasks (linking would produce three levels).
arbitrageActionNoAdvances an ARBITRATION task. `start`/`close`/`repropose`/`moot`/`clarify`/`record_external_decision` — not `validate`/`choose`/`contest`, which are reserved to the human through the interface. `clarify` answers "I need more explanation" (polled by `list_tasks({ awaitingClarification: true })`). Incompatible with any other field of this call.
expectedProjectIdNoUUID of the project targeted by THIS call. ACTUALLY targets this project instead of the session project. Refused without changing anything if access is not granted.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedInput schema / properties / executor
      Added value: +{
      +  "anyOf": [
      +    {
      +      "enum": [
      +        "agent",
      +        "human"
      +      ],
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "WHO is expected to DO the task: `agent` (an AI agent may take it) or `human` (a person must do it — an agent does not claim it and `list_tasks({executable:true})` leaves it out). This is an instruction, not an identity: it does not say who is ASSIGNED. `null` clears it back to unspecified; omitted = unchanged."
      +}
  2. Changed1 schema field changed
    • addedInput schema / properties / claimToken
      Added value: +{
      +  "description": "The token of YOUR claim (returned by `claim_task`) — REQUIRED to write to a task a lease holds: without it, the refusal is `CLAIM_HELD`; a stale token gives `CLAIM_LOST`. A SECRET that stays out of every written text. Any write that carries it extends the lease without touching the declared progress; the end of the task (`done`, archiving, back to `todo`) releases the claim. On a task nobody holds, the field stays empty.",
      +  "maxLength": 200,
      +  "minLength": 8,
      +  "type": "string"
      +}
  3. Changed31 schema fields changed
    • changedInput schema / properties / addLinks / description
      Previous value: -"AJOUTE des livrables à la tâche (au plus 20 par appel, et 20 par tâche au total) — jamais un remplacement : ceux des autres agents ne bougent pas. Idempotent : le même `key` (sinon la même URL, sinon le même `(type, ref)`) met l’entrée à jour au lieu de la dupliquer. La `key` est stable et `state` porte l’état VRAI. Sous forme lot (`taskId` tableau), appliqué à CHAQUE tâche, indépendamment."New value: +"ADDS deliverables to the task (at most 20 per call, and 20 per task in total) — it never REPLACES the list: those of other agents do not move. Idempotent: the same `key` (otherwise the same URL, otherwise the same `(type, ref)`) updates the entry instead of duplicating it. The `key` is stable and `state` carries the TRUE state. In batch form (`taskId` array), applied to EACH task, independently."
    • changedInput schema / properties / addLinks / items / properties / documentId / description
      Previous value: -"Pour le type `document` SEUL : l’identifiant d’un document du projet que TU peux lire (`list_documents`)."New value: +"For the `document` type ONLY: the identifier of a document of the project that YOU can read (`list_documents`)."
    • changedInput schema / properties / addLinks / items / properties / key / description
      Previous value: -"Ta clé STABLE pour ce livrable (ex. `pr-482`) : rejouer un ajout avec la même clé ne le duplique pas, il le MET À JOUR (c’est ainsi que tu passes une PR de `open` à `merged` : une `key` et un `state` suffisent alors, sans répéter l’URL). Sans clé, l’URL (normalisée), puis `(type, ref)`, désignent l’entrée."New value: +"Your STABLE key for this deliverable (e.g. `pr-482`): replaying an addition with the same key does not duplicate it, it UPDATES it (this is how you move a PR from `open` to `merged`: a `key` and a `state` are then enough, without repeating the URL). Without a key, the URL (normalized), then `(type, ref)`, designate the entry."
    • changedInput schema / properties / addLinks / items / properties / label / description
      Previous value: -"Libellé court affiché."New value: +"Short displayed label."
    • changedInput schema / properties / addLinks / items / properties / ref / description
      Previous value: -"Référence courte affichée en monospace (sha, numéro de PR, identifiant de run)."New value: +"Short reference displayed in monospace (sha, PR number, run identifier)."
    • changedInput schema / properties / addLinks / items / properties / state / description
      Previous value: -"L’état que TU DÉCLARES, vrai au moment de l’appel — OrgGen ne le vérifie jamais, l’humain voit « déclaré par l’agent »."New value: +"The state YOU DECLARE, true at the time of the call — OrgGen never verifies it, the human sees \"declared by the agent\"."
    • changedInput schema / properties / addLinks / items / properties / type / description
      Previous value: -"Le genre de livrable — énumération fermée."New value: +"The kind of deliverable — closed enumeration."
    • changedInput schema / properties / addLinks / items / properties / url / description
      Previous value: -"Adresse http(s) ABSOLUE, sans identifiant ni mot de passe intégrés. OrgGen ne l’ouvre jamais : elle n’est qu’affichée."New value: +"ABSOLUTE http(s) address, without embedded username or password. OrgGen never opens it: it is only displayed."
    • changedInput schema / properties / appendBody / description
      Previous value: -"AJOUTE ce texte à la fin de la note existante, séparé par UNE ligne vide ; la note existante n’est jamais écrasée (à l’inverse de `body`). Note absente ou vide : le texte devient la note. La note RÉSULTANTE est plafonnée à 20000 caractères (refus nommé sinon, note inchangée). Les espaces de DÉBUT et de fin du texte sont retirés (une indentation de tête ne survit pas : une note qui en dépend s’écrit avec `body`). INCOMPATIBLE avec `body` dans le même appel. Sous forme lot (`taskId` tableau), appliqué à CHAQUE tâche, indépendamment."New value: +"ADDS this text at the end of the existing note, separated by ONE blank line; the existing note is never overwritten (unlike `body`). Note absent or empty: the text becomes the note. The RESULTING note is capped at 20000 characters (named refusal otherwise, note unchanged). LEADING and trailing spaces of the text are removed (a leading indentation does not survive: a note that depends on one is written with `body`). INCOMPATIBLE with `body` in the same call. In batch form (`taskId` array), applied to EACH task, independently."
    • changedInput schema / properties / arbitrage / description
      Previous value: -"Transforme une tâche ORDINAIRE en ARBITRAGE — REFUSÉ si elle en porte déjà un (il évolue alors via `arbitrageAction`, jamais en réécrivant ce champ). Une tâche qui a un `cellId` le garde ; sans bloc, elle REPREND celui de sa tâche parente (`inheritedCellId` dans la réponse), sinon elle devient un arbitrage SANS SUJET — visible dans l’onglet Arbitrages, sur aucune carte du canevas — et la réponse le dit (`arbitrageWithoutBlock`). Incompatible avec tout autre champ de cet appel, `arbitrageAction` compris."New value: +"Turns an ORDINARY task into an ARBITRATION — REFUSED if it already carries one (it then evolves via `arbitrageAction`, not by rewriting this field). A task that has a `cellId` keeps it; without a block, it TAKES the one of its parent task (`inheritedCellId` in the response), otherwise it becomes an arbitration WITHOUT A SUBJECT — visible in the Arbitrations tab, on no card of the canvas — and the response says so (`arbitrageWithoutBlock`). Incompatible with any other field of this call, `arbitrageAction` included."
    • changedInput schema / properties / arbitrage / properties / options / description
      Previous value: -"Les réponses PRÉ-DÉFINIES — au moins deux, sinon il n’y a rien à choisir."New value: +"The PRE-DEFINED answers — at least two, otherwise there is nothing to choose."
    • changedInput schema / properties / arbitrage / properties / options / items / properties / id / description
      Previous value: -"Identifiant COURT de l’option — cité par `choose`, jamais affiché seul."New value: +"SHORT identifier of the option — cited by `choose`, and not displayed on its own."
    • changedInput schema / properties / arbitrage / properties / options / items / properties / label / description
      Previous value: -"Le texte de la réponse proposée."New value: +"The text of the proposed answer."
    • changedInput schema / properties / arbitrage / properties / options / items / properties / recommended / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "justification": {
      -        "description": "Pourquoi cette option est recommandée — affichée à côté d’elle.",
      -        "maxLength": 1000,
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "justification"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "justification": {
      +        "description": "Why this option is recommended — displayed next to it.",
      +        "maxLength": 1000,
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "justification"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / properties / arbitrage / properties / options / items / properties / recommended / description
      Previous value: -"Marque CETTE option comme la recommandation de l’agent. Omis/`null` = aucune recommandation sur cette option (le cas normal)."New value: +"Marks THIS option as the agent's recommendation. Omitted/`null` = no recommendation on this option (the normal case)."
    • changedInput schema / properties / arbitrage / properties / question / description
      Previous value: -"La question posée à l’humain."New value: +"The question posed to the human."
    • changedInput schema / properties / arbitrage / properties / selectionMode / description
      Previous value: -"Le mode de sélection humaine — `single` (une seule option, le défaut) ou `multiple` (cases à cocher, plusieurs options possibles). Posé une fois, jamais changé ensuite."New value: +"The human selection mode — `single` (one option only, the default) or `multiple` (checkboxes, several options possible). Set once and fixed afterwards."
    • changedInput schema / properties / arbitrageAction / description
      Previous value: -"Fait avancer une tâche d’ARBITRAGE. `start`/`close`/`repropose`/`moot`/`clarify`/`record_external_decision` — jamais `validate`/`choose`/`contest`, réservés à l’humain via l’interface. `clarify` répond à « il me faut plus d’explications » (relevé par `list_tasks({ awaitingClarification: true })`). Incompatible avec tout autre champ de cet appel."New value: +"Advances an ARBITRATION task. `start`/`close`/`repropose`/`moot`/`clarify`/`record_external_decision` — not `validate`/`choose`/`contest`, which are reserved to the human through the interface. `clarify` answers \"I need more explanation\" (polled by `list_tasks({ awaitingClarification: true })`). Incompatible with any other field of this call."
    • changedInput schema / properties / arbitrageAction / oneOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "type": {
      -        "const": "start",
      -        "description": "Démarre le travail — exige l’étape « arbitre ».",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "ref": {
      -        "anyOf": [
      -          {
      -            "maxLength": 500,
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Un pointeur optionnel vers le résultat (id de bloc, de version…)."
      -      },
      -      "summary": {
      -        "description": "La PREUVE de clôture — ce qui a été fait, en une phrase.",
      -        "maxLength": 2000,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "close",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "summary"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "Reformule la question après une contestation — exige l’étape « conteste ».",
      -    "properties": {
      -      "options": {
      -        "description": "Les réponses PRÉ-DÉFINIES — au moins deux, sinon il n’y a rien à choisir.",
      -        "items": {
      -          "additionalProperties": false,
      -          "properties": {
      -            "id": {
      -              "description": "Identifiant COURT de l’option — cité par `choose`, jamais affiché seul.",
      -              "maxLength": 100,
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "label": {
      -              "description": "Le texte de la réponse proposée.",
      -              "maxLength": 300,
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "recommended": {
      -              "anyOf": [
      -                {
      -                  "additionalProperties": false,
      -                  "properties": {
      -                    "justification": {
      -                      "description": "Pourquoi cette option est recommandée — affichée à côté d’elle.",
      -                      "maxLength": 1000,
      -                      "minLength": 1,
      -                      "type": "string"
      -                    }
      -                  },
      -                  "required": [
      -                    "justification"
      -                  ],
      -                  "type": "object"
      -                },
      -                {
      -                  "type": "null"
      -                }
      -              ],
      -              "description": "Marque CETTE option comme la recommandation de l’agent. Omis/`null` = aucune recommandation sur cette option (le cas normal)."
      -            }
      -          },
      -          "required": [
      -            "id",
      -            "label"
      -          ],
      -          "type": "object"
      -        },
      -        "maxItems": 8,
      -        "minItems": 2,
      -        "type": "array"
      -      },
      -      "question": {
      -        "description": "La question posée à l’humain.",
      -        "maxLength": 2000,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "repropose",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "question",
      -      "options"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "type": {
      -        "const": "moot",
      -        "description": "Rend l’arbitrage caduc — la question ne se pose plus.",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "Répond à « il me faut plus d’explications » (`needsMoreInfo`) : pose l’explication et lève la demande, SANS changer d’étape — l’humain tranche ensuite. Exige l’étape « propose » ET une demande en attente.",
      -    "properties": {
      -      "explanation": {
      -        "description": "L’explication demandée : courte, accessible, avec de la hauteur (le pourquoi, ce que chaque option change concrètement) — jamais un renvoi vers un document.",
      -        "maxLength": 2000,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "clarify",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "explanation"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "Cède le travail quand un humain a demandé de RECONSIDÉRER la décision (`reconsider.status: \"requested\"`) : la décision revient à « propose », l’historique la garde. Exige que la demande te soit adressée.",
      -    "properties": {
      -      "type": {
      -        "const": "yield",
      -        "type": "string"
      -      },
      -      "workSummary": {
      -        "description": "Ce qui a été FAIT avant de céder (livrables, état du travail) — obligatoire, jamais « rien ».",
      -        "maxLength": 2000,
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "workSummary"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "Refuse de céder quand un humain a demandé de reconsidérer : la décision et le travail restent, ta justification est montrée à l’humain. Exige que la demande te soit adressée.",
      -    "properties": {
      -      "justification": {
      -        "description": "Pourquoi tu poursuis malgré la demande — lue par l’humain qui l’a faite.",
      -        "maxLength": 2000,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "declineReconsider",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "justification"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "Enregistre une décision prise HORS du panneau (conversation, document) avec sa preuve — clôt le cycle directement, sans jamais passer par « arbitre »/« en_cours ». N’existe QUE depuis « propose » : une question qui progresse normalement n’a rien à enregistrer ici.",
      -    "properties": {
      -      "decidedAt": {
      -        "description": "La date RÉELLE de la décision — pas celle de cet appel.",
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "source": {
      -        "description": "Où la décision a été prise (canal, document, réunion…).",
      -        "maxLength": 300,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "record_external_decision",
      -        "type": "string"
      -      },
      -      "verbatim": {
      -        "description": "La CITATION de ce qui a été décidé — pas un résumé, le verbatim.",
      -        "maxLength": 2000,
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "verbatim",
      -      "source",
      -      "decidedAt"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "type": {
      +        "const": "start",
      +        "description": "Starts the work — requires the `arbitre` step.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "ref": {
      +        "anyOf": [
      +          {
      +            "maxLength": 500,
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "An optional pointer to the result (block id, version id…)."
      +      },
      +      "summary": {
      +        "description": "The PROOF of completion — what was done, in one sentence.",
      +        "maxLength": 2000,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "close",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "summary"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "Rewords the question after a challenge — requires the `conteste` step.",
      +    "properties": {
      +      "options": {
      +        "description": "The PRE-DEFINED answers — at least two, otherwise there is nothing to choose.",
      +        "items": {
      +          "additionalProperties": false,
      +          "properties": {
      +            "id": {
      +              "description": "SHORT identifier of the option — cited by `choose`, and not displayed on its own.",
      +              "maxLength": 100,
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "label": {
      +              "description": "The text of the proposed answer.",
      +              "maxLength": 300,
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "recommended": {
      +              "anyOf": [
      +                {
      +                  "additionalProperties": false,
      +                  "properties": {
      +                    "justification": {
      +                      "description": "Why this option is recommended — displayed next to it.",
      +                      "maxLength": 1000,
      +                      "minLength": 1,
      +                      "type": "string"
      +                    }
      +                  },
      +                  "required": [
      +                    "justification"
      +                  ],
      +                  "type": "object"
      +                },
      +                {
      +                  "type": "null"
      +                }
      +              ],
      +              "description": "Marks THIS option as the agent's recommendation. Omitted/`null` = no recommendation on this option (the normal case)."
      +            }
      +          },
      +          "required": [
      +            "id",
      +            "label"
      +          ],
      +          "type": "object"
      +        },
      +        "maxItems": 8,
      +        "minItems": 2,
      +        "type": "array"
      +      },
      +      "question": {
      +        "description": "The question posed to the human.",
      +        "maxLength": 2000,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "repropose",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "question",
      +      "options"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "type": {
      +        "const": "moot",
      +        "description": "Makes the arbitration obsolete — the question no longer applies.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "Answers \"I need more explanation\" (`needsMoreInfo`): posts the explanation and lifts the request, WITHOUT changing step — the human then decides. Requires the `propose` step AND a pending request.",
      +    "properties": {
      +      "explanation": {
      +        "description": "The requested explanation: short, accessible, with some perspective (the why, what each option concretely changes) — not a pointer to a document.",
      +        "maxLength": 2000,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "clarify",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "explanation"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "Hands back the work when a human asked to RECONSIDER the decision (`reconsider.status: \"requested\"`): the decision goes back to `propose`, the history keeps it. Requires the request to be addressed to you.",
      +    "properties": {
      +      "type": {
      +        "const": "yield",
      +        "type": "string"
      +      },
      +      "workSummary": {
      +        "description": "What was DONE before handing back (deliverables, state of the work) — required, and not \"nothing\".",
      +        "maxLength": 2000,
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "workSummary"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "Refuses to hand back when a human asked to reconsider: the decision and the work stay, your justification is shown to the human. Requires the request to be addressed to you.",
      +    "properties": {
      +      "justification": {
      +        "description": "Why you carry on despite the request — read by the human who made it.",
      +        "maxLength": 2000,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "declineReconsider",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "justification"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "Records a decision made OUTSIDE the panel (conversation, document) with its proof — closes the cycle directly, without going through `arbitre`/`en_cours`. Exists ONLY from `propose`: a question that progresses normally has nothing to record here.",
      +    "properties": {
      +      "decidedAt": {
      +        "description": "The ACTUAL date of the decision — not the date of this call.",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "source": {
      +        "description": "Where the decision was made (channel, document, meeting…).",
      +        "maxLength": 300,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "record_external_decision",
      +        "type": "string"
      +      },
      +      "verbatim": {
      +        "description": "The QUOTE of what was decided — not a summary, the verbatim.",
      +        "maxLength": 2000,
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "verbatim",
      +      "source",
      +      "decidedAt"
      +    ],
      +    "type": "object"
      +  }
      +]
    • changedInput schema / properties / assignees / description
      Previous value: -"REMPLACE la liste ENTIÈRE des responsables — même sémantique que `labels`, ce n’est PAS un ajout à la liste existante. `[]` DÉSASSIGNE tout le monde ; le champ OMIS ne touche à rien (les responsables actuels restent). Un identifiant ou un nom de personne du projet est RÉSOLU ; toute autre chaîne est conservée telle quelle comme désignation non résolue — jamais jetée."New value: +"REPLACES the WHOLE list of assignees — same semantics as `labels`, it is NOT an addition to the existing list. `[]` UNASSIGNS everyone; the OMITTED field touches nothing (the current assignees stay). An identifier or a name of a person of the project is RESOLVED; any other string is kept as is as an unresolved designation, not discarded."
    • changedInput schema / properties / batchTitle / description
      Previous value: -"Forme LOT (`taskId` en tableau, au moins deux tâches mises à jour) : la phrase que le bandeau de la vue affichera quand l’humain ouvre `batchUrl`. Ne change rien à la mise à jour. Maximum 120 caractères."New value: +"BATCH form (`taskId` as an array, at least two tasks updated): the sentence the view banner will display when the human opens `batchUrl`. Changes nothing about the update. Maximum 120 characters."
    • changedInput schema / properties / body / description
      Previous value: -"REMPLACE la note ENTIÈRE — ce n’est PAS un ajout au texte existant. `appendBody` COMPLÈTE une note (ajout atomique, sans jamais écraser). `null` efface la note ; le champ OMIS ne touche à rien. Incompatible avec `appendBody`."New value: +"REPLACES the WHOLE note — it is NOT an addition to the existing text. `appendBody` APPENDS to a note (atomic append, without overwriting). `null` clears the note; the OMITTED field touches nothing. Incompatible with `appendBody`."
    • changedInput schema / properties / complexity / description
      Previous value: -"Ordre de grandeur RELATIF en TEMPS HUMAIN : xs = moins d’une heure · s = quelques heures · m = une demi-journée à un jour · l = quelques jours · xl = à DÉCOUPER. Elle s’estime AVANT la prise du travail ; c’est une estimation, jamais une promesse. Sans valeur = non estimée. `null` efface l’estimation ; le champ OMIS ne touche à rien."New value: +"RELATIVE order of magnitude in HUMAN TIME: xs = under an hour · s = a few hours · m = half a day to a day · l = a few days · xl = to SPLIT. It is estimated ahead of the pick-up of the work; it is an estimate, not a promise. No value = not estimated. `null` clears the estimate; the OMITTED field touches nothing."
    • changedInput schema / properties / dependsOn / description
      Previous value: -"REMPLACE la liste ENTIÈRE des dépendances — même sémantique que `labels`, ce n'est PAS un ajout à la liste existante. `[]` retire toutes les dépendances ; le champ OMIS ne touche à rien. Chaque id doit exister dans ce projet."New value: +"REPLACES the WHOLE list of dependencies — same semantics as `labels`, it is NOT an addition to the existing list. `[]` removes all dependencies; the OMITTED field touches nothing. Each id must exist in this project."
    • changedInput schema / properties / expectedProjectId / description
      Previous value: -"UUID du projet visé par CET appel. Cible RÉELLEMENT ce projet au lieu du projet de session. Refusé sans rien modifier si l'accès n'est pas accordé."New value: +"UUID of the project targeted by THIS call. ACTUALLY targets this project instead of the session project. Refused without changing anything if access is not granted."
    • changedInput schema / properties / labels / description
      Previous value: -"REMPLACE la liste entière des étiquettes — même sémantique que `assignees`, ce n’est PAS un ajout. `[]` les retire toutes ; le champ OMIS ne touche à rien."New value: +"REPLACES the whole list of labels — same semantics as `assignees`, it is NOT an addition. `[]` removes them all; the OMITTED field touches nothing."
    • changedInput schema / properties / moveAfter / description
      Previous value: -"Place cette tâche JUSTE APRÈS la tâche nommée dans l’ordre du backlog — mêmes règles que `moveBefore` (exclusif de lui, même parent, refusé sous forme lot)."New value: +"Places this task RIGHT AFTER the named task in the backlog order — same rules as `moveBefore` (exclusive of it, same parent, refused in batch form)."
    • changedInput schema / properties / moveBefore / description
      Previous value: -"Place cette tâche JUSTE AVANT la tâche nommée dans l’ordre du backlog. La cible doit avoir le MÊME `parentTaskId` (US parmi les US, sous-tâche parmi les sous-tâches du même parent) — ce geste ne change jamais le parent. Exclusif de `moveAfter`, refusé sous forme lot ; refus nommé si la cible est introuvable, est la tâche elle-même ou n’a pas de place libre."New value: +"Places this task immediately ahead of the named task in the backlog order. The target must have the SAME `parentTaskId` (US among USs, subtask among the subtasks of the same parent) — this action never changes the parent. Exclusive of `moveAfter`, refused in batch form; named refusal if the target is not found, is the task itself or has no free slot."
    • changedInput schema / properties / parentTaskId / description
      Previous value: -"Rattache cette tâche à son regroupement parent (« Fait partie de » : une US, une autre tâche SANS `parentTaskId`), ou DÉTACHE-la. L’Épique est le BLOC (`cellId`), jamais la tâche parente. `null` = redevient une US (distinct du champ OMIS, qui ne touche à rien — à la différence de `assignees`, un tableau où `[]` joue déjà ce rôle). Même contrainte de profondeur qu’à la création : refusé si la cible est déjà une sous-tâche, ou si cette tâche a elle-même déjà des sous-tâches (le rattachement produirait trois niveaux)."New value: +"Links this task to its parent grouping (\"Part of\": a user story (US), another task WITHOUT `parentTaskId`), or DETACHES it. The epic is the BLOCK (`cellId`), not the parent task. `null` = becomes a US again (distinct from the OMITTED field, which touches nothing — unlike `assignees`, an array where `[]` already plays that role). Same depth constraint as at creation: refused if the target is already a subtask, or if this task itself already has subtasks (linking would produce three levels)."
    • changedInput schema / properties / removeLinks / description
      Previous value: -"RETIRE des livrables, chacun désigné par son `id` OU sa `key`. Idempotent : un livrable déjà retiré ou jamais ajouté n’est pas une erreur (la réponse le liste dans `notFound`). Les retraits passent AVANT les ajouts du même appel."New value: +"REMOVES deliverables, each designated by its `id` OR its `key`. Idempotent: a deliverable already removed or never added is not an error (the response lists it in `notFound`). Removals run ahead of the additions of the same call."
    • changedInput schema / properties / taskId / description
      Previous value: -"UN identifiant, ou JUSQU’À 100 (tableau) — le MÊME patch est alors appliqué à chaque tâche, INDÉPENDAMMENT : un id introuvable n’empêche jamais les autres d’aboutir, et la réponse porte `succeeded`/`failed` au lieu des champs plats du geste unitaire. `arbitrage` et `arbitrageAction` sont REFUSÉS sous forme lot (transition d’état PAR tâche) — ils s’appliquent un identifiant à la fois."New value: +"ONE identifier, or UP TO 100 (array) — the SAME patch is then applied to each task, INDEPENDENTLY: an id not found never prevents the others from succeeding, and the response carries `succeeded`/`failed` instead of the flat fields of the single action. `arbitrage` and `arbitrageAction` are REFUSED in batch form (state transition PER task) — they apply one identifier at a time."
  4. Changed6 schema fields changed
    • changedInput schema / properties / addLinks / description
      Previous value: -"AJOUTE des livrables à la tâche (au plus 20 par appel, et 20 par tâche au total) — jamais un remplacement : ceux des autres agents ne bougent pas. Idempotent : le même `key` (sinon la même URL, sinon le même `(type, ref)`) met l’entrée à jour au lieu de la dupliquer. Fournis une `key` stable et l’état VRAI (`state`). Sous forme lot (`taskId` tableau), appliqué à CHAQUE tâche, indépendamment."New value: +"AJOUTE des livrables à la tâche (au plus 20 par appel, et 20 par tâche au total) — jamais un remplacement : ceux des autres agents ne bougent pas. Idempotent : le même `key` (sinon la même URL, sinon le même `(type, ref)`) met l’entrée à jour au lieu de la dupliquer. La `key` est stable et `state` porte l’état VRAI. Sous forme lot (`taskId` tableau), appliqué à CHAQUE tâche, indépendamment."
    • changedInput schema / properties / appendBody / description
      Previous value: -"AJOUTE ce texte à la fin de la note existante, séparé par UNE ligne vide — ne l’écrase JAMAIS (à l’inverse de `body`). Note absente ou vide : le texte devient la note. La note RÉSULTANTE est plafonnée à 20000 caractères (refus nommé sinon, note inchangée). Les espaces de DÉBUT et de fin du texte sont retirés (une indentation de tête ne survit pas : pour une note qui en dépend, utilise `body`). INCOMPATIBLE avec `body` dans le même appel. Sous forme lot (`taskId` tableau), appliqué à CHAQUE tâche, indépendamment."New value: +"AJOUTE ce texte à la fin de la note existante, séparé par UNE ligne vide ; la note existante n’est jamais écrasée (à l’inverse de `body`). Note absente ou vide : le texte devient la note. La note RÉSULTANTE est plafonnée à 20000 caractères (refus nommé sinon, note inchangée). Les espaces de DÉBUT et de fin du texte sont retirés (une indentation de tête ne survit pas : une note qui en dépend s’écrit avec `body`). INCOMPATIBLE avec `body` dans le même appel. Sous forme lot (`taskId` tableau), appliqué à CHAQUE tâche, indépendamment."
    • changedInput schema / properties / arbitrage / description
      Previous value: -"Transforme une tâche ORDINAIRE en ARBITRAGE — REFUSÉ si elle en porte déjà un (fais-le évoluer via `arbitrageAction` à la place, jamais en réécrivant ce champ). Une tâche qui a un `cellId` le garde ; sans bloc, elle REPREND celui de sa tâche parente (`inheritedCellId` dans la réponse), sinon elle devient un arbitrage SANS SUJET — visible dans l’onglet Arbitrages, sur aucune carte du canevas — et la réponse le dit (`arbitrageWithoutBlock`). Incompatible avec tout autre champ de cet appel, `arbitrageAction` compris."New value: +"Transforme une tâche ORDINAIRE en ARBITRAGE — REFUSÉ si elle en porte déjà un (il évolue alors via `arbitrageAction`, jamais en réécrivant ce champ). Une tâche qui a un `cellId` le garde ; sans bloc, elle REPREND celui de sa tâche parente (`inheritedCellId` dans la réponse), sinon elle devient un arbitrage SANS SUJET — visible dans l’onglet Arbitrages, sur aucune carte du canevas — et la réponse le dit (`arbitrageWithoutBlock`). Incompatible avec tout autre champ de cet appel, `arbitrageAction` compris."
    • changedInput schema / properties / body / description
      Previous value: -"REMPLACE la note ENTIÈRE — ce n’est PAS un ajout au texte existant. Pour COMPLÉTER une note, utilise `appendBody` (ajout atomique, sans jamais écraser). `null` efface la note ; le champ OMIS ne touche à rien. Incompatible avec `appendBody`."New value: +"REMPLACE la note ENTIÈRE — ce n’est PAS un ajout au texte existant. `appendBody` COMPLÈTE une note (ajout atomique, sans jamais écraser). `null` efface la note ; le champ OMIS ne touche à rien. Incompatible avec `appendBody`."
    • changedInput schema / properties / complexity / description
      Previous value: -"Ordre de grandeur RELATIF en TEMPS HUMAIN : xs = moins d’une heure · s = quelques heures · m = une demi-journée à un jour · l = quelques jours · xl = à DÉCOUPER. Pose-la AVANT la prise du travail ; c’est une estimation, jamais une promesse. Sans valeur = non estimée. `null` efface l’estimation ; le champ OMIS ne touche à rien."New value: +"Ordre de grandeur RELATIF en TEMPS HUMAIN : xs = moins d’une heure · s = quelques heures · m = une demi-journée à un jour · l = quelques jours · xl = à DÉCOUPER. Elle s’estime AVANT la prise du travail ; c’est une estimation, jamais une promesse. Sans valeur = non estimée. `null` efface l’estimation ; le champ OMIS ne touche à rien."
    • changedInput schema / properties / taskId / description
      Previous value: -"UN identifiant, ou JUSQU’À 100 (tableau) — le MÊME patch est alors appliqué à chaque tâche, INDÉPENDAMMENT : un id introuvable n’empêche jamais les autres d’aboutir, et la réponse porte `succeeded`/`failed` au lieu des champs plats du geste unitaire. `arbitrage` et `arbitrageAction` sont REFUSÉS sous forme lot (transition d’état PAR tâche) — appelle-les un identifiant à la fois."New value: +"UN identifiant, ou JUSQU’À 100 (tableau) — le MÊME patch est alors appliqué à chaque tâche, INDÉPENDAMMENT : un id introuvable n’empêche jamais les autres d’aboutir, et la réponse porte `succeeded`/`failed` au lieu des champs plats du geste unitaire. `arbitrage` et `arbitrageAction` sont REFUSÉS sous forme lot (transition d’état PAR tâche) — ils s’appliquent un identifiant à la fois."
  5. First observed

TDQS

A4.5/5.0
Behavior5/5

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

Beyond the annotations, the description discloses exactly what is destructive: `body`, `labels`, `assignees`, and `dependsOn` replace existing data, with partial sends overwriting the rest and 'no way to recover it.' It also explains batched independent failures, `appendBody` atomic append behavior, claim-token requirements (`CLAIM_HELD`/`CLAIM_LOST`), archived-parent behavior, and deliverables state semantics. This is unusually rich behavioral context for a destructive mutation tool.

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

Conciseness3/5

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

The content is comprehensive and mostly relevant, but it is a dense wall of text with heavy all-caps emphasis and repeated warnings. For a 24-parameter tool the length is justified, yet the description could be better structured with headings or shorter paragraphs, and some replacement semantics duplicate the schema descriptions.

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?

There is no output schema, so the description carries the burden of explaining return values, and it does: `url`, `moved`, `unchanged`, `succeeded`/`failed`, `batchUrl`, `batchTitle`, `archivedParents`, and `links`. Given the tool's complexity, it covers the behaviors an agent needs to call it correctly and interpret the result.

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 already 75%, but the description adds meaningful semantics for risky parameters: `assignees: []` empties the list, `dependsOn` replaces, `taskId` can be an array with per-task independence, `moveBefore`/`moveAfter` target a sibling with the same `parentTaskId`, and `appendBody` is incompatible with `body`. Some parameters such as `dueOn`, `title`, `status`, `priority`, `cellId`, `executor`, and `expectedProjectId` are mostly left to the schema, which is acceptable given the high coverage.

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 specific verb and resource: 'Modifies an existing task' and enumerates the mutable fields. It distinguishes this from `create_tasks` by explaining that `create_tasks.dependsOn` applies only at creation, so an agent can tell it is the update path without opening the schema.

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

Usage Guidelines4/5

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

The description gives clear context: it is for modifying an existing task and is 'the ONLY way to (un)assign a task.' It also names alternatives for creation (`create_tasks`) and states several exclusions, such as `arbitrage`/`arbitrageAction` being refused in batch form. It does not provide a full when-to-use versus when-not decision tree, but the guidance is strong.

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.