返回 CodeWhale
SUBAGENTS.md
根目录 / docs / SUBAGENTS.md
1 # Fleet Workers and Sub-Agent Compatibility
2
3 Fleet roles are the user-facing vocabulary for delegated work: a parent
4 launches a focused `worker`, `scout`, `planner`, `reviewer`, `builder`,
5 `verifier`, or `consultant` through `agent` and gets back an `agent_id` plus transcript handle
6 while the worker runs. The internal runtime type is `FleetRole` (formerly
7 `SubAgentType`); the older role spellings (`general`, `explore`, `plan`,
8 `review`, `implementer`, `oracle`, …) remain accepted only as a persisted/deserialize
9 compatibility adapter during v0.9.x. New prompts and config should use Fleet
10 names.
11
12 Architecturally, sub-agents should not be a second execution substrate. The
13 durable primitive is the fleet-backed worker run described in
14 [`AGENT_RUNTIME.md`](AGENT_RUNTIME.md): retries, terminal status, receipts,
15 artifact refs, inspection, and restart behavior belong there. The
16 model-facing launcher is the single `agent` tool and detached work should
17 converge on the same lifecycle as Agent Fleet.
18
19 The current `agent` implementation delegates to the durable sub-agent runtime
20 while that cutover completes. It can still be useful for short in-session
21 delegation. Transient provider header/stream/time-out failures are retried with
22 backoff inside the child runtime before the worker is marked interrupted; if the
23 retry budget is exhausted, Codewhale preserves a checkpoint and returns a
24 continuation handle instead of leaving the parent to infer what happened. For
25 work that must survive process restarts, sleep, or remote execution, prefer
26 Fleet or a Workflow-backed fleet run.
27
28 Sub-agents inherit the parent's tool registry by default, and that includes
29 `agent` itself: children are built with `with_full_agent_surface_options`
30 (`crates/tui/src/tools/subagent/mod.rs:12164`) so they can recurse. `agent` is
31 filtered out of a child's catalog only when the depth budget is spent —
32 `can_spawn_child = !runtime.would_exceed_depth()` (`mod.rs:12145`), enforced at
33 `mod.rs:12324` and `:12469`. With the default depth of 3
34 (`DEFAULT_SPAWN_DEPTH`, `crates/config/src/lib.rs:1671`) a child can spawn
35 grandchildren. The removed `agent_open`/`agent_eval`/`agent_close` lifecycle
36 tools are gone from every registry, parent and child alike.
37
38 `agent` launches detached background work: cancelling the parent turn stops the
39 parent wait path, but it does not kill already-opened child runs.
40
41 This doc covers the role taxonomy and current compatibility controls. The active
42 orchestration surface is `agent`; see the sub-agent guidance in
43 `crates/tui/src/prompts/text.rs` (`AGENT_MODE`) and the in-line
44 tool description.
45
46 ## Role taxonomy
47
48 The `type` field on `agent` selects a Fleet posture for the child
49 (`agent_type` is accepted as a compatibility alias). Each role is a distinct
50 stance toward the work — not just a different label.
51
52 ## Maintainer posture
53
54 Sub-agents help Codewhale move faster, but the parent agent still owns the
55 maintainer decision. Use children to gather evidence, review patches, and run
56 verification while keeping the community posture in
57 [`AGENT_ETHOS.md`](AGENT_ETHOS.md): issues are open intake, PR gates are
58 review-load controls, and harvested work needs clear contributor credit.
59
60 When a child reviews community work, the parent should still inspect the PR
61 diff, linked issues, tests, and CI before merging, harvesting, closing, or
62 deferring it. A sub-agent's result is a working set, not a substitute for
63 stewardship.
64
65 | Role | Stance | Writes? | Shell posture | Typical use |
66 |---------------|----------------------------------------|---------|---------------|----------------------------------------------|
67 | `worker` | flexible; do whatever the parent says | yes | yes | the default; multi-step tasks |
68 | `scout` | read-only; map the relevant code fast | no | recon (net + bounded verify) | "find every call site of `Foo`; check the PR with gh" |
69 | `planner` | analyse and produce a strategy | minimal | minimal | "design the migration; don't execute" |
70 | `reviewer` | read-and-grade with severity scores | no | recon (net + bounded verify) | "audit this PR for bugs" |
71 | `builder` | land a specific change with min edit | yes | yes | "rewrite `bar.rs::Foo::bar` to do X" |
72 | `verifier` | run tests / validation, report outcome | no | test-focused | "run cargo test --workspace, report" |
73 | `consultant` | short-lived, high-reasoning counsel | no | none | "what are we missing in this design?" |
74 | `custom` | explicit narrow tool allowlist | depends | depends | locked-down dispatch with hand-picked tools |
75
76 Each role's full system prompt lives in
77 `crates/tui/src/tools/subagent/mod.rs` (search for
78 `*_AGENT_INTRO`). The prompt prefix loads automatically when the
79 child agent boots; the parent's assignment prompt becomes the first
80 turn's user message.
81
82 ## Context forking
83
84 `agent` starts fresh by default: the child gets its role prompt plus the
85 task you pass. Use `fork_context: true` when the child should continue from
86 the parent's current request prefix instead. In fork mode the runtime keeps the
87 parent prefill/prompt prefix byte-identical where available, appends a
88 structured state snapshot, then adds the sub-agent role instructions and task
89 at the tail. That preserves DeepSeek prefix-cache reuse while giving the child
90 the context needed for continuation, review, summarization, or compaction work.
91
92 Use fresh sessions for independent exploration. Use forked sessions when the
93 task depends on decisions, files, todos, or plan state already in the parent
94 transcript.
95
96 Forked state renders concrete Work progress from the To-do ledger — the sole
97 canonical Work surface, written by `work_update`. The child's
98 `<codewhale:fork_state>` block carries the same bounded body
99 (`crates/tui/src/work_grounding.rs`) that the parent's own requests carry, so a
100 fork continues from the parent's real progress position rather than a
101 paraphrase. That Work section is resolved when the spawn happens, so a
102 `work_update` earlier in the same parent turn is included.
103
104 Each agent then grounds on **its own** ledger: every sub-agent request carries
105 the same transient `<codewhale:work_state>` tail rendered from that agent's
106 private To-do list (#4810), refreshed after the agent's own `work_update`. It is
107 request-scoped — never stored in the child transcript or its system prefix — so
108 a worker can never read or write a parent's or sibling's **private transient
109 tail**. A deliberately forked child still receives the bounded immutable parent
110 ledger snapshot described above as part of its fork context; it cannot mutate
111 that snapshot or keep reading later parent changes.
112
113 That same private ledger is what the child's in-transcript card shows. A
114 delegate card renders a bounded projection of **its own** agent's To-do — the
115 settled/total count, the in-progress item always included, up to three rows, and an
116 explicit `… +N more` when the bound elides the rest — built by
117 `card_todo_projection` from the same snapshot, priority order, and sanitizer the
118 model-facing body uses. A card only ever consumes an envelope whose `agent_id`
119 matches it, so a parent's list never appears under a child and no sibling's list
120 appears under another. An agent that has stated no work shows no To-do rows at
121 all rather than a placeholder task, and a terminal card keeps the last snapshot
122 its agent actually published. Fanout cards stay a dot grid and do not show child
123 To-do: with many workers behind one card there is no truthful place to hang a
124 single ledger. A child To-do appears only when the runtime already represents
125 that child as its own delegate card.
126
127 The durable task/Fleet ledger still owns lifecycle state. `update_plan` is no
128 longer reachable by a model: `model_visible()` returns `false`
129 (`crates/tui/src/tools/plan.rs:408-413`), so it is filtered out of the API tool
130 list and never appears to a child. It survives only to replay older transcripts.
131 Strategy that used to go there now goes in the response body, and lifecycle
132 state goes in `work_update`.
133
134 ## Worktree isolation
135
136 For parallel edit lanes, launch the child with `worktree: true`. Codewhale
137 creates a fresh git worktree and branch for that child, runs the child from the
138 isolated checkout, and reports the resulting workspace/branch in the returned
139 session projection and worker record. By default the branch is
140 `codex/agent-<name>-<id>` and the checkout lives beside the parent repo under
141 `.codewhale-worktrees/`, so the parent checkout stays clean.
142
143 Isolation is not write authority. A prompt-only worker starts read-only.
144 A writer also declares `write_authority: "workspace_write"` or
145 `"worktree_write"` and at least one normalized repo-relative `write_roots`,
146 `exact_files`, or `coordination_contracts` value. Active overlapping shared
147 claims fail before mutation; a real isolated worktree may proceed in parallel.
148
149 Optional fields:
150
151 - `worktree_branch`: exact branch to create.
152 - `worktree_base`: git ref to branch from; defaults to `HEAD`.
153 - `worktree_path`: exact checkout path. Relative paths stay under the default
154 sibling `.codewhale-worktrees/` root.
155
156 Do not combine `cwd` with `worktree`; `cwd` remains the manual escape hatch for
157 an already-created directory inside the parent workspace.
158
159 ## Delegation briefs
160
161 The parent should pass a compact brief instead of a loose paragraph. Use the
162 structured `dependencies` and `acceptance` arrays for bounded prerequisite facts
163 and observable checks; keep the focused objective in `prompt`. Do not copy raw
164 parent reasoning or an unbounded transcript.
165
166 ```
167 QUESTION:
168 SCOPE:
169 ALREADY_KNOWN:
170 EFFORT: quick | medium | thorough
171 STOP_CONDITION:
172 OUTPUT: VERDICT, EVIDENCE, GAPS, NEXT
173 ```
174
175 `scout` briefs default to quick, read-only investigation (no writes, but
176 network reach and the bounded verification surface are available for real
177 recon). About 3-5 tool calls
178 is enough for quick exploration: orient, search, read the decisive lines, and
179 return. Do not repeat `ALREADY_KNOWN` work unless evidence contradicts it. Review
180 and verifier briefs can spend more calls, but should stop after decisive
181 evidence. Builder and repair-style briefs should use checkpoints before
182 scope expansion or after repeated failures rather than a tiny call cap.
183
184 Good delegation prompt examples:
185
186 ```text
187 QUESTION: Does PR #3124 introduce release-risk behavior around provider routing?
188 SCOPE: PR #3124 diff, linked issue, provider routing tests, docs/PROVIDERS.md.
189 ALREADY_KNOWN: Branch is hunter/0.8.62-glm-subagents; workspace version stays 0.8.61.
190 EFFORT: medium
191 STOP_CONDITION: Return once you have either one BLOCKER/MAJOR issue or enough evidence for no MAJOR+ issues.
192 OUTPUT: VERDICT, EVIDENCE with file:line refs or PR refs, GAPS, NEXT.
193 ```
194
195 ```text
196 QUESTION: Where is the child-agent prompt assembled?
197 SCOPE: crates/tui/src/prompts*, crates/tui/src/tools/subagent/*.
198 ALREADY_KNOWN: The model-facing launcher is only `agent`; do not look for removed lifecycle tools.
199 EFFORT: quick
200 STOP_CONDITION: Stop after identifying the prompt source files and the function that wraps assignment text.
201 OUTPUT: VERDICT, EVIDENCE, GAPS, NEXT.
202 ```
203
204 ```text
205 QUESTION: Is the focused prompt/subagent test filter valid, and what fails if not?
206 SCOPE: cargo test -p codewhale-tui --bin codewhale-tui --locked prompt; subagent filter if needed.
207 ALREADY_KNOWN: Do not fix failures; capture exact command, exit code, and first relevant assertion.
208 EFFORT: medium
209 STOP_CONDITION: Stop after one clean PASS or one reproducible failing assertion with command evidence.
210 OUTPUT: VERDICT, EVIDENCE, GAPS, NEXT.
211 ```
212
213 ### When to pick which role
214
215 - **`worker`** — when the task is "do this whole thing", not "go
216 look", "design", or "verify". This is the right default; reach for
217 a more specific role only when the posture matters.
218 - **`scout`** — when the parent needs evidence before deciding what
219 to do next. Scouts are cheap and fast; open 2–3 in parallel
220 for independent regions.
221 They should orient first: confirm the project root, read relevant
222 `AGENTS.md`/`README.md` guidance in unfamiliar trees, search only the
223 likely scope, and return `path:line-range` evidence instead of a narrative
224 tour. The role name to use is `scout`.
225 - **`planner`** — when the parent has an objective but no executable
226 decomposition. Planners write artifacts (`work_update` items for the ledger,
227 strategy in the response body) but don't carry them out.
228 - **`reviewer`** — when there's already a change and the parent wants
229 it graded. Reviewers don't patch — they describe the fix in the
230 finding so the parent can dispatch a builder if the verdict
231 is "fix it".
232 - **`builder`** — when the change is already specified and just
233 needs to land. Builders stay tightly scoped: minimum edit, no
234 drive-by refactoring, run a quick verification before handing back.
235 - **`verifier`** — when the parent needs an authoritative pass/fail
236 on the test suite or other validation. Verifiers don't fix
237 failures; they capture the failing assertion + stack and put fix
238 candidates under RISKS.
239 - **`consultant`** — when the operator wants a high-leverage second opinion
240 before cheaper execution continues. Consultants read enough to ground a
241 recommendation, but cannot write or run shell commands. `oracle` and
242 `advisor` remain accepted only when loading older requests or persisted
243 records; new prompts, receipts, and UI use `consultant`.
244 - **`custom`** — only when the parent needs to constrain the tool
245 set explicitly. Pass the allowlist via the `allowed_tools` field
246 on legacy/internal sub-agent records; the model-facing `agent` tool keeps the
247 public schema intentionally small.
248
249 ### Aliases
250
251 The model can spell each role multiple ways:
252
253 | Canonical | Aliases |
254 |---------------|------------------------------------------------------------------|
255 | `worker` | `general`, `default`, `general-purpose` |
256 | `scout` | `explore`, `explorer`, `exploration` |
257 | `planner` | `plan`, `planning`, `awaiter` |
258 | `reviewer` | `review`, `code-review`, `code_review` |
259 | `builder` | `implementer`, `implement`, `implementation` |
260 | `verifier` | `verify`, `verification`, `validator`, `tester` |
261 | `consultant` | `oracle`, `advisor` (compatibility input only) |
262 | `custom` | (none; explicit `allowed_tools` array required) |
263
264 All matching is case-insensitive. Unknown values produce a typed
265 error listing the accepted set, so the model can self-correct on
266 the next turn.
267
268 ## Concurrency cap
269
270 Up to **64** sub-agents run concurrently by default (`DEFAULT_MAX_SUBAGENTS`),
271 configurable via `[subagents].max_concurrent` in `~/.codewhale/config.toml` up to
272 the hard ceiling of **128** (`MAX_SUBAGENTS`). The session admits a bounded
273 queue of up to **1024** running plus queued sub-agents by default
274 (`MAX_SUBAGENT_ADMISSION`, `crates/tui/src/config/subagent_limits.rs:21`), so a turn can
275 request broad fan-out and let the manager drain it without creating an
276 unbounded population.
277
278 By default every admitted child may start immediately — there is no artificial
279 throttle. If you want gentler fan-out, lower `[subagents].launch_concurrency`
280 (how many direct children start at once); children beyond that limit **queue**
281 for a launch slot rather than bursting. `launch_concurrency` defaults to the
282 resolved `max_subagents` cap. (The pre-v0.8.61 `interactive_max_launch` key is
283 still accepted as a deprecated alias; the new key wins when both are set.)
284
285 High-fanout Workflows can tune that bounded population with `[subagents]
286 max_admitted` (aliases: `max_total`, `admission_limit`). That total ceiling
287 counts both **running** and **queued** agents, while `launch_concurrency` keeps
288 instantaneous execution bounded. Completed / failed / cancelled records persist
289 for inspection but don't occupy an admission slot. Agents that lost their
290 `task_handle` (e.g. across a process restart) also don't count against the cap.
291
292 Provider profiles let one config stay aggressive for direct API routes while
293 keeping subscription or aggregator routes gentle. Every key under
294 `[subagents.providers.<provider>]` inherits from `[subagents]` when omitted.
295 Provider keys accept canonical names such as `deepseek`, `zai`, `openrouter`,
296 and aliases such as `glm` for Z.ai:
297
298 ```toml
299 [subagents]
300 # Global fallback for providers without a profile.
301 max_concurrent = 20
302 launch_concurrency = 20
303 max_admitted = 200
304 max_depth = 6
305 token_budget = 100000
306
307 [subagents.providers.deepseek]
308 # Direct API key with room to fan out.
309 max_concurrent = 20
310 launch_concurrency = 20
311 max_admitted = 200
312
313 [subagents.providers.glm]
314 # Z.ai / GLM subscription-style route: keep pressure tight.
315 max_concurrent = 4
316 launch_concurrency = 3
317 max_admitted = 12
318 max_depth = 2
319 api_timeout_secs = 180
320 heartbeat_timeout_secs = 240
321
322 [subagents.providers.openrouter]
323 max_concurrent = 5
324 launch_concurrency = 3
325 max_admitted = 20
326
327 [subagents.providers.anthropic]
328 max_concurrent = 3
329 launch_concurrency = 2
330 max_admitted = 12
331 ```
332
333 Use `/config subagents status` to see both the global values and the active
334 provider's resolved fanout, depth, and timeout profile.
335
336 ## Token budget governor
337
338 Set `[subagents].token_budget` to give each root `agent` run an aggregate
339 token ceiling shared by that child and all of its descendants. When no budget
340 is configured, behavior is unchanged.
341
342 `token_budget` is **not** a field on the model-facing `agent` schema, and its
343 absence is deliberate — `crates/tui/src/tools/subagent/tests.rs:4260-4263`
344 asserts it, on the grounds that "ad-hoc children should inherit the generous
345 runtime budget; exposing an optional cap invites accidental micromanagement."
346 The parser still accepts the key (plus the `tokenBudget`/`max_tokens` aliases,
347 `mod.rs:10620`) so Workflow-shaped callers that construct the call themselves
348 can scope a budget, but the model is never told the field exists. Configure it
349 through `[subagents].token_budget` instead.
350
351 Provider-reported input and output tokens are folded into the worker record as
352 each child model call completes. The persisted `usage` object shows the
353 worker's own totals plus aggregate `budget_spent_tokens` and
354 `budget_remaining_tokens` for the shared scope. Once the shared scope is
355 exhausted, further descendant spawns are rejected with an actionable message
356 instead of opening more agents into a spent pool.
357
358 ## Per-role models (#3018)
359
360 Children can run on a different model than the parent. Two config surfaces
361 feed the same override map (`[subagents.models]` keys win on conflict, keys
362 are case-insensitive):
363
364 ```toml
365 [subagents]
366 default_model = "deepseek-v4-flash" # fallback for every role
367 worker_model = "deepseek-v4-pro" # worker
368 scout_model = "deepseek-v4-flash" # scout
369 planner_model = "deepseek-v4-flash" # planner
370 reviewer_model = "deepseek-v4-pro" # reviewer
371 custom_model = "deepseek-v4-pro" # custom
372
373 [subagents.models]
374 # Free-form role → model map; any role alias accepted by agent works.
375 builder = "deepseek-v4-pro"
376 ```
377
378 The v0.9.x convenience keys `explorer_model`, `awaiter_model`, and
379 `review_model` remain accepted as deprecated aliases so existing config files
380 do not break.
381
382 Model ids may be **any model the active provider accepts** — validation is
383 provider-aware and happens at spawn time, not load time. On the official
384 DeepSeek API only DeepSeek ids are accepted; every other provider passes the
385 id through to the provider API, which is the authority. A non-DeepSeek
386 example:
387
388 ```toml
389 provider = "moonshot"
390 model = "kimi-k2.7-code"
391
392 [subagents]
393 worker_model = "kimi-k2.6"
394 ```
395
396 Model ids are validated the same way when applied to a child route; an invalid
397 id on the official DeepSeek API fails the spawn with the accepted-id list
398 instead of an opaque provider 400.
399
400 With `/model auto`, sub-agent routing is provider-aware too: providers with a
401 known big/cheap pair (DeepSeek, and the hosted DeepSeek routes on NVIDIA NIM,
402 OpenRouter, Novita, SiliconFlow, SGLang, vLLM) route between that pair;
403 providers without a known cheap tier (e.g. Ollama, Moonshot) skip the
404 network router and keep children on the session model.
405
406 ## Per-profile provider routes (#3965)
407
408 `[subagents.models]` changes the child model within the active provider. To pin
409 a child to a different provider, use a Fleet/AgentProfile and pass it to the
410 model-facing `agent` tool with `profile`. The profile's explicit `provider` +
411 `model` fields win over the parent session route; omitting `provider` preserves
412 the existing inherit behavior.
413
414 Example: keep the parent session on DeepSeek, but run a formatter child on a
415 local LM Studio OpenAI-compatible endpoint:
416
417 ```toml
418 # ~/.codewhale/config.toml or workspace config
419 provider = "deepseek"
420
421 [providers.deepseek]
422 api_key = "YOUR_DEEPSEEK_KEY"
423
424 [providers.lm-studio]
425 kind = "openai-compatible"
426 base_url = "http://127.0.0.1:1234/v1"
427 api_key = "lm-studio"
428 model = "qwen-2.5-7b"
429 ```
430
431 ```toml
432 # .codewhale/agents/local-formatter.toml
433 id = "local-formatter"
434 role_hint = "formatter"
435 provider = "lm-studio"
436 model = "qwen-2.5-7b"
437 reasoning_effort = "off"
438
439 [instructions]
440 text = "Use small, local edits. Keep formatting changes mechanical."
441 ```
442
443 Then call `agent(profile: "local-formatter", prompt: "...")`. In-process
444 children build a client for `lm-studio`; Fleet workers forward
445 `--provider lm-studio` to `codewhale exec`, which resolves the same
446 `[providers.lm-studio]` table. Unknown or unconfigured provider ids fail the
447 spawn rather than silently falling back to the parent provider.
448
449 ## Per-step API timeout (#1806, #1808)
450
451 Each sub-agent step wraps its DeepSeek `create_message` call in a
452 per-step timeout so a single stuck request can't pin the parent's
453 completion wakeup channel indefinitely. The default is `600` seconds.
454 A timed-out attempt is retried with exponential backoff (up to 5
455 retries) before the step interrupts with a preserved checkpoint.
456 Long-thinking children that legitimately exceed that, for example
457 heavy plan or review work behind `agent`, can extend the timeout in
458 `~/.codewhale/config.toml`:
459
460 ```toml
461 [subagents]
462 api_timeout_secs = 900 # 15 minutes; clamped to 1..=3600
463 ```
464
465 Values are clamped to `1..=3600`. `0` and `unset` keep the `600`
466 second default.
467
468 ## Stale-agent heartbeat (#2614)
469
470 Running agents also track manager-visible progress. If a child stops emitting
471 progress for the heartbeat window, the manager auto-cancels it, releases its
472 sub-agent slot, and keeps the cancelled record inspectable through the returned
473 transcript handle and persisted worker record. The default is 5 minutes
474 (resolved to at least 30 seconds above `api_timeout_secs`, so 630 seconds
475 with the 600-second default API timeout):
476
477 ```toml
478 [subagents]
479 heartbeat_timeout_secs = 300 # clamped to 30..=3600
480 ```
481
482 The effective heartbeat is kept at least 30 seconds above
483 `api_timeout_secs`, so a configured long model request is not cancelled before
484 its own request timeout can fire.
485
486 ## Lifecycle
487
488 Each opened session produces a record that progresses through:
489
490 ```
491 Pending → Running → (Completed | Failed(reason) | Cancelled | Interrupted(reason))
492 ```
493
494 `Interrupted` fires when the manager detects a `Running` agent whose task
495 handle is gone — typically after a process restart that loaded the workspace's
496 persisted state from `.codewhale/state/subagents.v1.json`. The parent can open a
497 replacement session with the same assignment or treat it as a terminal state.
498
499 ### Session boundaries (#405)
500
501 Each `SubAgentManager` instance assigns itself a fresh `session_boot_id` on
502 construction. Every new session stamps the agent with that id; the workspace
503 state file records it for restart recovery.
504
505 Work-bar/status projections focus on current-session agents by default.
506 Prior-session agents that are not still running are treated as archived records
507 so the model does not mistake stale work for live work. This is a
508 *prior-session* rule only: agents that finished in the CURRENT session keep
509 their work-bar rows for the rest of the session (quiet completion), and their
510 details still open from those rows.
511
512 Records that loaded from a pre-#405 persisted state file (no
513 `session_boot_id` field) classify as prior-session because the
514 manager can't match them to the current boot.
515
516 ## Run receipts, follow-up, and takeover
517
518 Each compatibility sub-agent has a persisted worker record in
519 `.codewhale/state/subagents.v1.json`. The record is the current run-ledger
520 slice for sub-agent lanes until those lanes are backed directly by the fleet
521 ledger: it stores `run_id`, objective, role/model,
522 workspace/branch, lifecycle events, artifact refs, follow-up target, takeover
523 target, usage provenance, and verification provenance.
524
525 `agent` returns a session projection with these fields at the top level and
526 inside `worker_record`. The normal parent contract is not polling: keep working
527 and consume the completion event when the child finishes. If audit detail is
528 needed, inspect the returned `transcript_handle` with `handle_read`.
529
530 Legacy follow-up delivery is retained only for old transcripts and internal
531 recovery. If a message was delivered, the worker record stores a bounded preview
532 and timestamp. New model-facing flows should open a replacement `agent` when a
533 child's assignment no longer fits.
534
535 Artifacts are symbolic refs. Use `handle_read` on the returned
536 `transcript_handle` for transcript details, and treat `result_summary` as a
537 child self-report unless `verification.status` points to a separate gate or
538 receipt. `usage.status` is `unknown` until provider usage is reported; then it
539 switches to `reported`, or `budget_exhausted` when a configured shared token
540 budget has no remaining tokens.
541
542 ## Output contract
543
544 Every sub-agent ends with five Markdown headings, in this order:
545
546 ```
547 ### SUMMARY one paragraph; what you did and what happened
548 ### EVIDENCE path:line-range citations and key findings; one bullet each
549 ### CHANGES files modified, with one-line descriptions; "None." if read-only
550 ### RISKS what could go wrong / what the parent should double-check
551 ### BLOCKERS what stopped you; "None." if you finished cleanly
552 ```
553
554 They are `### HEADING` lines, not `HEADING:` labels, and `EVIDENCE` comes
555 before `CHANGES`. The exact format lives in `crates/tui/src/prompts/text.rs`
556 (`SUBAGENT_OUTPUT_FORMAT`, :414-422) and `crates/tui/src/prompts.rs:3222`
557 asserts every heading against it.
558 The parent reads `EVIDENCE` as a working set for the next turn, so
559 scouts and reviewers should be precise here.
560
561 ## Memory and the `remember` tool (#489)
562
563 Sub-agents share the parent's native memory store when memory is enabled
564 (`[memory] enabled = true` or `DEEPSEEK_MEMORY=on`). They can
565 append durable notes via the `remember` tool — handy for a
566 scout that discovers a project convention worth carrying across
567 sessions, or a verifier that learns "this test is flaky".
568
569 `remember` takes a `scope` of `global` or `workspace`
570 (`crates/tui/src/tools/remember.rs:79-108`) and writes through
571 `NativeMemoryStore` to `~/.codewhale/memory/global/MEMORY.md` or
572 `~/.codewhale/memory/workspace/<id>/MEMORY.md`. Writes do not go through the
573 standard write-approval flow. The legacy single-file `memory.md` path was
574 removed in v0.9.4 (remember.rs:165); see `docs/MEMORY.md` for the full layout.
575
576 ## Implementation notes
577
578 - Source: `crates/tui/src/tools/subagent/mod.rs`.
579 - Persisted state: `<workspace>/.codewhale/state/subagents.v1.json`. Schema
580 version `1` (forward-compatible — new optional fields use
581 `#[serde(default)]`).
582 - Worker records are pruned by time: completed / failed / cancelled /
583 interrupted records are evicted after the same retention window used for
584 finished agents (default 1h, `COMPLETED_AGENT_RETENTION`). Running /
585 starting / waiting records are preserved. The hard cap of 256 records
586 remains as a safety bound (#4217).
587 - `SubAgentRuntime::background_runtime()` starts from `child_runtime()` but
588 replaces the turn-scoped child token with a fresh cancellation token, so
589 parent turn cancellation does not stop detached background sessions.
590 - The `is_running` check ignores agents whose `task_handle` is
591 `None`; this avoids counting persisted-but-detached records
592 toward the concurrency cap (#509).
593 - `SharedSubAgentManager` is `Arc<RwLock<...>>` — read paths use
594 read locks so `/agents` and the sidebar projection don't block
595 the main loop during multi-agent fan-out (#510).
596
596 lines MARKDOWN