Tasks
Lifecycle, statuses, priorities, subtasks and sequential dispatch, goal-seeking loops with a definition of done, and how agents create, update, and complete tasks.
Tasks
A task is a commitment that persists on someone's list until it's done. Use a task when something is genuinely owed — a call to make, a follow-up, a review, an edit. Don't use a task for something that already happened; that's a post instead.
Lifecycle and statuses
A task moves through open → in_progress → done, or sideways to blocked or cancelled. Listing tasks defaults to the open backlog — open + in_progress + blocked — so done and cancelled work stays out of the way unless asked for.
Priorities
Four levels: urgent, high, normal (the default), low. Reserve urgent for a real, hard deadline — not everything that feels pressing is urgent.
Assignment and Triage
A task can be self-assigned (the default when nothing else is specified), handed to a human user (lands on their "Needs me" list), or filed unassigned into Triage — a holding area for work that needs an owner but doesn't have one yet. Clearing both the user and agent assignment in one update sends a task back to Triage.
How agents create, update, and complete tasks
One built-in tool, three actions — update_tasks, called directly, not through api_call (there's no separate tasks app in the catalog, so it won't show up on /docs/tools either — its shape comes with the tool call itself, like every built-in, always in an agent's context):
- create — file a new task: a title, optional body/priority/due date/section, and either self-assign, hand to a user, or set
triage: true. - update — change status, priority, title, body, due date, section, or reassign — mark a task done as you finish it, or hand a blocked one back to the user.
- list — see the backlog, filtered by status or assignee, or "mine" for the calling agent's own queue.
Subtasks and trees
A task can have subtasks: pass parent_task_id on create (or update) to file it underneath another task. Trees are shallow by design — up to three levels (a task, its subtasks, and their own subtasks) — and a task can never become its own ancestor.
Starting a parent — flipping its status to in_progress, the same update_tasks/PATCH /api/tasks/:id path as any other status change — dispatches its first not-done subtask, in the order they were created, to that subtask's own assignee (assignee_agent_id must be set; the subtask's title/body become that agent's instructions for the run). When the dispatched agent finishes, the next subtask dispatches automatically, one at a time — never in parallel. When every subtask is done or cancelled, the parent completes itself too, and that can cascade up another level in a 3-level tree.
Pass gate: "human" on a subtask to pause the sequence there: once that subtask's run finishes, it lands at blocked instead of done, and the tree only continues once a person marks it done. Leave gate unset (or "auto", the default) to let the sequence continue on its own. A subtask whose dispatched run itself fails also lands at blocked, gate or no gate — open its linked chat (chat_id) to see what happened, then mark it done to continue past it or reassign and reopen it to retry.
Handing a subtask to a different agent — reassigning it away from whoever is calling update_tasks right now — holds that step at status "blocked" (gate forced to "human") the instant you do, no matter who created the task: a person's, another agent's, or your own. It will not dispatch at all until a person releases it by setting it back to "open" from the task UI. Beyond that one handoff, an agent can change a subtask's status, gate, or assignee_agent_id only on a task it both created AND currently holds (assigned to it, or unassigned) — every other task, including the assignee's own once it's running, needs a person to change those fields, through the task UI. A pipeline can still hand pieces of itself to other agents; a person just needs to release each cross-agent step once, before its first run.
There is no separate template store in v1: an agent (or a person) builds a pipeline by creating a parent task and its subtasks in the order they should run, setting a gate wherever a human should sign off, then starting it. Any shape describable this way — a straight line, a review step in the middle, several review steps — is buildable from a prompt, today.
Goals
A subtask tree can run on a definition of done instead of a fixed list: set completion_policy: "dod" and a dod statement on a ROOT task (a goal can't itself be a subtask) instead of — or as well as — pre-filing its subtasks by hand. Starting it works the same way as any tree. Whenever it would otherwise finish (no not-done subtask left), the goal checks itself instead: an agent verifies whether the definition of done is actually satisfied by what's happened so far, then either files the next subtask itself, declares the goal met, or declares it stuck. One subtask, one check, one subtask, one check — repeating until the definition of done is met, or a limit stops it.
Four limits keep a goal from running forever: max_steps (verification passes, default 20), max_credits (default 5000), max_minutes of wall-clock time since it started (default 1440 — a day), and stuck_limit (default 3 consecutive checks in a row that made no progress). Hitting any of them lands the goal at blocked with a reason attached — the same status a gate="human" step or a failed run already uses. Raise the relevant limit and reopen it to let it keep going. steps_taken, credits_spent, and stuck_count only ever move by actually running the goal — never by editing them directly.
There's no separate grading step or second opinion: one agent's own judgment, once per pass, decides whether the definition of done holds. Set gate: "human" on the goal itself if a person should sign off before it's really considered finished, even after the agent says so.