pi-subagents 0.57.0 → 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +104 -0
- package/docs/agents.md +18 -9
- package/docs/configuration.md +4 -4
- package/docs/extension-api.md +40 -1
- package/docs/models.md +27 -4
- package/docs/observability.md +1 -1
- package/docs/tool-reference.md +92 -6
- package/docs/workflows.md +115 -0
- package/package.json +3 -1
- package/prompts/review-loop.md +2 -2
- package/skills/council-mode/SKILL.md +1 -1
- package/skills/pi-subagents/SKILL.md +3 -1
- package/skills/pi-subagents/references/execution-controls.md +6 -2
- package/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
- package/skills/pi-subagents/references/prompting-and-roles.md +26 -5
- package/src/agents/agent-management.ts +28 -17
- package/src/agents/agent-serializer.ts +9 -2
- package/src/agents/agents.ts +103 -27
- package/src/agents/runtime-agent-events.ts +70 -0
- package/src/agents/runtime-agent-registry.ts +19 -18
- package/src/api/agents.ts +10 -5
- package/src/api/background-work.ts +5 -1
- package/src/api/delegation.ts +0 -7
- package/src/api/preflight.ts +32 -10
- package/src/extension/fanout-child.ts +5 -3
- package/src/extension/index.ts +66 -27
- package/src/extension/public-execution.ts +15 -2
- package/src/extension/rpc.ts +35 -14
- package/src/extension/schemas.ts +37 -12
- package/src/extension/tool-description.ts +25 -6
- package/src/integrations/herdr-status.ts +5 -0
- package/src/intercom/result-intercom.ts +2 -0
- package/src/profiles/profiles.ts +5 -6
- package/src/runs/background/active-async-capacity.ts +2 -2
- package/src/runs/background/async-execution.ts +78 -46
- package/src/runs/background/async-job-tracker.ts +14 -12
- package/src/runs/background/async-resume.ts +29 -27
- package/src/runs/background/async-status-snapshot.ts +23 -261
- package/src/runs/background/async-status.ts +68 -7
- package/src/runs/background/chain-append.ts +8 -3
- package/src/runs/background/chain-root-attachment.ts +60 -8
- package/src/runs/background/fleet-view.ts +21 -11
- package/src/runs/background/notify.ts +184 -9
- package/src/runs/background/result-delivery-ownership.ts +45 -0
- package/src/runs/background/result-files.ts +2 -1
- package/src/runs/background/result-watcher.ts +29 -10
- package/src/runs/background/resume-guidance.ts +1 -1
- package/src/runs/background/retained-children.ts +1 -1
- package/src/runs/background/run-status.ts +18 -8
- package/src/runs/background/scheduled-runs.ts +86 -7
- package/src/runs/background/stale-run-reconciler.ts +10 -4
- package/src/runs/background/steering.ts +4 -14
- package/src/runs/background/subagent-runner.ts +389 -350
- package/src/runs/background/subagent-wait.ts +58 -10
- package/src/runs/background/terminal-run-index.ts +1 -1
- package/src/runs/background/wait-completions.ts +22 -1
- package/src/runs/background/wait-config.ts +23 -9
- package/src/runs/background/wait-tool.ts +9 -2
- package/src/runs/foreground/async-steering-action.ts +2 -2
- package/src/runs/foreground/execution.ts +134 -121
- package/src/runs/foreground/foreground-control.ts +3 -0
- package/src/runs/foreground/foreground-history.ts +1 -0
- package/src/runs/foreground/subagent-executor.ts +527 -257
- package/src/runs/foreground/workflow-detach-reconcile.ts +130 -120
- package/src/runs/shared/abort-recovery.ts +119 -0
- package/src/runs/shared/async-status-projection.ts +463 -0
- package/src/runs/shared/child-identity.ts +19 -4
- package/src/runs/shared/child-launch-plan.ts +151 -0
- package/src/runs/shared/completion-evidence.ts +89 -0
- package/src/runs/shared/completion-guard.ts +5 -4
- package/src/runs/shared/dynamic-fanout.ts +3 -3
- package/src/runs/shared/fast-mode-extension.ts +5 -5
- package/src/runs/shared/host-step-status.ts +230 -0
- package/src/runs/shared/lane-metadata.ts +105 -0
- package/src/runs/shared/launch-cwd.ts +16 -0
- package/src/runs/shared/long-running-guard.ts +2 -1
- package/src/runs/shared/mcp-config-sources.ts +422 -0
- package/src/runs/shared/mcp-direct-tool-allowlist.ts +221 -158
- package/src/runs/shared/mcp-direct-tool-grant.ts +197 -0
- package/src/runs/shared/model-exclusions.ts +12 -0
- package/src/runs/shared/model-fallback.ts +25 -6
- package/src/runs/shared/nested-events.ts +6 -2
- package/src/runs/shared/nested-render.ts +7 -3
- package/src/runs/shared/parallel-handoff.ts +419 -7
- package/src/runs/shared/parallel-utils.ts +15 -1
- package/src/runs/shared/pi-args.ts +81 -8
- package/src/runs/shared/single-output.ts +44 -4
- package/src/runs/shared/subagent-prompt-runtime.ts +98 -13
- package/src/runs/shared/worktree-cleanup-plan.ts +847 -0
- package/src/runs/shared/worktree.ts +18 -0
- package/src/shared/child-session-name.ts +46 -0
- package/src/shared/extension-context.ts +24 -0
- package/src/shared/formatters.ts +11 -2
- package/src/shared/launch-contract.ts +5 -1
- package/src/shared/settings.ts +9 -103
- package/src/shared/types.ts +240 -30
- package/src/shared/utils.ts +41 -84
- package/src/slash/delegation-adapters.ts +1 -8
- package/src/slash/delegation-request.ts +0 -4
- package/src/slash/slash-bridge.ts +1 -2
- package/src/slash/slash-commands.ts +369 -90
- package/src/slash/slash-live-state.ts +22 -11
- package/src/slash/subagents-admin.ts +3 -0
- package/src/tui/fleet-status.ts +125 -74
- package/src/tui/fleet.ts +11 -5
- package/src/tui/render.ts +330 -33
- package/src/watchdog/turn-delta.ts +1 -1
- package/src/workflows/chat-progress.ts +6 -3
- package/src/workflows/host-command.ts +230 -0
- package/src/workflows/scripted-workflow.ts +496 -35
- package/src/workflows/workflow-child-summary.ts +9 -5
- package/src/workflows/workflow-preflight.ts +270 -0
- package/src/workflows/workflow-receipt.ts +79 -5
- package/src/workflows/workflow-settlement.ts +246 -0
- package/src/runs/shared/turn-budget.ts +0 -98
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,110 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.59.0] - 2026-08-28
|
|
6
|
+
|
|
7
|
+
### Highlights
|
|
8
|
+
- Run host commands from workflow scripts with safer saved output and clearer command results.
|
|
9
|
+
- Build sequential parallel workflows with `runs.lanes(...)`, launch preflight labels, and better retained-resume behavior.
|
|
10
|
+
- See cleaner async status, child labels, and worktree handoff details without extra setup.
|
|
11
|
+
- Recover more reliably from stale contexts, provider aborts, missing outputs, malformed MCP metadata, and Windows file locks.
|
|
12
|
+
- Control live workflow children from more places, including non-TUI and RPC hosts.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- Add `runs.host(...)` command steps to `workflowScript`, with required timeouts, saved output, and status and receipt evidence (#1648).
|
|
16
|
+
- Add CI and gate monitor rows that record monitor kind, terminal verdict, freshness, and report pointers in workflow status and receipts.
|
|
17
|
+
- Persist workflow lane metadata in child status, receipts, and existing worktree handoff manifests, including display-only worktree paths and branches.
|
|
18
|
+
- Add `runs.lanes(...)` for parallel sequential workflow stages with per-lane results and retained-resume support (#1633).
|
|
19
|
+
- Add display-only `preflight` lane metadata for workflowScript launches, with coverage warnings and planned-lane rendering in launch, status, and live-card views.
|
|
20
|
+
- Add a plan-only `worktree.cleanup` management action that records a cleanup plan without removing worktrees or branches.
|
|
21
|
+
- Give every subagent child session a human-readable display name, and include it in result, progress, status, workflow, nested, and intercom payloads. Thanks to [@yanqianglu](https://github.com/yanqianglu) for #1615.
|
|
22
|
+
- Add `/subagents-steer <run-id> [--child <child-id>] <message>` so non-TUI sessions and RPC hosts can steer live async runs. Thanks to [@yanqianglu](https://github.com/yanqianglu) for #1608.
|
|
23
|
+
- Add explicit `allowNestedSubagents` agent authorization for nested fanout without replacing inherited tools or extensions. Thanks to [@tutu359](https://github.com/tutu359) for #1587.
|
|
24
|
+
- Accept a child id on `/subagents-stop <run-id> <child-id>` so one child of a multi-child async run can be stopped without stopping the whole run. Thanks to [@yanqianglu](https://github.com/yanqianglu) for #1603.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- Reduce noisy launch, status, output, settings, and worktree cleanup messages without changing behavior.
|
|
28
|
+
- Include a direct resumable child id in missing workflow receipt guidance when retained status proves it is safe.
|
|
29
|
+
- Clarify `workflowScript` contracts for retained resume keys and durable child output paths.
|
|
30
|
+
- Record merge or supersession evidence in existing worktree handoff manifests and show cleanup eligibility without removing anything.
|
|
31
|
+
- Show optional lane and work-item context in async status rows, including phase, gate, next action, output, run reference, and stale or blocked state.
|
|
32
|
+
- Show workflow child labels and phases in async status progress while preserving stable workflow keys.
|
|
33
|
+
- Remove assistant turn budgets, including hard termination, wrap-up prompt injection, and launch configuration.
|
|
34
|
+
- Split internal launch, status, settlement, evidence, and direct-MCP planning code into smaller modules without changing public behavior.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
- Match detached workflow completion by exact child identity, keep host gate rows in snapshots, and report missing host verdicts as inconclusive.
|
|
38
|
+
- Replace explicit `runs.host(...)` output files atomically inside their verified directory, and retry transient Windows destination locks.
|
|
39
|
+
- Reject malformed MCP direct-tool server and metadata-cache fields when JSON is loaded.
|
|
40
|
+
- Preserve live composite child tool-call ids for `cursor-native`, so Cursor MCP results keep matching pending execs. Thanks to [@moofone](https://github.com/moofone) for #1677 and #1678.
|
|
41
|
+
- Ignore stale cached UI contexts during background status refresh and session lifecycle cleanup (#1670).
|
|
42
|
+
- Compact workflow preflight status in default TUI and status views while keeping full details available when expanded (#1668).
|
|
43
|
+
- Give `runs.lanes(...)` stage-0 retained-resume validation actionable `runs.run(...)` guidance instead of a generic error (#1657).
|
|
44
|
+
- Remove the remaining `lane:` prefix from operator-facing async status rows in the TUI (#1658).
|
|
45
|
+
- Allow scheduled project roots shared through a registered Git worktree's `.pi` symlink while rejecting unrelated or unproven Git-layout escapes. Thanks to [@sususu98](https://github.com/sususu98) for #1656.
|
|
46
|
+
- Include delegated child usage in subagent tool results and `/subagent-cost`, including completed async workflow children and parent compaction usage with persisted workflow-receipt recovery when needed (#1662, #1666). Thanks to [@Geraldo-Morais](https://github.com/Geraldo-Morais) for #1662 and [@jf88888](https://github.com/jf88888) for #1666.
|
|
47
|
+
- Avoid false preflight mismatch warnings for generated `runs.lanes(...)` stage keys (#1649).
|
|
48
|
+
- Accept long host tool-call ids in workflow child summaries, matching the existing 4,096-byte session id bound. Thanks to [@SudoKillMe](https://github.com/SudoKillMe) for #1653.
|
|
49
|
+
- Keep an async `workflowScript` continuation live while an awaited child coordinates with its supervisor, so later sequential steps still run (#1634).
|
|
50
|
+
- Stop stale extension and slash-command contexts from escaping during reload or session replacement.
|
|
51
|
+
- Include saved workflow child output paths and inline previews in completion notices (#1629).
|
|
52
|
+
- Format million-scale context limits as `1M` instead of `1000k` in live status displays.
|
|
53
|
+
- Restore active workflow children under their workflow parent in Fleet Status after reload, while keeping unmatched shell rows visible.
|
|
54
|
+
- Prefer loaded workspace context over repeated internal workflow keys in async TUI lane rows (#1619).
|
|
55
|
+
- Accept path-like Pi session ids up to 4,096 characters when snapshotting background work. Thanks to [@dvishoot](https://github.com/dvishoot) for #1616.
|
|
56
|
+
- Accept bare leaf model ids reported by provider drivers when verifying provider-qualified launch candidates. Thanks to [@lallenlowe](https://github.com/lallenlowe) for #1609.
|
|
57
|
+
- Resume compaction-induced child aborts once when retained state is safe, and report the exact recovery blocker otherwise.
|
|
58
|
+
- Report aborted or signalled no-output child runs with their terminal stop, stderr, or process signal before missing-output handoff diagnostics.
|
|
59
|
+
- Apply `globalConcurrencyLimit` to `workflowScript` children launched through `runs.run` and `runs.all`, not only legacy multi-child runners. Thanks to [@mateominato](https://github.com/mateominato) for #1600.
|
|
60
|
+
- Ignore nested `.pi` and `sync-backups` directories during agent discovery so stale backup definitions cannot become executable agents. Thanks to [@arlishansenn](https://github.com/arlishansenn) for #1596.
|
|
61
|
+
- Let projects layer agent overrides by the active parent model provider without duplicating agent definitions. Thanks to [@arichiardi](https://github.com/arichiardi) for #1597.
|
|
62
|
+
- Let operators configure the default `subagent_wait` window and report window expiry as non-error active work while preserving strict headless draining. Thanks to [@Shujakuinkuraudo](https://github.com/Shujakuinkuraudo) for #1591.
|
|
63
|
+
- Degrade run status to the stored fan-out budget snapshot when persisted state is unavailable, instead of failing the entire run list. Thanks to [@qsgy-edge](https://github.com/qsgy-edge) for #1595.
|
|
64
|
+
- Enforce MCP server `includeTools` and `excludeTools` policies for child direct-tool grants, including adapter-compatible glob matching. Thanks to [@Shujakuinkuraudo](https://github.com/Shujakuinkuraudo) for #1590.
|
|
65
|
+
- Prevent Fleet prompt audit rendering from crashing on malformed non-string task payloads. Thanks to [@bengidev](https://github.com/bengidev) for #1586.
|
|
66
|
+
- Resume a retained child session once after a provider or transport abort follows useful progress, without restarting the task or involving the parent model.
|
|
67
|
+
- Retry unused fallback models after a provider reports a plain-text `500` or `internal server error`. Thanks to [@rafafortes](https://github.com/rafafortes) for #1642.
|
|
68
|
+
- Mark missing required child handoffs with useful mutation evidence as partial needs-attention results.
|
|
69
|
+
|
|
70
|
+
## [0.58.0] - 2026-08-27
|
|
71
|
+
|
|
72
|
+
### Highlights
|
|
73
|
+
- Launch MCP tools from more places, including runtime-registered servers, Pi package manifests, and Agent Plugin configs.
|
|
74
|
+
- Keep agent context smaller by default, with an explicit `inheritGlobalContext` opt-in when a child needs the operator's global context.
|
|
75
|
+
- Make detached and recovered workflow results more reliable, with clearer terminal handoffs and recovery actions.
|
|
76
|
+
- Show better launch and status diagnostics for workspace, authority, context-window, and missing-directory problems.
|
|
77
|
+
- Keep fast OpenAI-Codex launches compatible with priority service tier without losing provider request fields.
|
|
78
|
+
|
|
79
|
+
### Added
|
|
80
|
+
- Support direct MCP tool launches from runtime-registered servers.
|
|
81
|
+
- Add `inheritGlobalContext` agent configuration so children can opt into the operator's global context file separately from repository context. Thanks to [@hknatm](https://github.com/hknatm) for #1560.
|
|
82
|
+
- Add process-local event registration so independent Pi extensions can register runtime agents through the installed owner. Thanks to [@fmoda3](https://github.com/fmoda3) for #1533.
|
|
83
|
+
- Add advisory launch preflight diagnostics for likely workspace scope and authority mismatches.
|
|
84
|
+
- Document per-run thinking suffixes in model-facing subagent guidance. Thanks to [@yanqianglu](https://github.com/yanqianglu) for #1565.
|
|
85
|
+
- Document unsupported native child options for external CLI agents in the subagent tool help, packaged guide, and packaged skill.
|
|
86
|
+
|
|
87
|
+
### Changed
|
|
88
|
+
- Agents now omit the operator's global context file by default, including existing agents with `inheritProjectContext: true`; set `inheritGlobalContext: true` to preserve the previous behavior. Thanks to [@hknatm](https://github.com/hknatm) for #1560.
|
|
89
|
+
|
|
90
|
+
### Fixed
|
|
91
|
+
- Fail explicitly requested models closed when a cached model exclusion is active, instead of silently selecting a fallback. Thanks to [@harpsychord](https://github.com/harpsychord) for #1556.
|
|
92
|
+
- Preserve fast-mode provider request root fields when adding OpenAI's priority service tier. Thanks to [@nothingrotf](https://github.com/nothingrotf) for #1570.
|
|
93
|
+
- Classify workflow budget and timeout stops as partial terminal outcomes while preserving settled child evidence. Thanks to [@yceachan](https://github.com/yceachan) for #1530.
|
|
94
|
+
- Publish a deterministic terminal handoff with settled child evidence and keyed recovery actions when detached workflow lanes settle. Thanks to [@yceachan](https://github.com/yceachan) for #1530.
|
|
95
|
+
- Resolve direct MCP tool selections from Pi package manifests and Agent Plugin configs. Thanks to [@fmoda3](https://github.com/fmoda3) for #1541.
|
|
96
|
+
- Fail closed with a launch diagnostic when configured runtime-style MCP direct-tool selectors cannot be resolved.
|
|
97
|
+
- Sync Herdr status after restoring active async jobs, so recovered work appears without waiting for another lifecycle event. Thanks to [@vicocamacho](https://github.com/vicocamacho) for #1553.
|
|
98
|
+
- Show task intent and context-window use in compact in-progress async status rows.
|
|
99
|
+
- Report deterministic settlement diagnostics when background children fail before required output handoff.
|
|
100
|
+
- Auto-resume workflow children once after setup-phase aborts that produce zero usage, preserving the retained transcript instead of rerunning the whole task.
|
|
101
|
+
- Finalize detached foreground worktree handoffs after terminal child completion, preserving captured changes before cleanup. Thanks to [@jpriverar](https://github.com/jpriverar) for #1562.
|
|
102
|
+
- Fail native child launches before spawn when the requested local working directory is missing or not a directory, with the requested and resolved paths in the error.
|
|
103
|
+
- Map report paths requested in workflow child tasks to the actual saved child output when workflow output routing overrides them.
|
|
104
|
+
- Stop same-session workflows recovered after extension reload through the durable control channel.
|
|
105
|
+
- Let agents declare extension mutation tools so real non-Git or untracked edits satisfy the implementation completion guard. Thanks to [@AlphaGodzilla](https://github.com/AlphaGodzilla) for #1532.
|
|
106
|
+
- Deliver async results from an explicitly replaced predecessor session without accepting unrelated session results. Thanks to [@DresvyanskiyDenis](https://github.com/DresvyanskiyDenis) for #1531.
|
|
107
|
+
- Avoid attributing assistant-issued workflow stops to the user.
|
|
108
|
+
|
|
5
109
|
## [0.57.0] - 2026-08-26
|
|
6
110
|
|
|
7
111
|
### Highlights
|
package/docs/agents.md
CHANGED
|
@@ -57,6 +57,8 @@ The Pi async run remains the source of truth for status, artifacts, wake/wait, m
|
|
|
57
57
|
|
|
58
58
|
### Advisory runner data boundary
|
|
59
59
|
|
|
60
|
+
External CLI agents use their own runner contract. Do not pass native Pi child options such as model override, structured output, acceptance/agent contract, tool budgets, fast mode, fork context, skills, or native Pi tools unless the adapter explicitly implements them.
|
|
61
|
+
|
|
60
62
|
The built-in `codex-exec` and `codex-exec-writer` profiles are the supported Codex one-shot modes. Both require an installed and authenticated Codex CLI. The adapters own `codex exec --json` argv with ignored user config and rules, ephemeral sessions, approval policy `never`, and a final-message artifact.
|
|
61
63
|
|
|
62
64
|
| Profile | Access | Sandbox |
|
|
@@ -207,7 +209,7 @@ You can override selected builtin fields without copying the whole agent. Overri
|
|
|
207
209
|
}
|
|
208
210
|
```
|
|
209
211
|
|
|
210
|
-
Supported override fields: `description`, `output`, `outputMode`, `defaultReads`, `model`, `defaultProvider`, `fallbackModels`, `thinking`, `systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `defaultContext`, `acceptanceRole`, `disabled`, `skills`, `tools`, and `systemPrompt`.
|
|
212
|
+
Supported override fields: `description`, `output`, `outputMode`, `defaultReads`, `model`, `defaultProvider`, `fallbackModels`, `thinking`, `systemPromptMode`, `inheritProjectContext`, `inheritGlobalContext`, `inheritSkills`, `defaultContext`, `acceptanceRole`, `disabled`, `skills`, `tools`, and `systemPrompt`.
|
|
211
213
|
|
|
212
214
|
- `description` replaces the discovered description for builtin and custom agents, which lets list output show deployment-specific routing or model metadata.
|
|
213
215
|
- Use `output: false`, `defaultReads: false`, `defaultContext: false`, or `acceptanceRole: false` to clear an inherited value.
|
|
@@ -234,11 +236,12 @@ Use these fields when an agent should see more:
|
|
|
234
236
|
| Field | Effect |
|
|
235
237
|
|-------|--------|
|
|
236
238
|
| `systemPromptMode: append` | Append the agent prompt to Pi's normal base prompt. |
|
|
237
|
-
| `inheritProjectContext: true` | Keep inherited
|
|
239
|
+
| `inheritProjectContext: true` | Keep inherited repository instructions from files like `AGENTS.md` and `CLAUDE.md`. |
|
|
240
|
+
| `inheritGlobalContext: true` | Also keep the operator's global context file from the Pi config agent directory (such as `~/.pi/agent/AGENTS.md`). Defaults to `false`. |
|
|
238
241
|
| `inheritSkills: true` | Let the child see Pi's discovered skills catalog. |
|
|
239
242
|
| `defaultContext: fork` | Prefer forked session context when a launch omits `context`; if the parent has no persisted session file or current leaf yet, the implicit default falls back to `fresh` without a failed first attempt. Explicit `context: "fork"` remains strict, and explicit `context: "fresh"` still wins. |
|
|
240
243
|
|
|
241
|
-
Builtin agents opt into
|
|
244
|
+
Builtin agents opt into repository instruction inheritance by default so they follow repo-specific rules out of the box, but global context remains excluded unless `inheritGlobalContext: true` is set. This changes the behavior of existing agents that previously received global context as part of `inheritProjectContext: true`. `delegate` also uses append mode because its job is orchestration inside the parent workflow.
|
|
242
245
|
|
|
243
246
|
## Frontmatter reference
|
|
244
247
|
|
|
@@ -255,10 +258,11 @@ tools: read, grep, find, ls, bash, mcp:chrome-devtools
|
|
|
255
258
|
extensions:
|
|
256
259
|
subagentOnlyExtensions: ./tools/child-only-search.ts
|
|
257
260
|
model: claude-haiku-4-5
|
|
258
|
-
fallbackModels: openai/gpt-5-
|
|
261
|
+
fallbackModels: openai-codex/gpt-5.6-luna:low, anthropic/claude-sonnet-4
|
|
259
262
|
thinking: high
|
|
260
263
|
systemPromptMode: replace
|
|
261
264
|
inheritProjectContext: false
|
|
265
|
+
inheritGlobalContext: false
|
|
262
266
|
inheritSkills: false
|
|
263
267
|
skills: safe-bash, review-checklist
|
|
264
268
|
skillPath: ./skills, ../shared-skills
|
|
@@ -268,12 +272,12 @@ defaultProgress: true
|
|
|
268
272
|
async: true
|
|
269
273
|
timeoutMs: 900000
|
|
270
274
|
toolTimeoutMs: 600000
|
|
271
|
-
turnBudget: {"maxTurns":20,"graceTurns":2}
|
|
272
275
|
acceptance: {"level":"none","reason":"lightweight lookup"}
|
|
273
276
|
acceptanceRole: read-only
|
|
274
277
|
completionGuard: false
|
|
275
278
|
interactive: true
|
|
276
279
|
maxSubagentDepth: 1
|
|
280
|
+
allowNestedSubagents: true
|
|
277
281
|
---
|
|
278
282
|
|
|
279
283
|
Your system prompt goes here.
|
|
@@ -286,7 +290,7 @@ tools:
|
|
|
286
290
|
- read
|
|
287
291
|
- mcp:github/search_repositories
|
|
288
292
|
fallbackModels:
|
|
289
|
-
- openai/gpt-5-
|
|
293
|
+
- openai-codex/gpt-5.6-luna:low
|
|
290
294
|
- anthropic/claude-sonnet-4
|
|
291
295
|
```
|
|
292
296
|
|
|
@@ -297,13 +301,15 @@ Field notes:
|
|
|
297
301
|
| `package` | Optional package identifier. A file with `name: scout` and `package: code-analysis` registers as `code-analysis.scout`; serialization keeps `name` and `package` separate. |
|
|
298
302
|
| `aliases` | Optional comma-separated or block-list names that resolve to this agent for selection and explicit `agent` and task inputs. Runtime status, persistence, and config still use the canonical `name`. Exact canonical names take precedence over aliases, and alias collisions between distinct canonical agents fail as ambiguous. |
|
|
299
303
|
| `tools` | Strict child tool allowlist. Named extension tools must also have their provider loaded. `mcp:` entries select direct MCP tools when `pi-mcp-adapter` is installed. |
|
|
304
|
+
| `allowNestedSubagents` | Set `true` to authorize the child-safe nested `subagent` runtime without making omitted `tools` an allowlist. Inherited depth and capability ceilings remain authoritative. |
|
|
300
305
|
| `extensions` | Omitted means normal extensions; empty means no extensions; list values allowlist specific extensions. |
|
|
301
306
|
| `subagentOnlyExtensions` | Extension paths loaded only in spawned child sessions for this agent. Tools registered there are unavailable to the main agent unless also installed through normal Pi extension configuration. |
|
|
302
307
|
| `model` | Default model. Bare ids prefer the current provider when possible, then unique registry matches. |
|
|
303
308
|
| `fallbackModels` | Ordered backup models for provider/model failures such as quota, auth, timeout, or unavailable model. Ordinary task failures do not trigger fallback. |
|
|
304
309
|
| `thinking` | Appended as a `:level` suffix at runtime unless a suffix is already present. |
|
|
305
310
|
| `systemPromptMode` | `replace` by default; `append` keeps Pi's base prompt. |
|
|
306
|
-
| `inheritProjectContext` | Keeps or strips inherited
|
|
311
|
+
| `inheritProjectContext` | Keeps or strips inherited repository instruction blocks. |
|
|
312
|
+
| `inheritGlobalContext` | Keeps or strips the operator's global context file from the Pi config agent directory (e.g. `~/.pi/agent/AGENTS.md`). It has an effect only when `inheritProjectContext` is `true`; otherwise all context files are already disabled. Defaults to `false`. |
|
|
307
313
|
| `inheritSkills` | Keeps or strips Pi's discovered skills catalog. |
|
|
308
314
|
| `defaultContext` | Optional `fresh` or `fork` launch-context preference. An implicit `fork` falls back to `fresh` when the parent has no persisted session file or current leaf; an explicit launch `context: "fork"` remains strict. |
|
|
309
315
|
| `skills` | Selects specific skills for the child, regardless of `inheritSkills`. |
|
|
@@ -314,9 +320,9 @@ Field notes:
|
|
|
314
320
|
| `async` | Default a single-agent launch to background (`true`) or foreground (`false`) when the call omits `async`. Explicit call values and `forceTopLevelAsync` win. |
|
|
315
321
|
| `timeoutMs` | Positive integer default runtime deadline in milliseconds for single-agent launches. Foreground launches use 30 minutes when neither the call nor agent provides a timeout; explicit `timeoutMs`/`maxRuntimeMs` and agent defaults win. |
|
|
316
322
|
| `toolTimeoutMs` | Optional positive integer hard per-tool-call deadline in milliseconds. An explicit call value wins, then this agent default, global `toolTimeoutMs`, and `PI_SUBAGENT_TOOL_TIMEOUT_MS`. When omitted, known-fast built-in tools get a five-minute default; long-running tools get attention notices but no hard default. It does not extend the run-level deadline; `contact_supervisor`, `intercom`, and `subagent_wait` are exempt. |
|
|
317
|
-
| `turnBudget` | JSON object default such as `{"maxTurns":20,"graceTurns":2}` for single-agent launches. An explicit call value wins, followed by this agent default, then global `turnBudget` config. |
|
|
318
323
|
| `acceptance` | Acceptance default for single-agent launches. Use a scalar level such as `checked` or an inline/block YAML map such as `{ level: "none", reason: "lightweight lookup" }`. Explicit call values win; chain and parallel acceptance remains task/step configuration. |
|
|
319
324
|
| `acceptanceRole` | Optional `read-only` or `writer` role for automatic acceptance inference. Explicit task mutation or no-edit intent wins; otherwise the declared role replaces agent-name guessing. This does not grant or revoke tools. |
|
|
325
|
+
| `mutationTools` | Comma-separated extension tool names whose calls count as mutation attempts for the completion guard. This declares evidence only; list and load each tool through `tools` and its extension provider as usual. |
|
|
320
326
|
| `completionGuard` | Set `false` only for non-implementation agents that may mention implementation words while using mutation-capable tools such as `bash`. |
|
|
321
327
|
| `interactive` | Parsed for compatibility but not currently enforced. |
|
|
322
328
|
| `maxSubagentDepth` | Tightens nested delegation for this agent's children. |
|
|
@@ -377,6 +383,7 @@ How `tools` behaves:
|
|
|
377
383
|
- `tools` omitted: `pi-subagents` does not pass `--tools`, so the child gets Pi's normal builtin tools.
|
|
378
384
|
- `tools` present: regular tool names become an explicit allowlist.
|
|
379
385
|
- `tools:` empty: emits `--no-tools`.
|
|
386
|
+
- `allowNestedSubagents: true`: explicitly enables child-safe nested fanout without turning omitted `tools` into an allowlist. Depth and inherited capability ceilings still apply.
|
|
380
387
|
|
|
381
388
|
An allowlisted name does not load the extension that registers it. Load that provider through normal Pi extension discovery, `extensions`, `subagentOnlyExtensions`, or a path-like `tools` entry.
|
|
382
389
|
|
|
@@ -385,6 +392,7 @@ More rules:
|
|
|
385
392
|
- `mcp:` entries are split out and forwarded as direct MCP selections without granting normal builtins unless those builtins are also listed.
|
|
386
393
|
- Path-like `tools` entries, such as extension paths or `.ts`/`.js` files, are treated as tool-extension paths rather than tool names.
|
|
387
394
|
- Internal runtime tools such as `structured_output` are added to an explicit allowlist only when their contract is active.
|
|
395
|
+
- Unknown extension tool calls count as mutation attempts only when their names are listed in `mutationTools`; undeclared unknown tools keep the no-edit guard active.
|
|
388
396
|
- Agents that declare only known read-only builtin tools skip the implementation completion guard. `bash`, unknown tools, and MCP tools stay mutation-capable. Use `completionGuard: false` for bash-enabled validators or advisors that should never be judged as implementation agents.
|
|
389
397
|
|
|
390
398
|
Examples:
|
|
@@ -393,9 +401,10 @@ Examples:
|
|
|
393
401
|
- `tools: mcp:chrome-devtools`: only the resolved direct Chrome DevTools MCP tools.
|
|
394
402
|
- `tools: read, bash, mcp:chrome-devtools`: only `read` and `bash` as builtins, plus direct Chrome DevTools MCP tools.
|
|
395
403
|
- `tools: subagent, read`: a child-safe `subagent` tool is available inside that child so it can run explicitly assigned nested fanout.
|
|
404
|
+
- `allowNestedSubagents: true` with `tools` omitted: normal builtin tools and ambient extensions remain inherited, and the child-safe nested `subagent` runtime is added.
|
|
396
405
|
- `tools: read, fixture_search` plus `subagentOnlyExtensions: ./tools/fixture-search.ts`: the provider loads only in this agent's child process, and the registered `fixture_search` name survives the strict allowlist.
|
|
397
406
|
|
|
398
|
-
Direct MCP tools require [pi-mcp-adapter](https://github.com/nicobailon/pi-mcp-adapter). Subagents only receive direct MCP tools when `mcp:` entries are listed in their frontmatter; global `directTools: true` in `mcp.json` is not enough by itself. The generic `mcp` proxy tool can still be used for discovery when available. The adapter caches tool metadata at startup, so after connecting a new MCP server for the first time, restart Pi before relying on direct tools. An `mcp:` entry named `subagent` does not authorize nested fanout;
|
|
407
|
+
Direct MCP tools require [pi-mcp-adapter](https://github.com/nicobailon/pi-mcp-adapter). Subagents only receive direct MCP tools when `mcp:` entries are listed in their frontmatter; global `directTools: true` in `mcp.json` is not enough by itself. The generic `mcp` proxy tool can still be used for discovery when available. The adapter caches tool metadata at startup, so after connecting a new MCP server for the first time, restart Pi before relying on direct tools. Server `includeTools` and `excludeTools` policies are enforced while resolving cached metadata for children: both accept exact names and `*`/`?` glob patterns against raw, generated-resource, and server/short/none-prefixed names, with `excludeTools` taking precedence. An `mcp:` entry named `subagent` does not authorize nested fanout; declare the builtin `subagent` tool or set `allowNestedSubagents: true`. If a resolved direct MCP name is missing from the child registry, pi-subagents keeps the launch failed under the strict allowlist and identifies the condition as a host/pi-mcp-adapter registration problem; verify that the adapter registers the selected tools before child startup.
|
|
399
408
|
|
|
400
409
|
`extensions` controls child extension loading:
|
|
401
410
|
|
package/docs/configuration.md
CHANGED
|
@@ -184,10 +184,10 @@ Controls the under-editor widget for active background runs. It defaults to `tru
|
|
|
184
184
|
## `waitTool`
|
|
185
185
|
|
|
186
186
|
```json
|
|
187
|
-
{ "waitTool": { "enabled":
|
|
187
|
+
{ "waitTool": { "enabled": true, "defaultTimeoutMs": 120000 } }
|
|
188
188
|
```
|
|
189
189
|
|
|
190
|
-
|
|
190
|
+
`defaultTimeoutMs` sets the blocking window used when a `subagent_wait` call omits `timeoutMs`; explicit call values win, followed by this setting, then the 30-minute fallback. When the window elapses, the tool returns a non-error `window_elapsed` result with the still-active work identities, and that work keeps running. Set `enabled` to `false` to keep the tool registered while making direct calls return immediately instead of blocking. The default is enabled. You can also set `"waitTool": false`; set `PI_SUBAGENT_WAIT_TOOL_ENABLED=false` (or `0`, `off`, `disabled`) to override config for one process. The effective enabled and default-timeout values are passed explicitly to child runtimes. Headless `agent_end` auto-drain retains its own strict deadline and fails if required work remains unresolved. Invalid config or environment values fail instead of being coerced.
|
|
191
191
|
|
|
192
192
|
Blocking `subagent_wait({ id: "..." })` keeps the current tool call open until that run changes. By default it returns when a run needs attention. Use `subagent_wait({ stopOnAttention: false })` only for run-to-completion flows that should wait through idle or long-thinking attention; supervisor/contact requests still stop the wait. In a long-lived interactive parent session, `subagent_wait({ id: "...", nonBlocking: true })` instead resolves the prefix once, persists the exact run identity, returns a subscription token immediately, and wakes that session on completion, failure, attention, reconciliation failure, or timeout. Armed subscriptions appear in ordinary `subagent({ action: "status" })` output and are not counted as active child work.
|
|
193
193
|
|
|
@@ -241,7 +241,7 @@ The tool timer tracks each active `toolCallId` separately and never extends the
|
|
|
241
241
|
{ "globalConcurrencyLimit": 20 }
|
|
242
242
|
```
|
|
243
243
|
|
|
244
|
-
Caps simultaneously running children inside
|
|
244
|
+
Caps simultaneously running children inside one run, including durable legacy multi-child runs and `workflowScript` launches through `runs.run`/`runs.all`. Queued workflow children retain their stable keys and begin when a running sibling releases capacity. The default is `20`.
|
|
245
245
|
|
|
246
246
|
## `maxSubagentSpawnsPerSession`
|
|
247
247
|
|
|
@@ -336,7 +336,7 @@ Routes relative `output` paths for single-agent `/run` calls under this director
|
|
|
336
336
|
{ "maxSubagentDepth": 1 }
|
|
337
337
|
```
|
|
338
338
|
|
|
339
|
-
Controls nested delegation when no inherited `PI_SUBAGENT_MAX_DEPTH` is already in effect. Per-agent `maxSubagentDepth` can tighten the limit for that agent's child runs, but cannot relax an inherited stricter limit. This applies even to children that explicitly declare `tools: subagent`; at the cap, execution fanout is blocked instead of silently hiding nested work.
|
|
339
|
+
Controls nested delegation when no inherited `PI_SUBAGENT_MAX_DEPTH` is already in effect. Per-agent `maxSubagentDepth` can tighten the limit for that agent's child runs, but cannot relax an inherited stricter limit. This applies even to children that explicitly declare `tools: subagent` or `allowNestedSubagents: true`; at the cap, execution fanout is blocked instead of silently hiding nested work.
|
|
340
340
|
|
|
341
341
|
## `PI_SUBAGENT_PI_BINARY`
|
|
342
342
|
|
package/docs/extension-api.md
CHANGED
|
@@ -58,6 +58,45 @@ The DTO intentionally never exposes run, async, or tool IDs. Clients must ignore
|
|
|
58
58
|
|
|
59
59
|
`pi.events` is in-process only. It does not reach separate Pi processes or child subagents; use the file lifecycle artifacts or `pi-intercom` for cross-process coordination.
|
|
60
60
|
|
|
61
|
+
## Runtime agent registration from independent extensions
|
|
62
|
+
|
|
63
|
+
An independently installed Pi extension can register an agent with the installed `pi-subagents` owner through the process-local `pi-subagents:runtime-agent-register:v1` event. Emit after extension setup, such as during `session_start`. Event delivery is synchronous, so the owner writes the result onto the request before `emit()` returns.
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
const request: {
|
|
67
|
+
version: 1;
|
|
68
|
+
name: string;
|
|
69
|
+
definition: {
|
|
70
|
+
description: string;
|
|
71
|
+
systemPrompt: string;
|
|
72
|
+
tools?: readonly string[];
|
|
73
|
+
};
|
|
74
|
+
result?:
|
|
75
|
+
| { ok: true; registration: { dispose(): void } }
|
|
76
|
+
| { ok: false; error: Error };
|
|
77
|
+
} = {
|
|
78
|
+
version: 1,
|
|
79
|
+
name: "runtime-probe-agent",
|
|
80
|
+
definition: {
|
|
81
|
+
description: "Agent registered by an independent extension",
|
|
82
|
+
systemPrompt: "Return the words runtime probe.",
|
|
83
|
+
tools: [],
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
pi.events.emit("pi-subagents:runtime-agent-register:v1", request);
|
|
88
|
+
if (!request.result) throw new Error("pi-subagents is not installed or not ready");
|
|
89
|
+
if (!request.result.ok) throw request.result.error;
|
|
90
|
+
const registration = request.result.registration;
|
|
91
|
+
// Call registration.dispose() during your extension cleanup.
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
If `pi-subagents` is a resolvable dependency of the consumer package, `pi-subagents/agents` exports `RUNTIME_AGENT_REGISTER_EVENT`, the request/result types, and `registerAgentViaEvents()` for the same contract. A separately installed Pi package is not automatically a Node dependency of another package. In that case, use the event contract directly instead of a runtime import. A type-only development dependency is optional.
|
|
95
|
+
|
|
96
|
+
The installed owner applies the existing runtime-agent validation, collision checks, limits, runtime source metadata, and cleanup. If more than one owner listens, the first handler that writes `request.result` wins. Unsupported versions, malformed requests, and registration failures return `{ ok: false, error }`. No result means no compatible owner handled the event.
|
|
97
|
+
|
|
98
|
+
This contract is process-local. It does not register agents in child processes or other Pi processes, and it does not change package discovery or package resolution.
|
|
99
|
+
|
|
61
100
|
## External jobs in FleetView
|
|
62
101
|
|
|
63
102
|
Use `pi-subagents/external-runs` to publish display-only current-session jobs owned by another extension:
|
|
@@ -126,7 +165,7 @@ Preflight covers ordinary single-agent launch resolution:
|
|
|
126
165
|
- Fresh/fork context, effective model and thinking, skill and tool resolution, direct MCP selections, runtime/configured extensions.
|
|
127
166
|
- Artifact/session paths, async lifecycle/status/result/event/process-terminal paths, package/lifecycle versions, capability-ceiling audit data, and stable digests.
|
|
128
167
|
|
|
129
|
-
`launchContractDigest` is the canonical digest of the caller task, effective system prompt
|
|
168
|
+
`launchContractDigest` is the canonical digest of the caller task, effective system prompt, model candidates, effective tools/extensions/MCP (including inherited capability ceilings), output binding, and structured-output schema that ordinary foreground and async execution report in results/status/events and metadata.
|
|
130
169
|
|
|
131
170
|
Boundaries:
|
|
132
171
|
|
package/docs/models.md
CHANGED
|
@@ -8,9 +8,10 @@ Builtin agents inherit your current Pi default model. This keeps new installs fr
|
|
|
8
8
|
- `subagents.defaultProvider` — a provider preference for bare model ids, such as `llama-3`, when multiple providers expose the same id.
|
|
9
9
|
- `subagents.agentOverrides.<name>.model` — pin one role.
|
|
10
10
|
- `subagents.agentOverrides.<name>.defaultProvider` — choose or clear the provider preference for one role.
|
|
11
|
+
- `subagents.agentOverridesByProvider.<provider>.<name>` — layer role fields for the active parent provider.
|
|
11
12
|
- Per-run overrides — for one launch only.
|
|
12
13
|
|
|
13
|
-
Precedence, strongest first: per-run override → agent frontmatter `model` → `agentOverrides.<name>.model` → `subagents.defaultModel` → the parent session model. A provider preference does not replace this order; it only resolves bare model ids when the active registry has more than one match. Fully qualified `provider/model` strings still win exactly.
|
|
14
|
+
Precedence, strongest first: per-run override → agent frontmatter `model` → provider-scoped role override → `agentOverrides.<name>.model` → `subagents.defaultModel` → the parent session model. A provider preference does not replace this order; it only resolves bare model ids when the active registry has more than one match. Fully qualified `provider/model` strings still win exactly.
|
|
14
15
|
|
|
15
16
|
Use `model: "inherit"` in agent frontmatter or `agentOverrides.<name>.model` to select the current parent session model explicitly.
|
|
16
17
|
|
|
@@ -36,6 +37,28 @@ In `~/.pi/agent/settings.json` (user) or the project config settings file (`.pi/
|
|
|
36
37
|
}
|
|
37
38
|
```
|
|
38
39
|
|
|
40
|
+
To keep one role definition but configure it differently for work and personal providers, add the unambiguous provider map beside `agentOverrides`:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"subagents": {
|
|
45
|
+
"agentOverrides": {
|
|
46
|
+
"worker": { "thinking": "medium" }
|
|
47
|
+
},
|
|
48
|
+
"agentOverridesByProvider": {
|
|
49
|
+
"github-copilot": {
|
|
50
|
+
"worker": { "model": "github-copilot/gpt-5-mini" }
|
|
51
|
+
},
|
|
52
|
+
"openrouter": {
|
|
53
|
+
"worker": { "model": "openrouter/openai/gpt-5-mini" }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The provider key comes from the active parent session model (or an explicit host `preferredProvider`) before fallback selection. Provider-scoped fields layer over the ordinary override in the same settings file; project settings still win over user settings. A fallback attempt does not switch the selected provider configuration.
|
|
61
|
+
|
|
39
62
|
For one run, put the override in the command:
|
|
40
63
|
|
|
41
64
|
```text
|
|
@@ -51,7 +74,7 @@ For a persistent role override with a backup model for provider failures:
|
|
|
51
74
|
"reviewer": {
|
|
52
75
|
"model": "anthropic/claude-sonnet-4",
|
|
53
76
|
"thinking": "high",
|
|
54
|
-
"fallbackModels": ["openai/gpt-5-
|
|
77
|
+
"fallbackModels": ["openai-codex/gpt-5.6-luna:low"]
|
|
55
78
|
}
|
|
56
79
|
}
|
|
57
80
|
}
|
|
@@ -182,9 +205,9 @@ To keep subagents inside a budget or compliance profile, enforce a model scope.
|
|
|
182
205
|
"modelScope": {
|
|
183
206
|
"enforce": true,
|
|
184
207
|
"strict": true,
|
|
185
|
-
"allow": ["inherit", "openai/gpt-5-*"],
|
|
208
|
+
"allow": ["inherit", "openai/gpt-5-*", "openai-codex/gpt-5.6-*"],
|
|
186
209
|
"agents": {
|
|
187
|
-
"worker": { "allow": ["openai/gpt-5-
|
|
210
|
+
"worker": { "allow": ["openai-codex/gpt-5.6-luna"] },
|
|
188
211
|
"reviewer": { "allow": ["inherit"] }
|
|
189
212
|
}
|
|
190
213
|
}
|
package/docs/observability.md
CHANGED
|
@@ -56,7 +56,7 @@ After you expand it:
|
|
|
56
56
|
|
|
57
57
|
When the focused editor is empty, press `↓` or `←` to expand the summary into `main` plus active children with agent name, state, elapsed time, and token usage. When providers report usage, `window` is the latest assistant turn's input plus cache-read tokens, while `spent` keeps the cumulative input-plus-output total. Old run artifacts without window data keep the existing token-total label. The compact line counts active current-session work and Herdr project panes. Then use `↑`/`↓` or `j`/`k` to select a child and `Enter` to inspect it. Printable navigation keys are never intercepted before activation.
|
|
58
58
|
|
|
59
|
-
FleetView replaces the legacy above-editor async widget by default. Successful background completions stay quiet so inactive Pi tabs are not marked unread, while failed or paused completions still notify the originating session. Parallel runs show every active child independently. Chains with parallel groups keep their grouped shape in progress and results, so failed or paused agents stay visible next to completed ones. When a child is explicitly allowed to fan out with `tools: subagent`, its nested runs appear under that parent child in the main status tree instead of being hidden inside the child process.
|
|
59
|
+
FleetView replaces the legacy above-editor async widget by default. Successful background completions stay quiet so inactive Pi tabs are not marked unread, while failed or paused completions still notify the originating session. Parallel runs show every active child independently. Chains with parallel groups keep their grouped shape in progress and results, so failed or paused agents stay visible next to completed ones. When a child is explicitly allowed to fan out with `tools: subagent` or `allowNestedSubagents: true`, its nested runs appear under that parent child in the main status tree instead of being hidden inside the child process.
|
|
60
60
|
|
|
61
61
|
## The fleet inspector
|
|
62
62
|
|
package/docs/tool-reference.md
CHANGED
|
@@ -36,18 +36,61 @@ Use `workflowScriptPath` instead of `workflowScript` to load the same JavaScript
|
|
|
36
36
|
` }
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
### Parallel sequential lanes
|
|
40
|
+
|
|
41
|
+
Use `runs.lanes(lanes)` inside a `workflowScript` when several independent lanes each have ordered stages. This helper composes the existing workflow child runner; it does not add a top-level `lanes` parameter or a second persistence/cleanup system.
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
{ workflowScript: `
|
|
45
|
+
const board = await runs.lanes([
|
|
46
|
+
{ key: "api", stages: [
|
|
47
|
+
{ key: "writer", agent: "worker", task: "Implement the API change" },
|
|
48
|
+
{ key: "challenge", resume: "previous", task: "Challenge the implementation" },
|
|
49
|
+
{ key: "review", agent: "reviewer", task: "Review the API lane" }
|
|
50
|
+
] },
|
|
51
|
+
{ key: "ui", stages: [
|
|
52
|
+
{ key: "writer", agent: "worker", task: "Implement the UI change" },
|
|
53
|
+
{ key: "review", agent: "reviewer", task: "Review the UI lane" }
|
|
54
|
+
] }
|
|
55
|
+
]);
|
|
56
|
+
return board.map((lane) => ({
|
|
57
|
+
key: lane.key,
|
|
58
|
+
state: lane.state,
|
|
59
|
+
failedStage: lane.failedStage,
|
|
60
|
+
stages: lane.stages.map((stage) => ({
|
|
61
|
+
key: stage.key,
|
|
62
|
+
state: stage.state,
|
|
63
|
+
ok: stage.ok,
|
|
64
|
+
runId: stage.runId,
|
|
65
|
+
outputReference: stage.outputReference,
|
|
66
|
+
verdict: stage.verdict
|
|
67
|
+
}))
|
|
68
|
+
}));
|
|
69
|
+
` }
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The first stage of each lane is launched by one existing `runs.all(...)` batch. Later stages run in lane order. Set `resume: "previous"` on a later stage to continue the preceding retained child; the helper requires that child’s returned `runId` and delegates to the existing resume checks. Stage keys are local to the lane, and generated child keys are `<lane>.<stage>`.
|
|
73
|
+
|
|
74
|
+
The complete plain-JSON inventory is validated before the first launch (maximum 32 lanes, 16 stages per lane, 64 total stages, and 64 KiB canonical JSON). A failed, stopped, or detached stage blocks only its lane and marks later stages `skipped`; an explicit `structuredOutput.verdict === "blocked"` has the same effect. Reviewer prose is not parsed. The bounded board returns lane/stage keys, state, `ok`, run ids, explicit output references, bounded errors, and optional verdicts, not transcripts. Use raw `runs.run(...)`/`runs.all(...)` for conditional or rolling workflows.
|
|
75
|
+
|
|
39
76
|
## Parameter reference
|
|
40
77
|
|
|
41
78
|
| Param | Type | Default | Description |
|
|
42
79
|
|-------|------|---------|-------------|
|
|
43
80
|
| `agent` | string | - | Agent target for management actions. Workflow child agents are set inside `runs.run` or `runs.all`. |
|
|
44
|
-
| `action` | string | - | Offline workflow `validate`, agent management (including `guide`, `children.list`, and `refine`/`refine.show`/`refine.rollback`), mission (`mission.create/list/show/update/resolve-decision/attach-run/close`), Herdr inspector (`inspector.open/status/close`), Herdr project pane (`project.open/status/close`), status/control, schedule, watchdog, or doctor action. |
|
|
81
|
+
| `action` | string | - | Offline workflow `validate`, agent management (including `guide`, `children.list`, and `refine`/`refine.show`/`refine.rollback`), lane evidence (`lane.status`, `lane.recordMerge`, `lane.recordSupersession`), mission (`mission.create/list/show/update/resolve-decision/attach-run/close`), Herdr inspector (`inspector.open/status/close`), Herdr project pane (`project.open/status/close`), status/control, plan-only `worktree.cleanup`, schedule, watchdog, or doctor action. |
|
|
45
82
|
| `topic` | `overview \| workflows \| agents \| missions \| observability \| tool-reference \| configuration \| models \| watchdog \| extension-api` | `overview` | Packaged guide topic for `action: "guide"`. |
|
|
46
83
|
| `config` | object/string | - | Agent config for management create/update. |
|
|
47
84
|
| `context` | `fresh \| fork` | global or per-agent default, else `fresh` | Explicit `fresh` or `fork` overrides every workflow child. When omitted, [`defaultSubagentContext`](configuration.md#defaultsubagentcontext) wins over each agent's `defaultContext`; `"fork"` creates a real branched session when the parent session file and current leaf exist, otherwise it falls back to `fresh`. Packaged `worker`, `oracle`, and `advisor` default to `fork`. |
|
|
48
85
|
| `missionId` | string | - | Attach a workflow to an existing project mission instead of creating its default enclosing mission. |
|
|
49
86
|
| `mission` | object/false | auto-create | Override the default enclosing mission with `{ title \| summary, objective?, goal?, budget?, labels? }`. Set exactly one non-empty `title` or `summary`; `objective` and `labels` are optional. `goal` may only be `true`, requires `budget.tokens`, and enables continuation notices. Pass `false` for an intentionally ephemeral workflow with no mission for it or its children and no `state` global. Explicit mission persistence failures are strict. |
|
|
50
|
-
| `handoffPath` | string | - | Aggregate handoff manifest
|
|
87
|
+
| `handoffPath` | string | - | Aggregate handoff manifest for `action: "worktree.discard"` or lane evidence actions, or optional explicit metadata for `action: "worktree.cleanup"`. |
|
|
88
|
+
| `repo` | string | runtime cwd | Repository path for `action: "worktree.cleanup"`; plan mode only. The configured worktree base filters candidates but never discovers them. |
|
|
89
|
+
| `planId` | string | - | Reserved for a future `worktree.cleanup` apply action; rejected by the current plan-only action. |
|
|
90
|
+
| `mode` | `steer \| follow_up \| auto \| plan \| apply` | - | Delivery mode for `action: "steer"`; `worktree.cleanup` currently accepts `plan` only. Apply/removal is reserved for a later change. |
|
|
91
|
+
| `laneId` | string | - | Exact `runId` stored in the handoff manifest for `lane.status`, `lane.recordMerge`, or `lane.recordSupersession`. |
|
|
92
|
+
| `merge` | object | - | Attested merge evidence for `lane.recordMerge`; requires a positive PR number, full reviewed/merge SHAs, tree-equivalence and post-merge-check statuses, attestor, and timestamp. |
|
|
93
|
+
| `supersession` | object | - | Attested replacement-lane evidence for `lane.recordSupersession`; requires a different replacement lane id, attestor, and timestamp. |
|
|
51
94
|
| `focus` | boolean | false | Focus the newly split pane for `action: "inspector.open"` or `action: "project.open"`; not a standalone action. Panes open in the background unless you set `focus: true`. Existing saved project panes can be focused through the public project-pane API when Herdr reports a tab or workspace id. |
|
|
52
95
|
| `view` | `fleet \| transcript` | - | Optional `status` view for the active fleet surface or transcript tail inspection. |
|
|
53
96
|
| `lines` | number | `80` | Maximum transcript lines for `action: "status", view: "transcript"`; capped at 500. |
|
|
@@ -57,7 +100,6 @@ Use `workflowScriptPath` instead of `workflowScript` to load the same JavaScript
|
|
|
57
100
|
| `isolation` | `none \| worktree` | - | Workflow child isolation. `none` runs in the shared cwd and does not need Git. `worktree` requires a managed Git worktree. Do not combine it with a contradictory `worktree` value. |
|
|
58
101
|
| `timeoutMs` / `maxRuntimeMs` | number | config `timeoutMs`, else 30 min foreground / single-agent async | Optional run-level max runtime in milliseconds. When omitted, the global [`timeoutMs`](configuration.md#timeoutms) config provides the default; absent that, foreground and plain single-agent async runs fall back to 30 minutes, while composite async runs (chains, parallel tasks, workflows) stay unbounded at the top level. |
|
|
59
102
|
| `toolTimeoutMs` | number | fast-tool default | Optional positive hard per-tool-call deadline in milliseconds. Precedence: call value → agent frontmatter → config → `PI_SUBAGENT_TOOL_TIMEOUT_MS`. The timer starts on `tool_execution_start`, clears on the matching `tool_execution_end`, and terminates the run with `timedOut: true` if the tool remains open. When omitted, known-fast built-in tools get a five-minute default; long-running tools get attention notices but no hard default. It never extends the run deadline; `contact_supervisor`, `intercom`, and `subagent_wait` are exempt. |
|
|
60
|
-
| `turnBudget` | object | none | Optional assistant-turn budget `{ maxTurns, graceTurns }`. At `maxTurns` the child is warned to wrap up. After the grace window (default 1), termination occurs at the next assistant boundary; a response that starts tool work records `termination-deferred` until a later boundary. Partial output is returned on abort. |
|
|
61
103
|
| `toolBudget` | object | none | Optional child tool-call budget `{ soft?, hard, block? }`. At `soft` the child is nudged to finalize. After `hard`, configured tools are blocked; `block` defaults to `read`, `grep`, `find`, and `ls`, while `"*"` blocks every tool call. Final assistant text is never blocked. |
|
|
62
104
|
| `usageBudget` | object | none | Optional root-only reported-usage budget `{ tokens?: { soft?, hard }, costUsd?: { soft?, hard } }`. Soft limits are status-only. Hard limits prevent later child launches after reported usage is reconciled; already-running children are not stopped and no reservations are made. |
|
|
63
105
|
| `cwd` | string | runtime cwd | Override working directory. |
|
|
@@ -71,7 +113,7 @@ Use `workflowScriptPath` instead of `workflowScript` to load the same JavaScript
|
|
|
71
113
|
|
|
72
114
|
### Budget guidance for writers
|
|
73
115
|
|
|
74
|
-
As a conservative orchestration policy, do not set
|
|
116
|
+
As a conservative orchestration policy, do not set a hard `toolBudget` or tight `usageBudget` on implementation workers, fix workers, reviewers with edit authority, or other mutation-capable children. A default tool budget blocks read/search tools rather than mutation tools, and reported usage has no reservation model, so neither tool-call counts nor token/cost totals measure whether a delivery slice is buildable or safe to hand off. Hard caps remain appropriate for explicitly read-only scouts, reviewers, and validators.
|
|
75
117
|
|
|
76
118
|
Bound writer work with a narrow task and an outer `timeoutMs` or `maxRuntimeMs` that leaves enough margin for the slice. An elapsed timeout is not a mutation-safe boundary and may still signal a child during tool work. Before the deadline, use `steer` or an attention notice to request a checkpoint after the current tool returns, including changed files, build/test state, remaining work, and commit or PR state.
|
|
77
119
|
|
|
@@ -112,6 +154,8 @@ Use `outputMode: "file-only"` when a saved output may be large and the parent on
|
|
|
112
154
|
|
|
113
155
|
In workflowScript, give each child an explicit output path when later script steps need a durable file reference. A child with only read-only tools does not need direct filesystem access for `output`: it returns the complete artifact in its final response and the runtime persists it. Children with mutation-capable tools retain the direct-write instruction.
|
|
114
156
|
|
|
157
|
+
The `output` field is the API binding; a filename mentioned in task text (for example, `Write your findings to exactly this path: report.md`) is only instruction and does not override runtime routing. When a later workflow step or parent needs a durable file, set `output` on `runs.run`/`runs.all` and return the child’s `outputReference`, `outputPathMapping`, or `artifactPaths`; arbitrary literal strings returned by workflow JavaScript are not rewritten. Omitted child output may use a managed aggregate-derived sibling path.
|
|
158
|
+
|
|
115
159
|
Workflows get `await state.get(key)` and `await state.set(key, value)` through their default or explicit mission. Use them to share durable JSON values across later workflows attached with the same `missionId`. Each `set` takes the state-file lock and merges its key with the latest on-disk state. Missing keys return `undefined`, and the complete state file has a strict 256 KiB limit. `mission:false` workflows have no `state` global.
|
|
116
160
|
|
|
117
161
|
### Retained children
|
|
@@ -129,6 +173,8 @@ Completed workflow children from the current parent session stay addressable as
|
|
|
129
173
|
` }
|
|
130
174
|
```
|
|
131
175
|
|
|
176
|
+
Each workflow key identifies one result lane. Use a new stable workflow key for every distinct retained resume pass; same-key calls are reused only when launch parameters are identical, and incompatible parameters are rejected.
|
|
177
|
+
|
|
132
178
|
Inside `workflowScript`, `await runs.run(key, { resume, task })` waits for the revived child to finish and returns its completed output and new `runId`. Each resume can return a new retained run id, so loops must continue from the latest returned `runId`. Top-level `{ action: "resume" }` remains detached and returns a background-run receipt.
|
|
133
179
|
|
|
134
180
|
For a simple implementation challenge outside a workflow script, send the challenge through `subagent({ action: "resume", id: "<retained-writer-run>", message: "Reconsider the implementation and make any better current-scope change." })` only when `children.list` reports that retained writer as `resumable`. If no retained writer is resumable, start a same-role fallback challenge and record why it is a fallback. Use workflow `runs.run({ resume })` only when the script must await the revived writer output before the next step. Do not use `steer` as the sole challenge action for a completed retained child; `steer` with `mode: "follow_up"` only queues text for the next `resume`.
|
|
@@ -159,9 +205,10 @@ Agent definitions are not loaded into context by default. Management actions let
|
|
|
159
205
|
systemPrompt: "You are a code scout...",
|
|
160
206
|
systemPromptMode: "replace",
|
|
161
207
|
inheritProjectContext: false,
|
|
208
|
+
inheritGlobalContext: false,
|
|
162
209
|
inheritSkills: false,
|
|
163
210
|
model: "anthropic/claude-sonnet-4",
|
|
164
|
-
fallbackModels: ["openai/gpt-5-
|
|
211
|
+
fallbackModels: ["openai-codex/gpt-5.6-luna:low", "anthropic/claude-haiku-4-5"],
|
|
165
212
|
tools: "read, bash, mcp:github/search_repositories",
|
|
166
213
|
extensions: "",
|
|
167
214
|
skills: "parallel-scout",
|
|
@@ -200,6 +247,42 @@ Rules:
|
|
|
200
247
|
|
|
201
248
|
`refine`, `refine.show`, and `refine.rollback` manage project-local refinement overlays for one agent. `/subagents-refine <agent>` is the slash equivalent of `refine`. See [agents.md](agents.md#refinement-overlays) for behavior and storage.
|
|
202
249
|
|
|
250
|
+
## Lane merge evidence and cleanup eligibility
|
|
251
|
+
|
|
252
|
+
Lane evidence actions update an existing parallel handoff manifest at an explicit update boundary. They do not verify GitHub state, run Git commands, or remove worktrees. Pass the manifest path and its exact `runId` as `laneId`:
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
subagent({
|
|
256
|
+
action: "lane.recordMerge",
|
|
257
|
+
laneId: "<manifest-run-id>",
|
|
258
|
+
handoffPath: "/path/to/handoff.json",
|
|
259
|
+
merge: {
|
|
260
|
+
prNumber: 123,
|
|
261
|
+
reviewedHead: "<40-character-sha>",
|
|
262
|
+
mergeCommit: "<40-character-sha>",
|
|
263
|
+
treeEquivalent: true,
|
|
264
|
+
postMergeChecks: "recorded",
|
|
265
|
+
attestedBy: "operator",
|
|
266
|
+
attestedAt: "2026-08-27T16:23:00.000Z"
|
|
267
|
+
}
|
|
268
|
+
})
|
|
269
|
+
subagent({
|
|
270
|
+
action: "lane.recordSupersession",
|
|
271
|
+
laneId: "<manifest-run-id>",
|
|
272
|
+
handoffPath: "/path/to/handoff.json",
|
|
273
|
+
supersession: {
|
|
274
|
+
supersededBy: "<replacement-lane-id>",
|
|
275
|
+
attestedBy: "operator",
|
|
276
|
+
attestedAt: "2026-08-27T16:23:00.000Z"
|
|
277
|
+
}
|
|
278
|
+
})
|
|
279
|
+
subagent({ action: "lane.status", laneId: "<manifest-run-id>", handoffPath: "/path/to/handoff.json" })
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
The manifest stores one of these fail-closed eligibility states: `active` (an owning child is still running), `terminal-eligible` (complete merge evidence and recorded post-merge checks), `terminal-blocked` with a reason, `superseded-eligible` (an explicit replacement attestation), or `unknown` (missing or malformed evidence/manifest). Each attestation stores a digest of the manifest facts it covered; later group, worktree, or patch changes downgrade that evidence to `terminal-blocked` until it is recorded again. A terminal update recomputes a previously stored `active` state from the current child statuses and evidence. Conflicting reviewed heads and mismatched lane ids are rejected as stale. Existing workflow receipts remain immutable.
|
|
283
|
+
|
|
284
|
+
`lane.status` renders the stored state and a copy-pasteable `worktree.cleanup` plan invocation. It never runs that invocation. All cleanup planning/apply and apply-time Git/ownership revalidation belong to `worktree.cleanup` from #1622; remote branch deletion and extension-side GitHub verification remain out of scope.
|
|
285
|
+
|
|
203
286
|
## Status and control actions
|
|
204
287
|
|
|
205
288
|
```ts
|
|
@@ -249,6 +332,7 @@ subagent({ action: "doctor" })
|
|
|
249
332
|
- Direct id calls execute immediately.
|
|
250
333
|
- `/subagents-stop` without an id opens a selector with confirmation when a TUI is available. Use `↑`/`↓` or `j`/`k` to move through the selector.
|
|
251
334
|
- In non-TUI contexts the slash command prints exact `subagent({ action: "stop", id })` and `/subagents-stop <id>` commands.
|
|
335
|
+
- Pass a child id to stop one child of a multi-child async run or workflow while the rest continue: `/subagents-stop <run-id> <child-id>` (equivalent to `subagent({ action: "stop", id, childId })`). Child ids come from status output, the async status snapshot, or `/subagents-inspect-rpc` replies. Only pending or running children are stoppable; the request is rejected for anything else instead of widening to a run-level stop.
|
|
252
336
|
- Inactive schedules can appear in the selector, but they are labeled as schedules and route through `schedule.pause`, not `stop`.
|
|
253
337
|
|
|
254
338
|
### steer
|
|
@@ -261,6 +345,8 @@ Only a top-level single run may interrupt after the acknowledgment deadline and
|
|
|
261
345
|
|
|
262
346
|
The persisted `steering` ledger retains 20 requests and replaces the old `steerCount`/`lastSteerAt` fields.
|
|
263
347
|
|
|
348
|
+
The `/subagents-steer <run-id> [--child <child-id>] <message>` slash command is the host bridge for non-TUI sessions and RPC hosts. `--child` accepts the stable child identity shown in status output and inspect replies (workflow key, child run id, or `step:<index>`) and resolves it to the child index before steering; unknown or ambiguous child ids fail closed. Flags are parsed only between the run id and the message tail — once the message starts, `--` tokens are message text. The bridge always disables pause-and-revive recovery (`steeringRecovery: false`), matching the extension RPC `nonRecoveringSteer` guarantee so the caller keeps authority over the exact child it addressed.
|
|
349
|
+
|
|
264
350
|
## Acceptance gates
|
|
265
351
|
|
|
266
352
|
Every run resolves an effective acceptance policy. Callers may omit `acceptance` for the inferred default, or set it on single runs, top-level parallel task items, chain steps, static parallel tasks, and dynamic fanout templates.
|
|
@@ -371,7 +457,7 @@ async: true
|
|
|
371
457
|
|
|
372
458
|
Supported: status artifacts, stdout/stderr logs, timeout, and stop. Full stdout and stderr are written to log files, while the in-memory final stdout response and stderr error are limited to their last 64 KiB.
|
|
373
459
|
|
|
374
|
-
Intentionally unsupported:
|
|
460
|
+
Intentionally unsupported: native Pi child options such as model override, structured output, acceptance/agent contract, tool budgets, fast mode, fork context, skills, or native Pi tools unless the runner explicitly implements them. Foreground/clarify, steer/resume/interrupt-as-pause, nested subagents, and fallback models are also unsupported.
|
|
375
461
|
|
|
376
462
|
## Session sharing
|
|
377
463
|
|