Harness: Claude Code (v3)
One of the three harness files a loop root reads beside the contract, published unchanged from the public export of the copy my own agents read.
- Source
- agent-docs/sources/loop/harness-claude.md
- Revision
- 0f4fd35
Read at launch with the contract and the charter.
Launch
The launch file’s first line is the command; the message follows it:
cmd: claude --model claude-opus-5-5 --effort medium
You are the root. Read $PROTOCOL_SOURCE/sources/loop/contract.md, $PROTOCOL_SOURCE/sources/loop/harness-claude.md
and <abs charter path> in full. Write <abs closeout path> last, then reconcile and reply (contract section 12).
Standing: <abs path> sha256=<hex>
<each charter authority: or live: line touching customer data or a live system, verbatim>
- The root runs Opus 5.5 at medium unless the charter’s
root:says otherwise. - The
agent-workflowsStop hook arms on “You are the root” plus exactly onecodex/closeout-<date>-loop<N>.mdpath, or a bare path to a launch file holding them. It lets the turn end only when that closeout counts (contract section 12, step 4) or the last line is a currentPAUSED:orWAITING: ... until <UTC>line; otherwise it re-prompts up to three times in a chain. - Nothing wakes an owner-only wait. Before ending that turn, start one background command that
sleeps until its
WAITINGdeadline, so the session wakes then (contract section 12).
Permissions and owner questions
- A lane cannot clear an auto-mode permission block the root could, so SSH, deploys, tenant or
cloud mutations, secret-store writes and destructive git stay with the root. Running the
charter’s gate route (a
justgate recipe, even one that reaches a build host) is lane work, not SSH. - The auto-mode classifier weighs only owner messages, never the charter file. The launch message
therefore repeats each charter
authority:andlive:line that touches customer data or a live system, verbatim, afterStanding:. Paste the message text, not a bare launch-file path, when it carries such lines. AskUserQuestionblocks the session: call it only as contract section 7 allows, never in overnight mode, and reconcile (section 12) as soon as it returns.
Routes
| Role | subagent_type |
Model / effort |
|---|---|---|
| implementation (default) | agent-workflows:worker |
Sonnet 5.5 / high |
| judgement, unknown cause, seams, compose and board batches | agent-workflows:senior |
Opus 5.5 / medium |
| escalation (tripwire or owner-named) | agent-workflows:senior-escalation |
Opus 5.5 / xhigh |
| review and security review | agent-workflows:reviewer |
Opus 5.5 / high |
| read-only mapping, sweeps, wave drafts, log reduction | agent-workflows:scout |
Sonnet 5.5 / medium |
- Pass no
modelto these agents: it overrides the pin. Give each dispatch adescriptionof<lane> <task>. - Every role keeps a one-hour prompt cache, so a lane can wait on a gate slot without rewriting its context.
- If an
agent-workflows:*type is missing, the plugin is not installed: stop and say so in chat.
Dispatch and repairs
- Dispatch unnamed, in the background. Never
subagent_type: "fork"for a lane. - The
agent-workflowsPreToolUse hook denies an armed root’sAgentcall unless the prompt’s first non-empty line is the brief header (contract section 3). Fix the header and dispatch again. - At most 30 running subagents (
CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS); the 31st fails withConcurrent subagent limit reached. Wait for a return instead of retrying. Keep about 7 free when lanes may delegate; a brief says whether a lane may. - A lane’s completion arrives as a task notification. Repair rounds and answers go to the same lane
with
SendMessageto its agent id, carrying the new evidence. TaskStopa lane once its task lands or parks, so it stops counting against the cap.- Make lane worktrees yourself (
git worktree add);isolation: "worktree"branches from the default branch, not your base. Keep your own shell at the repository checkout: your working directory persists between Bash calls and every lane you dispatch inherits it. Nevercdinto a worktree; usegit -C <worktree>and absolute paths, or a subshell(cd <worktree> && ...). Ifpwdis not the checkout,cdback before the next dispatch. Lanes never callEnterWorktree. - A lane’s hand-back is one-shot. After a resume, its next return may arrive as an agent message
instead of a task notification: take the
lane-returnblock in it as the return. If a resumed lane goes idle with neither, read itsreturn.md.
Waits
- Your own waits (main CI, a release, a gate you run) are one
run_in_backgroundBash command whoseuntilloop exits on every terminal state; its completion wakes you. Streamed events useMonitor, re-armed when it expires. LOOP.md’s optionalci-statuscommand replacesghreads: substitute the full SHA for{sha}, sleep 60 s between reads, stop onsuccessorfailure, bound the loop byci-max-minutes(default 30).- A composed gate’s legs (contract section 6): after the
git status --porcelaincheck, start each leg as its ownrun_in_backgroundBash command against the compose worktree by absolute path, one log per leg. If the classifier refuses the fan-out, record the denial, run the legs one after another and say so in the return orDECISIONS.md. - Bash calls time out at 10 minutes: run anything longer in the background. Never a foreground
sleepover 60 seconds.
Turn endings
A message with no tool call ends your turn, and the loop stops there until the operator returns.
Do not end a turn with a summary that announces the next step without taking it, an offer to carry
on, a list of decisions none of which blocks the remaining work, or a decision that this is a good
place to stop. Put status notes in the same message as your next tool call. End a turn only when the
closeout is written, when paused, or when a running background command, monitor or lane will wake
this session; when waiting, make the last line `WAITING: <what> until <YYYY-MM-DDTHH:MM[:SS]Z>`;
when paused, `PAUSED: <reason>`. Never TaskStop a lane mid-mutation.