update_task
Modify an existing task's details—title, description, dates, estimates, priority, assignees, subtasks, GitHub issue/PR links, or acceptance criteria—by task ID, with optional clearing of fields.
Instructions
Update task details like title, description, estimates, or acceptance criteria.
Tool call template
Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.
{
"id": 1,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {
"task_id": "<task_id>"
},
"name": "update_task"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| title | No | New title for the task | |
| task_id | Yes | The ID of the task to update | |
| due_date | No | New due date as YYYY-MM-DD. Pass an empty string to clear it. | |
| priority | No | New priority level (0-5, higher is more important) | |
| blocked_by | No | REPLACES the full set of tasks this task is blocked by. Pass [] to clear all of them. Every id must be a task in the same product; a circular chain (A blocked by B blocked by A) is rejected. While any of these is not done, the task shows as blocked whatever its stored status says. | |
| sort_order | No | Position among the project's tasks (lower sorts first). Drives the order returned by list_tasks and the board/list views. | |
| start_date | No | New start date as YYYY-MM-DD. Pass an empty string to clear it. | |
| description | No | New description | |
| is_milestone | No | Mark this task as a milestone, drawn differently on the Gantt view. Pass false to unmark it. | |
| github_pr_url | No | URL of the GitHub Pull Request implementing this task. Used to fetch the PR diff for AI verification and to match incoming CI status back to this task. Pass an empty string to clear it. | |
| blocked_reason | No | Free-text reason shown next to a manually-set Blocked status ("waiting on the client"). Cleared automatically when the task leaves the blocked status. | |
| parent_task_id | No | RE-PARENT this existing task: make it a subtask of the given task, or pass null to detach it back to top level. Until GH #387 this was settable only at creation (create_task), which meant a finding recognised as adjacent AFTER it was written down could not be filed under the task that found it. The parent must be in the SAME project, cannot itself be a subtask, and THIS task must not already have subtasks of its own — nesting is one level only, and each of those is refused with a 400 naming what is in the way rather than silently producing a grandchild. Note that parenting a task immediately stops its parent closing: a parent with any subtask that is not done is refused (403 OPEN_SUBTASKS) by PUT /api/tasks/:id/status. | |
| github_issue_id | No | The GitHub issue number this task tracks (pass null or an empty string to unlink). LOAD-BEARING, not bookkeeping: session_heartbeats.task_id is NOT NULL and the heartbeat endpoint resolves a session's GitHub issue number to a task through tasks.github_issue_id — so a session working an issue whose task lacks this column emits heartbeats that have nowhere to land and is invisible on the live agent board. Writable over REST since #384; this tool could not send it until GH #387, which is why it had to be set with a hand-rolled curl. | |
| assignee_user_id | No | User ID to assign the task to, REPLACING THE WHOLE assignee set (every non-active assignment row is deleted, active workers spared) — use this only when you want exactly one owner. Must be a member of the same account. Pass an empty string to unassign everyone (active workers still spared). To ADD a second assignee without touching the first, use add_assignee instead; to remove just one, use remove_assignee. | |
| github_issue_url | No | Full URL of the GitHub issue this task tracks. Pass an empty string to clear it. Set it alongside github_issue_id so the two cannot disagree. | |
| estimated_minutes | No | New time estimate in minutes | |
| verification_mode | No | Gate this task's own completion. "manual" (default) allows a plain status change to done. "ai_review" or "all" BLOCK marking the task done (403 VERIFICATION_REQUIRED) until ai_completion_score reaches 0.8 — run "Verify with AI" first. "ci_required" or "all" BLOCK it until a PR is linked (github_pr_url) with passing CI. Setting this arms a real check against your own future attempt to close the task. | |
| required_ci_checks | No | Which named CI checks (matched case-insensitively as a substring of the check name) must pass for "ci_required"/"all" verification_mode to consider CI satisfied — e.g. ["build","test"]. Read by GET /api/tasks/:id/ci-status's resolveRequiredChecks (app/functions/api/tasks/[id]/ci-status.js:13-32), NOT by the GitHub webhook handler, which sets ci_status unconditionally from whichever single check/workflow event just arrived regardless of this field. Stored as a JSON array. Pass an empty array to require every check; this tool has no way to clear the column back to "inherit from project" (the REST API reserves that for an empty string, which this array-typed field cannot send). | |
| acceptance_criteria | No | New acceptance criteria |