MCP Task Orchestrator ยท Field guidePlate 8 of 10
A run is a bounded pass over a set of items. It lets the server, not the prompt, hold three lines: which agent may touch which item, how much a pass may spend, and when a person has to weigh in. Everything in the earlier plates works without one.
Step through one run. The panel shows the state of the run, its two kinds of token, and one item after each call.
runs_write open takes a root and up to 500 of its items. An item can sit in only one run that is not closed. The answer carries coordinatorToken once. Who holds it is the coordinator.
Only the coordinator can assign. It returns a seat token for one item and one seat, shown once. Assigning the seat again kills the old token and counts another attempt.
The coordinator, the director profile or a human can close, with completed, cancelled, failed or abandoned. completed is refused while a seat is active. budget_exhausted belongs to the server.
| Credential | How it is passed | What it can do |
|---|---|---|
| Coordinator token | Top-level seatToken next to ops | update (add or remove items, lower the budget), assign, close, any transition of a member item that the transition table allows, and the note keys of the seat named orchestrator. |
| Seat token | Top-level seatToken on every call the seat makes, reads included | Act on its own item and seat only. end_seat with its own token. The coordinator token is refused there. |
| Director profile | A separate MCP connection, no token | open, close, pause, resume, ack, answer, withdraw (only a decision it raised itself). Nothing else. |
| Human credential | A human credential and no seat token, over REST or the director profile | Everything a director can. With a real credential proof it also answers the classes that only a human may. mark is REST only. |
A token is never stored in readable form or replayed. A keyed retry of open or assign answers tokenRedacted: true. Lose a seat token and you assign the seat again. Lose the coordinator token and you close the run and open another.
A token that is unknown, ended, superseded, or presented by a different principal is unauthenticated with no detail. Closing a run ends every token it issued.
Notes are owned by (principal, seat); claims are held by (principal, assignment), so a re-assigned seat does not inherit them. Two agents that share the one local principal on stdio are still separate holders when their seats differ.
{"seatToken": "<seatToken>",
"ops": [{"op": "transition", "itemId": "a1b2c3d4", "trigger": "start"}]}
Only on a member of a run that is not closed, and only when the item's pinned schema declares seats. Outside a run, seats stay a signal for the orchestrator and nothing is refused.
A seat marked enters may start its item, and only into its own phase. Any other trigger must be listed in the calling seat's own transitions:. The default is block and hold. A refusal is seat_forbidden and applies nothing.
A seat writes the note keys its seat owns, plus keys no seat owns. A note belongs to (principal, seat), so another seat gets note_owned_by_other even from the same principal. The coordinator writes only the orchestrator seat's keys.
A cascade is a write. When a child's change would move a member parent, it is applied only if the caller could have sent that trigger to the parent directly. Otherwise it is suppressed and reported as blocked: seat.
A human credential without a token is exempt. On stdio the caller is the local principal, which counts as an agent, so it is not exempt.
| Concern | Rule | What happens |
|---|---|---|
| Stalled | Quiet for longer than stallAfterSeconds. Config key runs.stall_after, default 600, pinned when the run opens. | A view only. Nothing is ended or released. Only a call under the token to a tool that takes ops counts as a sign of life; a select read never does. A long seat sends an advance heartbeat. |
| Frontier | runs_read select="frontier" | The members that are ready, the seats inFlight with their stalled flag, and the waiting members with a reason (manual, dependency, awaiting_decision or resource). |
| Budget | Optional tokens and costUsd on the run | The next heartbeat, assign, end_seat, transition or raise under a token after a crossing pauses the run (pauseReason: budget) and the server raises a run-budget decision. Answer extend with an amount, or stop. |
| Attempts | attemptsPerSeat | An assign past the cap is run_paused, the run pauses (attempts) and an attempt-cap decision is raised. Answer allow_one, skip_item or stop. |
| Concurrency | maxActiveSeats | An extra assign is a transient run_at_capacity. No decision. Retry when a seat ends. |
Budgets are opt-in: no budget means no cap. The runs.budgets.* keys in config (tokens, cost_usd, attempts_per_seat, max_active_seats) are ceilings an operator sets. A run may only choose a value at or under them, and update can only lower a field or set one that was absent.
Nobody can resume a pause for a budget or attempts. Only the answer clears it (a stop answer closes the run), or a close ends the run. While it is paused, a start under any of its tokens is refused run_paused. A manual pause refuses no start, so seats in flight can finish; assign and update are refused run_paused under any pause. Only a director or a human can resume a manual pause.
A seat or the coordinator raises a decision when it needs a person. The class decides who may answer it. Pick a class and a caller to see the server's answer.
| Built-in class | Answerers | Severity | Overdue after | Options |
|---|---|---|---|---|
run-budget | director or human | high | never | extend (with an amount), stop |
attempt-cap | director or human | high | never | allow_one, skip_item, stop |
deviation | director or human | normal | 14400 seconds | whatever the raiser lists |
question | any actor | low | never | free text allowed |
{"seatToken": "<seatToken>",
"ops": [{"op": "raise", "class": "deviation", "dedupeKey": "api-shape-1", "block": true,
"question": "The spec says X but the code does Y. Which wins?",
"options": [{"key": "spec", "label": "Follow the spec"}, {"key": "code", "label": "Keep the code"}],
"recommended": "spec"}]}
Under the orchestration profile. The same dedupeKey returns the existing decision instead of a second one. block: true raises and blocks the item as awaiting_decision in one step.
A second ack, answer or withdraw on a closed decision is decision_closed. Expiry only makes a decision read one step more urgent. The server takes no other action.
An answer never resumes the item. The coordinator reads the answer and resumes it. The decisions the server raises for a limit cannot be withdrawn, and closing the run leaves them open, counted in snapshot.openDecisions.
On a single-developer stdio server every caller is the one local agent, so a human-only class cannot be answered there. Start a second stdio entry with MCP_TOOL_PROFILE=director to answer the built-in classes.
The director runs the board and never the code. It sees runs and decisions, and it hands every read of a file or a note to someone else.
The director profile (/mcp/director, or MCP_TOOL_PROFILE=director on stdio) serves a short list: items_read (get, list, overview, blocked), deps_read, report, runs_read (get, list, frontier, decisions, decision) and runs_write (open, close, pause, resume, ack, answer, withdraw). No read on it can return a note, document or transition-summary body.
/task-orchestrator:init registers it as the entry mcp-task-orchestrator-director. /task-orchestrator:director shows the board; /task-orchestrator:director off leaves the mode.
While the mode is on, a guard hook denies file reads and edits, foreground agent dispatch, and any shell command outside a short read-only list. The only bodies the director may read are one decision request and one run rollup. A denied call is delegated to a background agent or sent to a coordinator, not retried another way.
The guard also watches three MCP reads on the orchestration connection: it denies notes_read and docs_read and allows items_read only with get, list, overview and blocked. It sees no other MCP call. The director connection enforces the rule on the server, because it has no note-body read at all. Use the hardened entry when the rule must hold for every tool.
The skill reads, in order: the open runs (runs_read list), then for each run its frontier, its decisions and its report rollup, then the blocked work under the project root (items_read blocked). The decisions select has no status filter, so the director keeps the open and acknowledged ones itself. A summary carries the effective severity (one step higher once overdue), the question cut to 120 characters, and never the options; the decision read brings those when the director answers. The board shows the most urgent first, then the director asks which decision to take.
## Director board
Decisions waiting: 2 (1 overdue)
[d-3f2a] run 7c41 deviation high
"Keep the old API shape?" OVERDUE
[d-91bc] run 7c41 question low
"Pick a retry strategy"
Runs: 1 open
7c41 "W8 plugin" ready 3 inFlight 2
waiting 1 spend 1.2M tok stalled 0
Blocked: 1
8aee blocked by dependency 4440ff65
Coordinator tier: 2 (Workflow)
The director shows the question and its options and asks the user; it never answers for them unless told how to answer that class. A forbidden answer names the cause in detail.scope and required: capability and decide (the credential lacks the capability), principal_kind and human (a human-only class), or principal_kind and director,human (the call did not come through the director profile without a seat token).
On a coordinator's message, a task notification or the user's return, the director reads that run and its decisions. It does not decide by itself when to notify or start a retrospective: the director-watch hook tells it, once per decision or run.
| Piece | What it does |
|---|---|
director-guard | Writes a per-session marker when the skill is invoked and enforces the altitude rule under it. Subagents and headless iterations are exempt. It fails closed. |
director-context | Re-states the rule after a compaction, so a long session keeps it. |
director-watch | After a runs_read, tells the director to push one notification naming all the new open decision ids, each pushed once, and to start the retrospective once for a closed run that is not yet marked (silent under REST). |
agents/director.md | A hardened entry for claude --agent director. Its tool list holds the five director tools and no file or shell access, so the rule is enforced by what is missing. It has neither Workflow nor start_session, so it reaches only tiers 3 and 4 below. |
The director never runs a wave itself. A coordinator plans the run, makes or receives its seat calls, runs post-run and reports a short summary. Where the coordinator lives depends on what the session can launch. The director probes once per entry and shows the tier as one board line. Tiers 1 and 2 show in its own tool list; for tier 3 it asks the user, or has a background agent run claude --version.
| Tier | Needs | Where the coordinator runs |
|---|---|---|
| 1 | start_session and SendMessage | A separate desktop session, reached with SendMessage. Cross-session inbound messages must be set to accept, or a report can be lost. |
| 2 | Workflow | A background coordinator agent plans the run (run-wave Steps 0 to 5a, altitude-safe) and keeps the coordinator token. The director makes the one implement-wave call, whose result holds counts, statuses, SHAs, file lists and note keys, with reasons cut short and no other seat prose, then messages the coordinator to run post-run. |
| 3 | The claude CLI on the host | A headless claude -p process that a background agent starts with --allowedTools Workflow and --max-budget-usd, the only configured hard stop. Never --bare, which cannot receive messages. |
| 4 | None of these | No coordinator. The run executes in the director session, which breaks the altitude rule, and the director warns once. |
Tiers 1 and 2 need the skill entered in a normal session. A run of one or two items skips the coordinator layer at any tier and goes to one background agent. Tier 2 makes one call per run, so decisions land between runs. The launch details are in the skill's coordinator tiers reference.