Resident subagents
V0.x breaking change: zut no longer supports subprocess subagent state.
Previous state is ignored rather than read or migrated; remove it when you
no longer need it. Existing child jobs are never resumed.
V0.x breaking change: the separate subagent_spawn, subagent_status,
subagent_stop, and subagent_resume tools are replaced by one subagent
tool whose actions are selected by an action argument.
--tools subagent_spawn no longer selects anything; use
--tools subagent:spawn, or bare --tools subagent for every action.
Under --no-yolo, "always allow" is remembered per action
(subagent:status and subagent:spawn are separate grants), so approving a
read-only status call never pre-approves any other action.
Subagents are independent core.Agent conversations resident in the same zut
process as their parent. A child has a stable, private session identity, its own
provider client and tool registry, a cancellation boundary, and an authoritative
journal. Starting a child never launches another zut executable.
Profiles
Profiles are Markdown files discovered from ~/.agents/agents/*.md and paths
in ZUT_AGENT_PROFILES. They are inputs only; zut does not execute them.
---
name: reviewer
description: Read-only code reviewer
tools: [read, grep]
model: openai-codex/gpt-5.6-luna
thinking: high
systemPromptMode: replace
inheritProjectContext: false
inheritSkills: false
fastMode: false
---
Inspect the requested scope and report evidence-backed findings.
tools is a capability boundary. An omitted value inherits the child-safe
catalogue, tools: [] grants no tools, and an explicit list replaces the
default. The child-safe catalogue contains only tools offered by the parent
that are also available in the resolved child runtime; parent-only scheduling
and extension tools are never inherited. Names unavailable to the child
(including host-only extensions) and tools denied by subagents.allowed_tools
are omitted from an explicit list; they never grant the child additional
access. model, provider, thinking,
the prompt mode, project/skill inheritance, and fastMode are resolved before
the child is accepted. Spawn-level model, provider, reasoning, and fast-mode
values take precedence where supplied.
Children are always fresh conversations: they receive the delegated task and
resolved host/profile context, never the parent transcript or hidden reasoning.
They cannot recursively create more children.
Lifecycle and persistence
The manager records each accepted child under its managed state root:
subagents/<child-id>/
transcript.jsonl # accepted turns, finalized messages, and compaction checkpoints
owner.lock # host-ownership coordination; do not modify or remove
.transcript-backup-* # retained private pre-repair transcript, when repaired
metadata.json # rebuildable bounded state
result.json # latest outcome, final summary, artifacts
patch.diff # optional worktree capture
Acceptance is durable before the subagent tool's spawn action reports
success. Finalized user, assistant, tool-call, and tool-result messages are
journaled; streamed deltas and hidden reasoning are not exposed as ordinary
history. A tool call is stored before execution and reconciliation repairs
incomplete call/result pairs. A context-overflow recovery appends one
child.compacted checkpoint carrying the replacement transcript; resume
starts from the newest checkpoint, while the paged history view still shows
everything appended before it.
All children stop when the host exits. On the next start, queued or running
turns are marked interrupted; zut never replays their task. Resume only with
an explicit new prompt through the subagent tool's resume action, the
child-session composer, or /subagents resume <id> <prompt>.
Multiple zut processes may share a state root. Each resident journal has one
host owner at a time. A process that finds a child owned elsewhere reports it
as such and does not inspect, recover, or modify its transcript. Resume that
child from its owning host or after the owner exits. On a subsequent safe
reconciliation, zut repairs only the known legacy false-recovery sequence; it
leaves any ambiguous journal corruption untouched. A repair retains the
pre-repair transcript as .transcript-backup-*; it can contain private session
data and is intentionally not removed automatically.
The subagent tool's status action reports owned_elsewhere: true when
another process owns a child. The field is omitted when false. A foreign-owned
child cannot be resumed, or have its history or result read, from this process.
The global scheduler admits the oldest eligible accepted prompt, runs at most
one turn for each child, and defaults to six concurrent turns. Set
subagents.max_concurrent to a positive limit to override it. Queueing is
unlimited by default; a positive subagents.queue_timeout cancels an accepted
prompt that has not received a slot and records its terminal failure durably.
subagents.allowed_tools is an allowlist for child-visible tools and
subagents.allowed_roots limits eligible child workspaces. Resident children
have no cumulative token budget and no child-only step cap: a child inherits
the parent's resolved limit, including the unlimited default. A turn is bounded
by the provider context window, with one compaction recovery, and by an
explicit parent --max-steps. Removed legacy
settings, including tui_subagent_position and subagents.budget_ratio, are
ignored. Resident journals written by older versions are read with explicit
translation (an old budget_exhausted outcome reconciles as failure) or, for
unknown versions, left untouched on disk and excluded from automatic
discovery. Incompatible journals cannot be resumed; start a new child
instead. Other journal recovery errors are still reported.
Compatibility notes: new journals write version 3 and carry no budget
fields, baselines, or exhaustion states. Version 2 archives are read with
explicit translation and their transcripts are never rewritten by
translation. result.json keeps a deprecated handoff field that stays
empty for new results and remains readable for archives. The subagent tool's
status action no longer exposes budget or budget_source fields.
Context reminders
When a child's last-turn prompt reaches 85%, 90%, or 95% of its model context
window, the runner injects a non-blocking reminder into the next provider
request:
Context usage is at NN% of the model window. Finish the current task, report
results, limits, and remaining verifications, and do not start broad new work.
Each band fires at most once per child runner and reminders never block a turn.
A jump straight to a higher band delivers one reminder for that band, and usage
that falls does not re-deliver a band. Reminders travel as developer context in
the live request; the durable transcript keeps only finalized history. Usage is
the last-turn prompt size (input plus cache read/write tokens) against the
resolved context window; an unknown window never triggers a reminder. The
per-turn gauge resets when the host restarts and when a recovery compacts the
context, so neither event reports a stale percentage. The band ladder itself
advances at most once per child runner: a restart starts a fresh ladder, while a
compacted child is reminded again only when usage reaches a higher band.
Context-overflow recovery
A provider request that exceeds the model context window ends the turn. When
the transcript holds at least four messages, the child recovers once per turn:
it compacts the transcript, keeps the two most recent messages verbatim,
journals the replacement as a child.compacted record, and continues the same
turn. A compaction or persistence failure restores the pre-compaction
transcript and fails the turn, and a second overflow stays terminal. Recovery
never replenishes an explicit parent --max-steps: when the allowance is
already spent, the checkpoint is still written for a later resume, but the turn
is not continued.
Explicit resume replays the newest checkpoint instead of the full append-only
log. The history views (/subagents logs, HistoryPage, subagent:// refs)
still show the append-only log, including pre-compaction records. A build that
predates checkpoint support cannot resume such a child correctly; downgrading
is unsupported.
The summarization request itself can be rejected when a single oversized
message leaves nothing to summarize away. The turn then fails with the original
provider error and no checkpoint is written, so the child keeps failing on
resume until its transcript shrinks. Recovery is a best effort, not a
guarantee.
Retrieve the saved result without executing a model:
{"action":"status","agent_id":"<child-id>","include_result":true}
Pass this to the subagent tool's status action, then reconcile the history
and artifacts before repeating any side effects. The subagent tool's explicit
resume action after a terminal failure continues the retained session,
workspace, and cumulative cost. It does not automatically retry the task.
Ordinary follow-ups continue the existing session.
required: true makes a delegated result an obligation of the parent turn.
Failed, cancelled, and interrupted required work remains
unresolved until an explicit successful follow-up. Reading a saved result or
accepting a recovery prompt does not satisfy the obligation. A host restart never
retries it automatically.
Delegation ownership
Interactive proactive delegation keeps the primary agent on the critical path.
Process start says nothing about the task, and the workers it needs only become
knowable once the user states the request. Routing therefore happens then: the
reply that starts the work names the parts the primary keeps on the critical
path and the profile that owns each delegable part, before it implements or
spawns anything. It states plainly when nothing is worth delegating rather than
forcing a worker. The routing guidance is part of the prompt only when
launch-time policy exposes the spawn action.
Before spawning, it selects useful local work and delegates only a concrete,
bounded sidecar with a non-overlapping question, responsibility, package, or
file set. Immediate blockers and tightly coupled work stay local. While a child
is active, it owns that scope; the primary continues only its preselected
independent work instead of repeating the investigation, review, testing, or
implementation. If an explicit user request or active workflow hands blocking
work to a child, the primary yields for the completion update. Once a worktree
child succeeds, the primary may apply and verify its captured patch without
redoing the delegated task.
Explicit headless --orchestrate remains manager-only. Its primary divides the
request into disjoint worker scopes, coordinates active children, and yields
rather than implementing or reproducing delegated work. Children do not inherit
the parent's strict orchestrator role. Headless orchestration waits for every
accepted child before continuing its completion wave; required: true
additionally creates a durable obligation. When proactive
interactive delegation cannot spawn because of launch-time policy, the primary
continues locally; a strict headless orchestrator instead reports the missing
required capability.
The model-facing tool keeps one logical name and five actions, selected by its
action argument. Launch-time gating is per action: --tools subagent grants
every action, --tools subagent:<action> grants one, and --no-tools disables
all of them.
subagent accepts an action of spawn, status, stop, resume, or
interrupt.
-
spawn accepts task, optional agent, model and provider,
reasoning, fast_mode, required, wait, and isolation (shared or
worktree).
wait is an explicit whole-second value from 1 through 300; when omitted,
spawning returns immediately. A timed-out wait leaves the
accepted child active, whether it is queued or running. Do not retry that
task until it reaches a terminal failure, cancellation, or interruption. It
returns a logical subagent://<id> reference.
-
status accepts optional agent_id and include_result, and returns
bounded current state for one child or the current set immediately. With
agent_id and include_result: true, it also reads the saved terminal
result without model execution. Without this option it remains
metadata-only; foreign-owned results cannot be read. Result-read errors
distinguish foreign ownership, a missing saved result, and permission
denial without exposing filesystem paths or saved content.
With agent_id, a running child also includes activity: a phase
(waiting_for_model, writing, tools, or working), the tail of its
visible text, and its active tools with truncated arguments. Hidden
reasoning is never exposed. watch (1–60 seconds, requires agent_id)
observes that activity and returns a timeline of phase and tool changes.
It returns early when the child stops running. Use it to inspect progress,
not to wait for completion. pending_followups counts follow-ups the
child has accepted but not read yet.
-
stop accepts agent_id and stops one live child.
-
resume accepts agent_id, prompt, optional mode, and optional
wait. prompt is an explicit follow-up prompt for an existing child.
Do not use resume solely to wait for existing work or ask for its result
again: yield for the automatic completion update. queue schedules another
turn and produces another completion.
After a terminal failure, inspect the saved result before resuming; resume
continues the retained session. mode controls how a follow-up reaches a
running child:
steer (default) injects it into the current turn at the next tool or
model boundary, like typing while the main agent works. It adds no new
turn and no extra completion.
queue runs it as a separate turn after the current one.
An idle or stopped child starts a new turn in either mode, and a steer
never jumps ahead of already queued turns. The response's delivery is
steered or queued. wait uses the same 1–300 second bound as spawn
and waits for the turn that answers the follow-up, returning its outcome or
reporting the timeout while the child stays active. A returned outcome can
be dropped when a queued follow-up never started. When the host accepts
the completion report, the summary and undelivered steers arrive in the
completion update; otherwise the outcome includes them.
-
interrupt accepts agent_id and cancels only the child's running turn.
Unlike stop, the child stays live with its transcript, so a later
resume such as "report what you have" continues with full context.
Queued follow-ups are dropped. It fails when no turn is running.
When a turn ends before the child reads a steered follow-up, for example after
stop, interrupt, or a failure, the completion update lists it as
undelivered. Queued follow-ups that never started are reported as dropped.
Neither appears as an interrupted task.
Child execution started by the subagent tool's spawn or resume action is
asynchronous unless it receives an explicit wait value. For an unwaited call,
completion arrives through the host’s typed completion update; the subagent
tool's status action returns immediately and does not wait for completion. Do
not use sleep loops, repeated status calls, journal files, or terminal UI
inspection as a completion signal.
When the host accepts a completion report, a completed spawn or resume
wait returns terminal status and report_delivery: host_update; the full report
arrives only through the completion update, not again in the tool result.
If no host observer accepts the report, the tool result includes it inline.
An expired wait does not suppress later completion delivery. Cancelling the
parent turn discards pending completion updates; cancelling only a tool wait
leaves host tracking intact.
In interactive mode, a result received while the primary is busy enters the
visible sliding in queue and reaches the model at its next safe boundary,
without interrupting a model request or tool call and without waiting for other
children. Results already queued are not repeated when the parent turn ends.
Undelivered results remain queued after a provider or compaction error for the
next turn; they do not automatically retry the failed request. Explicit
cancellation clears pending queue entries. The queue is in memory, while the
child’s saved result remains available through the subagent tool's status
action.
When the primary is idle, each child completion immediately starts the next
parent turn instead of waiting for its siblings. The host update names the
finished child and lists sibling agent IDs that are still running. A completion
that arrives while that parent turn is active slides into its queue. Headless
orchestration still waits for every accepted child before its next parent turn.
Successful completions include the final visible assistant summary, capped at
256 KiB; open the child session for the complete durable transcript.
/subagents opens the resident-child list, ordered by the latest state change.
Each row leads with the profile (or model), shows a human terminal state such
as completed, a relative update time, and a short ID. Press Down from the
main composer to open this list without clearing a draft when a child exists.
Use arrows and Enter to open a child session; /subagents new <task> creates a child; /subagents logs <id>
opens its history; /subagents result <id> shows the bounded final summary;
kill <id> stops it; and resume <id> <prompt> continues it. A prompt sent
from the child composer or resume to a running child steers its current turn.
The child session uses the same transcript renderer as the main session.
Recent history is bounded and loaded asynchronously; PgUp asks for an older
page. Up/Down preserves the current reading position, and PgDn returns to the
live tail after unread updates accumulate. The screen combines durable finalized
history with an immutable in-memory projection of the active turn. Enter submits
the local composer only after the manager durably accepts it; Esc closes the session. History may contain task
text, tool arguments, tool results, and source-derived output, so treat it as
private local session data.
Worktrees and references
Shared children use the host working directory. With isolation: "worktree",
zut prepares a detached Git worktree and captures a patch and changed-file list
on successful completion or non-cancelled failure. Failed turns retain
partial work in the worktree, along with any captured patch and changed-file
list. zut never applies a captured patch automatically. Failed or interrupted
worktrees are retained for inspection; an idle successful worktree is cleaned
when its child is explicitly stopped.
Use the subagent tool's status action with agent_id and
include_result: true to retrieve the saved result, changed_files, and
patch_ref when a patch was captured. The
patch bytes are stored in subagents/<child-id>/patch.diff under the managed
state root shown above; logical references are identifiers, not filesystem
paths. Inspect the retained worktree and patch before resuming or applying
partial changes.
New terminal journal records also save the capture metadata, so reconciliation
can restore it if result.json is missing or corrupt. Older records remain
readable, but cannot reconstruct artifact metadata they never recorded.
Logical references avoid exposing runtime paths:
subagent://<id>
subagent://<id>/history
subagent://<id>/result
subagent://<id>/patch
Provider caching
Each main and child conversation sends a stable logical session ID and a new
turn ID per accepted prompt to the provider layer. Provider adapters decide
whether and how to use them: OpenAI/Codex translates a supported stable session
into its cache key and routing header, while other adapters preserve deterministic
request input and use only cache controls their provider/model/endpoint supports.
An OpenAI-compatible wire shape is not itself evidence that a cache extension
or transport feature is available. Models continue through their declared
provider transport; a transport change must not change the logical session or
turn identity used by the provider request.
source
1# Resident subagents
2
3> **V0.x breaking change:** zut no longer supports subprocess subagent state.
4> Previous state is ignored rather than read or migrated; remove it when you
5> no longer need it. Existing child jobs are never resumed.
6
7> **V0.x breaking change:** the separate `subagent_spawn`, `subagent_status`,
8> `subagent_stop`, and `subagent_resume` tools are replaced by one `subagent`
9> tool whose actions are selected by an `action` argument.
10> `--tools subagent_spawn` no longer selects anything; use
11> `--tools subagent:spawn`, or bare `--tools subagent` for every action.
12> Under `--no-yolo`, "always allow" is remembered per action
13> (`subagent:status` and `subagent:spawn` are separate grants), so approving a
14> read-only `status` call never pre-approves any other action.
15
16Subagents are independent `core.Agent` conversations resident in the same zut
17process as their parent. A child has a stable, private session identity, its own
18provider client and tool registry, a cancellation boundary, and an authoritative
19journal. Starting a child never launches another zut executable.
20
21## Profiles
22
23Profiles are Markdown files discovered from `~/.agents/agents/*.md` and paths
24in `ZUT_AGENT_PROFILES`. They are inputs only; zut does not execute them.
25
26```markdown
27---
28name: reviewer
29description: Read-only code reviewer
30tools: [read, grep]
31model: openai-codex/gpt-5.6-luna
32thinking: high
33systemPromptMode: replace
34inheritProjectContext: false
35inheritSkills: false
36fastMode: false
37---
38
39Inspect the requested scope and report evidence-backed findings.
40```
41
42`tools` is a capability boundary. An omitted value inherits the child-safe
43catalogue, `tools: []` grants no tools, and an explicit list replaces the
44default. The child-safe catalogue contains only tools offered by the parent
45that are also available in the resolved child runtime; parent-only scheduling
46and extension tools are never inherited. Names unavailable to the child
47(including host-only extensions) and tools denied by `subagents.allowed_tools`
48are omitted from an explicit list; they never grant the child additional
49access. `model`, `provider`, `thinking`,
50the prompt mode, project/skill inheritance, and `fastMode` are resolved before
51the child is accepted. Spawn-level model, provider, reasoning, and fast-mode
52values take precedence where supplied.
53
54Children are always fresh conversations: they receive the delegated task and
55resolved host/profile context, never the parent transcript or hidden reasoning.
56They cannot recursively create more children.
57
58## Lifecycle and persistence
59
60The manager records each accepted child under its managed state root:
61
62```text
63subagents/<child-id>/
64 transcript.jsonl # accepted turns, finalized messages, and compaction checkpoints
65 owner.lock # host-ownership coordination; do not modify or remove
66 .transcript-backup-* # retained private pre-repair transcript, when repaired
67 metadata.json # rebuildable bounded state
68 result.json # latest outcome, final summary, artifacts
69 patch.diff # optional worktree capture
70```
71
72Acceptance is durable before the `subagent` tool's `spawn` action reports
73success. Finalized user, assistant, tool-call, and tool-result messages are
74journaled; streamed deltas and hidden reasoning are not exposed as ordinary
75history. A tool call is stored before execution and reconciliation repairs
76incomplete call/result pairs. A context-overflow recovery appends one
77`child.compacted` checkpoint carrying the replacement transcript; resume
78starts from the newest checkpoint, while the paged history view still shows
79everything appended before it.
80
81All children stop when the host exits. On the next start, queued or running
82turns are marked `interrupted`; zut never replays their task. Resume only with
83an explicit new prompt through the `subagent` tool's `resume` action, the
84child-session composer, or `/subagents resume <id> <prompt>`.
85
86Multiple zut processes may share a state root. Each resident journal has one
87host owner at a time. A process that finds a child owned elsewhere reports it
88as such and does not inspect, recover, or modify its transcript. Resume that
89child from its owning host or after the owner exits. On a subsequent safe
90reconciliation, zut repairs only the known legacy false-recovery sequence; it
91leaves any ambiguous journal corruption untouched. A repair retains the
92pre-repair transcript as `.transcript-backup-*`; it can contain private session
93data and is intentionally not removed automatically.
94
95The `subagent` tool's `status` action reports `owned_elsewhere: true` when
96another process owns a child. The field is omitted when false. A foreign-owned
97child cannot be resumed, or have its history or result read, from this process.
98
99The global scheduler admits the oldest eligible accepted prompt, runs at most
100one turn for each child, and defaults to six concurrent turns. Set
101`subagents.max_concurrent` to a positive limit to override it. Queueing is
102unlimited by default; a positive `subagents.queue_timeout` cancels an accepted
103prompt that has not received a slot and records its terminal failure durably.
104`subagents.allowed_tools` is an allowlist for child-visible tools and
105`subagents.allowed_roots` limits eligible child workspaces. Resident children
106have no cumulative token budget and no child-only step cap: a child inherits
107the parent's resolved limit, including the unlimited default. A turn is bounded
108by the provider context window, with one compaction recovery, and by an
109explicit parent `--max-steps`. Removed legacy
110settings, including `tui_subagent_position` and `subagents.budget_ratio`, are
111ignored. Resident journals written by older versions are read with explicit
112translation (an old `budget_exhausted` outcome reconciles as failure) or, for
113unknown versions, left untouched on disk and excluded from automatic
114discovery. Incompatible journals cannot be resumed; start a new child
115instead. Other journal recovery errors are still reported.
116
117Compatibility notes: new journals write version 3 and carry no budget
118fields, baselines, or exhaustion states. Version 2 archives are read with
119explicit translation and their transcripts are never rewritten by
120translation. `result.json` keeps a deprecated `handoff` field that stays
121empty for new results and remains readable for archives. The `subagent` tool's
122`status` action no longer exposes `budget` or `budget_source` fields.
123
124### Context reminders
125
126When a child's last-turn prompt reaches 85%, 90%, or 95% of its model context
127window, the runner injects a non-blocking reminder into the next provider
128request:
129
130```text
131Context usage is at NN% of the model window. Finish the current task, report
132results, limits, and remaining verifications, and do not start broad new work.
133```
134
135Each band fires at most once per child runner and reminders never block a turn.
136A jump straight to a higher band delivers one reminder for that band, and usage
137that falls does not re-deliver a band. Reminders travel as developer context in
138the live request; the durable transcript keeps only finalized history. Usage is
139the last-turn prompt size (input plus cache read/write tokens) against the
140resolved context window; an unknown window never triggers a reminder. The
141per-turn gauge resets when the host restarts and when a recovery compacts the
142context, so neither event reports a stale percentage. The band ladder itself
143advances at most once per child runner: a restart starts a fresh ladder, while a
144compacted child is reminded again only when usage reaches a higher band.
145
146### Context-overflow recovery
147
148A provider request that exceeds the model context window ends the turn. When
149the transcript holds at least four messages, the child recovers once per turn:
150it compacts the transcript, keeps the two most recent messages verbatim,
151journals the replacement as a `child.compacted` record, and continues the same
152turn. A compaction or persistence failure restores the pre-compaction
153transcript and fails the turn, and a second overflow stays terminal. Recovery
154never replenishes an explicit parent `--max-steps`: when the allowance is
155already spent, the checkpoint is still written for a later resume, but the turn
156is not continued.
157
158Explicit resume replays the newest checkpoint instead of the full append-only
159log. The history views (`/subagents logs`, `HistoryPage`, `subagent://` refs)
160still show the append-only log, including pre-compaction records. A build that
161predates checkpoint support cannot resume such a child correctly; downgrading
162is unsupported.
163
164The summarization request itself can be rejected when a single oversized
165message leaves nothing to summarize away. The turn then fails with the original
166provider error and no checkpoint is written, so the child keeps failing on
167resume until its transcript shrinks. Recovery is a best effort, not a
168guarantee.
169
170Retrieve the saved result without executing a model:
171
172```json
173{"action":"status","agent_id":"<child-id>","include_result":true}
174```
175
176Pass this to the `subagent` tool's `status` action, then reconcile the history
177and artifacts before repeating any side effects. The `subagent` tool's explicit
178`resume` action after a terminal failure continues the retained session,
179workspace, and cumulative cost. It does not automatically retry the task.
180Ordinary follow-ups continue the existing session.
181
182`required: true` makes a delegated result an obligation of the parent turn.
183Failed, cancelled, and interrupted required work remains
184unresolved until an explicit successful follow-up. Reading a saved result or
185accepting a recovery prompt does not satisfy the obligation. A host restart never
186retries it automatically.
187
188## Delegation ownership
189
190Interactive proactive delegation keeps the primary agent on the critical path.
191Process start says nothing about the task, and the workers it needs only become
192knowable once the user states the request. Routing therefore happens then: the
193reply that starts the work names the parts the primary keeps on the critical
194path and the profile that owns each delegable part, before it implements or
195spawns anything. It states plainly when nothing is worth delegating rather than
196forcing a worker. The routing guidance is part of the prompt only when
197launch-time policy exposes the spawn action.
198Before spawning, it selects useful local work and delegates only a concrete,
199bounded sidecar with a non-overlapping question, responsibility, package, or
200file set. Immediate blockers and tightly coupled work stay local. While a child
201is active, it owns that scope; the primary continues only its preselected
202independent work instead of repeating the investigation, review, testing, or
203implementation. If an explicit user request or active workflow hands blocking
204work to a child, the primary yields for the completion update. Once a worktree
205child succeeds, the primary may apply and verify its captured patch without
206redoing the delegated task.
207
208Explicit headless `--orchestrate` remains manager-only. Its primary divides the
209request into disjoint worker scopes, coordinates active children, and yields
210rather than implementing or reproducing delegated work. Children do not inherit
211the parent's strict orchestrator role. Headless orchestration waits for every
212accepted child before continuing its completion wave; `required: true`
213additionally creates a durable obligation. When proactive
214interactive delegation cannot spawn because of launch-time policy, the primary
215continues locally; a strict headless orchestrator instead reports the missing
216required capability.
217
218## Tools and slash commands
219
220The model-facing tool keeps one logical name and five actions, selected by its
221`action` argument. Launch-time gating is per action: `--tools subagent` grants
222every action, `--tools subagent:<action>` grants one, and `--no-tools` disables
223all of them.
224
225- `subagent` accepts an `action` of `spawn`, `status`, `stop`, `resume`, or
226 `interrupt`.
227 - `spawn` accepts `task`, optional `agent`, `model` and `provider`,
228 `reasoning`, `fast_mode`, `required`, `wait`, and `isolation` (`shared` or
229 `worktree`).
230 `wait` is an explicit whole-second value from 1 through 300; when omitted,
231 spawning returns immediately. A timed-out wait leaves the
232 accepted child active, whether it is queued or running. Do not retry that
233 task until it reaches a terminal failure, cancellation, or interruption. It
234 returns a logical `subagent://<id>` reference.
235 - `status` accepts optional `agent_id` and `include_result`, and returns
236 bounded current state for one child or the current set immediately. With
237 `agent_id` and `include_result: true`, it also reads the saved terminal
238 result without model execution. Without this option it remains
239 metadata-only; foreign-owned results cannot be read. Result-read errors
240 distinguish foreign ownership, a missing saved result, and permission
241 denial without exposing filesystem paths or saved content.
242 With `agent_id`, a running child also includes `activity`: a `phase`
243 (`waiting_for_model`, `writing`, `tools`, or `working`), the tail of its
244 visible text, and its active tools with truncated arguments. Hidden
245 reasoning is never exposed. `watch` (1–60 seconds, requires `agent_id`)
246 observes that activity and returns a `timeline` of phase and tool changes.
247 It returns early when the child stops running. Use it to inspect progress,
248 not to wait for completion. `pending_followups` counts follow-ups the
249 child has accepted but not read yet.
250 - `stop` accepts `agent_id` and stops one live child.
251 - `resume` accepts `agent_id`, `prompt`, optional `mode`, and optional
252 `wait`. `prompt` is an explicit follow-up prompt for an existing child.
253 Do not use `resume` solely to wait for existing work or ask for its result
254 again: yield for the automatic completion update. `queue` schedules another
255 turn and produces another completion.
256 After a terminal failure, inspect the saved result before resuming; resume
257 continues the retained session. `mode` controls how a follow-up reaches a
258 running child:
259 - `steer` (default) injects it into the current turn at the next tool or
260 model boundary, like typing while the main agent works. It adds no new
261 turn and no extra completion.
262 - `queue` runs it as a separate turn after the current one.
263
264 An idle or stopped child starts a new turn in either mode, and a steer
265 never jumps ahead of already queued turns. The response's `delivery` is
266 `steered` or `queued`. `wait` uses the same 1–300 second bound as `spawn`
267 and waits for the turn that answers the follow-up, returning its outcome or
268 reporting the timeout while the child stays active. A returned outcome can
269 be `dropped` when a queued follow-up never started. When the host accepts
270 the completion report, the summary and `undelivered` steers arrive in the
271 completion update; otherwise the outcome includes them.
272 - `interrupt` accepts `agent_id` and cancels only the child's running turn.
273 Unlike `stop`, the child stays live with its transcript, so a later
274 `resume` such as "report what you have" continues with full context.
275 Queued follow-ups are dropped. It fails when no turn is running.
276
277When a turn ends before the child reads a steered follow-up, for example after
278`stop`, `interrupt`, or a failure, the completion update lists it as
279`undelivered`. Queued follow-ups that never started are reported as `dropped`.
280Neither appears as an interrupted task.
281
282Child execution started by the `subagent` tool's `spawn` or `resume` action is
283asynchronous unless it receives an explicit `wait` value. For an unwaited call,
284completion arrives through the host’s typed completion update; the `subagent`
285tool's `status` action returns immediately and does not wait for completion. Do
286not use sleep loops, repeated status calls, journal files, or terminal UI
287inspection as a completion signal.
288When the host accepts a completion report, a completed `spawn` or `resume`
289wait returns terminal status and `report_delivery: host_update`; the full report
290arrives only through the completion update, not again in the tool result.
291If no host observer accepts the report, the tool result includes it inline.
292An expired wait does not suppress later completion delivery. Cancelling the
293parent turn discards pending completion updates; cancelling only a tool wait
294leaves host tracking intact.
295In interactive mode, a result received while the primary is busy enters the
296visible **sliding in** queue and reaches the model at its next safe boundary,
297without interrupting a model request or tool call and without waiting for other
298children. Results already queued are not repeated when the parent turn ends.
299Undelivered results remain queued after a provider or compaction error for the
300next turn; they do not automatically retry the failed request. Explicit
301cancellation clears pending queue entries. The queue is in memory, while the
302child’s saved result remains available through the `subagent` tool's `status`
303action.
304When the primary is idle, each child completion immediately starts the next
305parent turn instead of waiting for its siblings. The host update names the
306finished child and lists sibling agent IDs that are still running. A completion
307that arrives while that parent turn is active slides into its queue. Headless
308orchestration still waits for every accepted child before its next parent turn.
309Successful completions include the final visible assistant summary, capped at
310256 KiB; open the child session for the complete durable transcript.
311
312`/subagents` opens the resident-child list, ordered by the latest state change.
313Each row leads with the profile (or model), shows a human terminal state such
314as `completed`, a relative update time, and a short ID. Press Down from the
315main composer to open this list without clearing a draft when a child exists.
316Use arrows and Enter to open a child session; `/subagents new <task>` creates a child; `/subagents logs <id>`
317opens its history; `/subagents result <id>` shows the bounded final summary;
318`kill <id>` stops it; and `resume <id> <prompt>` continues it. A prompt sent
319from the child composer or `resume` to a running child steers its current turn.
320
321The child session uses the same transcript renderer as the main session.
322Recent history is bounded and loaded asynchronously; PgUp asks for an older
323page. Up/Down preserves the current reading position, and PgDn returns to the
324live tail after unread updates accumulate. The screen combines durable finalized
325history with an immutable in-memory projection of the active turn. Enter submits
326the local composer only after the manager durably accepts it; Esc closes the session. History may contain task
327text, tool arguments, tool results, and source-derived output, so treat it as
328private local session data.
329
330## Worktrees and references
331
332Shared children use the host working directory. With `isolation: "worktree"`,
333zut prepares a detached Git worktree and captures a patch and changed-file list
334on successful completion or non-cancelled failure. Failed turns retain
335partial work in the worktree, along with any captured patch and changed-file
336list. zut never applies a captured patch automatically. Failed or interrupted
337worktrees are retained for inspection; an idle successful worktree is cleaned
338when its child is explicitly stopped.
339
340Use the `subagent` tool's `status` action with `agent_id` and
341`include_result: true` to retrieve the saved result, `changed_files`, and
342`patch_ref` when a patch was captured. The
343patch bytes are stored in `subagents/<child-id>/patch.diff` under the managed
344state root shown above; logical references are identifiers, not filesystem
345paths. Inspect the retained worktree and patch before resuming or applying
346partial changes.
347
348New terminal journal records also save the capture metadata, so reconciliation
349can restore it if `result.json` is missing or corrupt. Older records remain
350readable, but cannot reconstruct artifact metadata they never recorded.
351
352Logical references avoid exposing runtime paths:
353
354```text
355subagent://<id>
356subagent://<id>/history
357subagent://<id>/result
358subagent://<id>/patch
359```
360
361## Provider caching
362
363Each main and child conversation sends a stable logical session ID and a new
364turn ID per accepted prompt to the provider layer. Provider adapters decide
365whether and how to use them: OpenAI/Codex translates a supported stable session
366into its cache key and routing header, while other adapters preserve deterministic
367request input and use only cache controls their provider/model/endpoint supports.
368An OpenAI-compatible wire shape is not itself evidence that a cache extension
369or transport feature is available. Models continue through their declared
370provider transport; a transport change must not change the logical session or
371turn identity used by the provider request.