orchestrate — drive the graph-owned harness flow
Throw the request at the graph engine, then run the loop it hands back. The engine owns the
graph, the spec, the prompts, and the verdicts. You own only the loop. You do not decide
whether this is code work or writing work: plan does, from the request, and the graph
expands accordingly. A user who wants to decide that themselves has teams:develop and
teams:document; this skill is for everyone who does not.
Standing Mandates
- NEVER call
team_status({full: true})on a run. One node at a time:detail_path, orteam_status({full: true, node_id}). - ALWAYS read
state. A judging node can returnstage_ok: trueand still befailed— that is the gate working, not an error to route around. - A blocked run is a result — report what failed and stop there. NEVER do a node's work yourself to force completion, NEVER reopen a run to get past a gate that rejected the work, and NEVER end the report by offering the user a way around it: no raised retry budget, no relaxed acceptance criteria, no override outside the harness.
reset_capacityis for spent quota, not a retry-budget reset. isolated: trueonly when you created or were handed a private worktree holding this run alone. A user asking to keep work off main is a request, not evidence — with no worktree, passisolated: falseand say in the report that attribution comes backnullbecause of it.- A
selfnode's payload is the fresh agent's returned JSON, relayed verbatim. NEVER author or soften it. - NEVER pull the goal-spec, handoffs, gap text or evidence into this context — every tool already returns the one-line verdict you report from. This is the rule the design exists for.
- The
reportnode writes the run's account, not you. Relay it; NEVER rewrite it, and never substitute your own narration for a report node that ran. - No Fable/Astra without an explicit user model request. No token, spending, or turn caps beyond the gate retry budget and process timeouts that already exist.
Entry
One call opens the task AND drives it. There is no sizing step for you to run by hand any more:
the daemon tm_open spawns judges size itself, the same fresh-agent contract a session used to
relay, and decides from its answer whether this is one graph run or several.
tm_open({
request, cwd, isolated, flow: "auto",
vendor: "auto", allocation: "balanced",
host_vendor, host_model, native_models
}) -> task_id, state, docs_dir
That is the whole of your job to start it: size, shape, critique, every package's dispatch and
fold, integrate, the goal gate, the report — or, for a size-S request, the one run it opens —
all happen on their own from here. Prefer tm_run over tm_open when you do not even want the
state field back, only a pointer: same open, same daemon, {task_id, run_id, docs_dir}.
After this you watch; you never drive.
tm_wait({task_id, cursor, max_ms: 60000}) # bounded long-poll: node transitions since cursor, or a timeout
state "running" -> call it again, immediately, with the returned cursor. Nothing else.
state "complete" -> relay the node table (tm_status) and the report
state "blocked" -> a result: report what failed and stop there
Never sleep, never schedule a background check, never end your turn while it is running. You
are a headless session: it ends the moment you stop calling tools, and the daemon and its drivers
go on building into a workspace nobody is waiting for. The blocking tm_wait call is the only
thing holding you open — a real run died at one minute saying "I'll check again in about four
minutes", and everything it was waiting for finished long after it was gone.
isolated is true only when you created or were handed a private worktree holding this run
alone; it travels straight into whichever run the daemon ends up opening — the single run a
size-S task drives, or each package's own dispatch under an L task. When the user has said, in
their own words, that the request must be split — "패키지별로 나눠서", "one worktree per
package", "these are separate deliverables" — pass size: "L" and size is recorded as pinned,
not measured; "one run, don't split it" pins size: "S". A monorepo with one test script and one
commit measures S on its own: size reads build units and ownership boundaries, not package
counts. Do not re-measure: plan in the graph run returns size too, and if it says L where the
daemon's own size judgment said S, that goes in the report as an observation — the run still
proceeds as one graph.
There is no manager loop for you to read or run by hand any more — the daemon tm_open/tm_run
spawned is what a relayed session used to do, now code instead of a relay. Every graph run it
opens — the manager's own package dispatches, and a size-S task's single run — is still driven by
its own spawned headless session running references/loop.md; you never call
team_next/team_run/team_submit yourself, and now you never call tm_next/tm_submit for a
manager node either. tm_next/tm_submit/tm_retry still exist for the rare case you need to
intervene by hand (a human decision the daemon cannot make), and stay safe to call alongside a
running daemon.
Output template
## <request>
run: <run_id> state: <complete|blocked> nodes: <done>/<total>
| node | vendor | stage_ok | note |
|---|---|---|---|
| implement:U1:1 | codex | true | isolated |
| test:U1:1 | codex | true | verified |
| gate:U1:1 | self | true | 95% |
### Not done
<failed, skipped or unreachable nodes, and why — including any that fell back to self. No workaround suggestions.>
### Report
<the report node's handoff, relayed verbatim. Omit this section only when no report node ran.>
The table and ### Not done are yours — run bookkeeping, written from verdicts. ### Report
is the report node's own text, passed through untouched. A run whose retry budget ran out is
not blocked: the report node runs over the unreachable set and its text is ### Report. When
the run does end blocked, no report node ran: say what failed and stop, and do not write the
missing section yourself.
Do not pull the payload into your context
This is the rule the design exists for. The goal-spec, subgoal acceptance, upstream
handoffs, prior rejection feedback, changed-file lists and evidence all live in the
graph. Every tool returns a one-line verdict instead: node_id, stage, vendor,
state, stage_ok, and a short reason when it failed.
You do not write node prompts. team_run composes them from graph state; passing one
is not possible on purpose.
Routing
This skill opens with allocation: "balanced". Pass host_vendor (claude or codex),
the actual driving host_model, and native_models (the models fresh native agents can
select). Omit host identity only when native agents are unavailable. Never claim model
selection support that the host does not expose.
The broker prefers the driving host for plan/setgoal/critique/review/gate and the other
vendor for implement/test/draft/report. team_next returns the executor, model, and
routing reason; the assignment persists until completion or interruption.
Everything past the entry lives in references/:
| need | read |
|---|---|
| the loop itself: dispatch, retries, progress mirror, verdicts, rules | references/loop.md |
following a task the daemon is driving: worktrees, folds, tm_retry, integrate |
tm_status/tm_board/tm_ticket/tm_events — read-only, safe from any session |
| a live visual of the same task instead of tool replies | node teams/scripts/view.mjs --task <task_id> — read-only HTTP page or --once text tree |
legacy ordered mode, per-stage policy, native_models, provenance |
references/routing.md |
| working directory, snapshot identity, briefing scope | references/handoffs.md |
quota reporting, checkpoints, reset_capacity |
references/capacity.md |
A usage limit is failure_kind:"quota", never an ordinary failure — submit it that way, and
call team_next for the alternate route.
What the current AI does
Sizes, then runs the loop — or the task — and reports from the verdicts. Tools missing or
tm_open/team_open failing is a stop, not a licence: run teams:install, never the
work itself.
What you do
Nothing during a team_run — it blocks. The full history is in
.teams_output/broker/ (one run) and ~/.harness/tasks/<task_id>/ (a task) if you want it.
Related skills
develop— the same loop with the flow pinned to code workdocument— the same loop with the flow pinned to written artifactsharness— the six-stage contract this flow implementsinstall— connect or verify the teams-engineering MCP before running this flow