pi-subagents 0.34.0 → 0.35.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 +78 -9
- package/README.md +213 -32
- package/index.ts +1 -0
- package/install.mjs +1 -1
- package/package.json +23 -8
- package/prompts/review-loop.md +3 -1
- package/skills/pi-subagents/SKILL.md +87 -25
- package/src/agents/agent-management.ts +82 -15
- package/src/agents/agent-serializer.ts +19 -0
- package/src/agents/agents.ts +91 -49
- package/src/agents/frontmatter.ts +67 -13
- package/src/agents/skills.ts +25 -12
- package/src/api/background-work.ts +197 -0
- package/src/api/delegation.ts +158 -0
- package/src/extension/chain-validation.ts +165 -0
- package/src/extension/doctor.ts +15 -0
- package/src/extension/fanout-child.ts +3 -1
- package/src/extension/index.ts +65 -124
- package/src/extension/rpc.ts +10 -2
- package/src/extension/schemas.ts +18 -14
- package/src/extension/steering-notices.ts +35 -0
- package/src/extension/tool-description.ts +20 -9
- package/src/intercom/intercom-bridge.ts +3 -2
- package/src/intercom/native-supervisor-channel.ts +9 -1
- package/src/intercom/result-intercom.ts +4 -0
- package/src/runs/background/async-execution.ts +293 -44
- package/src/runs/background/async-job-tracker.ts +56 -9
- package/src/runs/background/async-resume.ts +159 -52
- package/src/runs/background/async-status.ts +25 -18
- package/src/runs/background/auto-drain.ts +67 -0
- package/src/runs/background/chain-root-attachment.ts +16 -8
- package/src/runs/background/control-channel.ts +260 -13
- package/src/runs/background/fleet-view.ts +23 -2
- package/src/runs/background/notify.ts +79 -10
- package/src/runs/background/result-watcher.ts +12 -9
- package/src/runs/background/run-id-resolver.ts +14 -2
- package/src/runs/background/run-status.ts +23 -15
- package/src/runs/background/scheduled-runs.ts +3 -0
- package/src/runs/background/stale-run-reconciler.ts +32 -10
- package/src/runs/background/steering.ts +237 -0
- package/src/runs/background/subagent-runner.ts +898 -236
- package/src/runs/background/subagent-wait.ts +484 -0
- package/src/runs/background/top-level-async.ts +2 -1
- package/src/runs/background/wait-config.ts +36 -0
- package/src/runs/background/wait-tool.ts +26 -0
- package/src/runs/foreground/async-steering-action.ts +230 -0
- package/src/runs/foreground/chain-clarify.ts +22 -6
- package/src/runs/foreground/chain-execution.ts +50 -32
- package/src/runs/foreground/execution.ts +308 -94
- package/src/runs/foreground/subagent-executor.ts +592 -268
- package/src/runs/shared/acceptance.ts +355 -97
- package/src/runs/shared/child-protocol.ts +121 -0
- package/src/runs/shared/completion-guard.ts +8 -127
- package/src/runs/shared/dynamic-fanout.ts +6 -4
- package/src/runs/shared/model-fallback.ts +36 -0
- package/src/runs/shared/nested-events.ts +9 -4
- package/src/runs/shared/nested-render.ts +4 -1
- package/src/runs/shared/parallel-utils.ts +7 -0
- package/src/runs/shared/pi-args.ts +34 -7
- package/src/runs/shared/pi-spawn.ts +18 -12
- package/src/runs/shared/session-lease.ts +279 -0
- package/src/runs/shared/single-output.ts +61 -6
- package/src/runs/shared/spawn-budget.ts +128 -0
- package/src/runs/shared/subagent-control.ts +10 -6
- package/src/runs/shared/subagent-prompt-runtime.ts +127 -26
- package/src/runs/shared/task-intent.ts +176 -0
- package/src/runs/shared/tool-availability.ts +65 -0
- package/src/runs/shared/turn-budget.ts +49 -4
- package/src/shared/atomic-json.ts +4 -1
- package/src/shared/fork-context.ts +28 -3
- package/src/shared/model-info.ts +7 -4
- package/src/shared/status-format.ts +7 -1
- package/src/shared/types.ts +203 -25
- package/src/shared/utils.ts +35 -7
- package/src/slash/delegation-adapters.ts +457 -0
- package/src/slash/delegation-request.ts +103 -0
- package/src/slash/prompt-template-bridge.ts +167 -344
- package/src/slash/slash-commands.ts +239 -6
- package/src/slash/subagents-admin.ts +428 -0
- package/src/slash/subagents-editor.ts +86 -0
- package/src/tui/fleet.ts +405 -0
- package/src/tui/render.ts +90 -16
- package/src/watchdog/change-signature.ts +127 -0
- package/src/watchdog/child-status.ts +205 -0
- package/src/watchdog/emission-guard.ts +123 -0
- package/src/watchdog/lsp-diagnostics.ts +532 -0
- package/src/watchdog/model-selection.ts +167 -0
- package/src/watchdog/register-child.ts +117 -0
- package/src/watchdog/register-main.ts +433 -0
- package/src/watchdog/render.ts +54 -0
- package/src/watchdog/review.ts +293 -0
- package/src/watchdog/runtime.ts +712 -0
- package/src/watchdog/settings.ts +528 -0
- package/src/watchdog/tool-actions.ts +155 -0
- package/src/watchdog/turn-delta.ts +161 -0
- package/src/watchdog/types.ts +188 -0
- package/src/watchdog/warning-format.ts +73 -0
- package/src/runs/background/wait.ts +0 -394
package/package.json
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-subagents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"description": "Pi extension for delegating tasks to subagents with chains, parallel execution, and TUI clarification",
|
|
5
5
|
"author": "Nico Bailon",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./index.ts",
|
|
10
|
+
"./background-work": "./src/api/background-work.ts",
|
|
11
|
+
"./delegation": "./src/api/delegation.ts"
|
|
12
|
+
},
|
|
8
13
|
"repository": {
|
|
9
14
|
"type": "git",
|
|
10
15
|
"url": "git+https://github.com/nicobailon/pi-subagents.git"
|
|
@@ -26,6 +31,7 @@
|
|
|
26
31
|
"pi-subagents": "install.mjs"
|
|
27
32
|
},
|
|
28
33
|
"files": [
|
|
34
|
+
"index.ts",
|
|
29
35
|
"src/**/*.ts",
|
|
30
36
|
"*.mjs",
|
|
31
37
|
"agents/",
|
|
@@ -43,7 +49,7 @@
|
|
|
43
49
|
},
|
|
44
50
|
"pi": {
|
|
45
51
|
"extensions": [
|
|
46
|
-
"./
|
|
52
|
+
"./index.ts"
|
|
47
53
|
],
|
|
48
54
|
"skills": [
|
|
49
55
|
"./skills"
|
|
@@ -55,7 +61,9 @@
|
|
|
55
61
|
"peerDependencies": {
|
|
56
62
|
"@earendil-works/pi-agent-core": "*",
|
|
57
63
|
"@earendil-works/pi-ai": "*",
|
|
58
|
-
"@earendil-works/pi-coding-agent": "*"
|
|
64
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
65
|
+
"@earendil-works/pi-tui": "*",
|
|
66
|
+
"typebox": "*"
|
|
59
67
|
},
|
|
60
68
|
"peerDependenciesMeta": {
|
|
61
69
|
"@earendil-works/pi-agent-core": {
|
|
@@ -66,16 +74,23 @@
|
|
|
66
74
|
},
|
|
67
75
|
"@earendil-works/pi-coding-agent": {
|
|
68
76
|
"optional": true
|
|
77
|
+
},
|
|
78
|
+
"@earendil-works/pi-tui": {
|
|
79
|
+
"optional": true
|
|
80
|
+
},
|
|
81
|
+
"typebox": {
|
|
82
|
+
"optional": true
|
|
69
83
|
}
|
|
70
84
|
},
|
|
71
85
|
"dependencies": {
|
|
72
|
-
"@earendil-works/pi-tui": "0.74.0",
|
|
73
86
|
"jiti": "2.7.0",
|
|
74
|
-
"
|
|
87
|
+
"yaml": "2.8.3"
|
|
75
88
|
},
|
|
76
89
|
"devDependencies": {
|
|
77
|
-
"@earendil-works/pi-agent-core": "0.
|
|
78
|
-
"@earendil-works/pi-ai": "0.
|
|
79
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
90
|
+
"@earendil-works/pi-agent-core": "0.80.10",
|
|
91
|
+
"@earendil-works/pi-ai": "0.80.10",
|
|
92
|
+
"@earendil-works/pi-coding-agent": "0.80.10",
|
|
93
|
+
"@earendil-works/pi-tui": "0.80.10",
|
|
94
|
+
"typebox": "1.1.38"
|
|
80
95
|
}
|
|
81
96
|
}
|
package/prompts/review-loop.md
CHANGED
|
@@ -10,6 +10,8 @@ Default to a maximum of 3 review rounds unless I specify a different cap. Count
|
|
|
10
10
|
|
|
11
11
|
If the invocation includes an implementation request, first launch one async `worker` to implement the approved scope. If the current diff is already the target, start with review. The sequence can be launched up front as an async/background chain when the workflow is already clear, or continued as follow-up subagent runs after each async completion. For an initial chain, pass `async: true` so the main chat is unblocked; do not set `clarify: true` unless I explicitly want the foreground clarify UI. Use only one writer against the active worktree at a time unless I explicitly ask for isolated worktrees.
|
|
12
12
|
|
|
13
|
+
As a conservative orchestration policy, do not set `turnBudget` or a hard `toolBudget` on implementation or fix workers. A default tool budget blocks read/search tools rather than mutation tools, but count limits still do not measure delivery safety. Give each writer a narrow delivery slice and an outer elapsed deadline with enough margin. Before that deadline, request a checkpoint after the current tool returns with changed files, build/test state, remaining work, and commit or PR state. An elapsed timeout is not a mutation-safe boundary and must not be the checkpoint trigger.
|
|
14
|
+
|
|
13
15
|
For each review round, launch fresh-context `reviewer` agents in parallel. Reviewers must inspect the repository, relevant instructions, and current diff directly from files and commands. They must not rely on the main conversation history and must not edit files.
|
|
14
16
|
|
|
15
17
|
Choose review angles from the actual change. Common angles are correctness/regressions, tests/validation, and simplicity/maintainability. Add security, performance, docs/API contracts, or user-flow validation when the work calls for it. Prefer three strong reviewers over many vague reviewers.
|
|
@@ -24,7 +26,7 @@ Do not blindly apply every reviewer suggestion. If reviewers surface an unapprov
|
|
|
24
26
|
|
|
25
27
|
When an async implementation worker completes, treat its handoff as the transition into review, not as final completion, unless I explicitly asked for worker-only work, review-only output, or to stop after implementation.
|
|
26
28
|
|
|
27
|
-
When there are fixes worth doing now and the workflow is implementation-authorized, launch one async forked `worker` to apply only those synthesized fixes. Ask it to preserve the approved scope, run focused validation, and report changed files, commands run with exit codes, validation evidence, surprises, and anything left undone.
|
|
29
|
+
When there are fixes worth doing now and the workflow is implementation-authorized, launch one async forked `worker` without hard turn or tool-call caps to apply only those synthesized fixes. Ask it to preserve the approved scope, run focused validation, and report changed files, commands run with exit codes, validation evidence, surprises, and anything left undone.
|
|
28
30
|
|
|
29
31
|
After a fix worker returns, run another review round only when it made material changes or addressed non-trivial findings. Do not keep looping for optional polish, speculative improvements, or findings already deferred by the parent.
|
|
30
32
|
|
|
@@ -16,12 +16,13 @@ Use this skill when the parent orchestrator needs to launch a specialized subage
|
|
|
16
16
|
|
|
17
17
|
## When to Use
|
|
18
18
|
|
|
19
|
+
- **Complex work orchestration**: use Fable mode as the default parent-agent loop for complex work. Complex means the task has multiple moving parts, unclear acceptance, cross-cutting code, meaningful user-visible impact, expensive or irreversible validation, broad review surface, or the user asks for orchestration. Lightweight one-off delegation can stay lightweight.
|
|
19
20
|
- **Advisory review**: use fresh-context `reviewer` agents for adversarial code review, or fork to `oracle` when inherited decisions and drift matter
|
|
20
21
|
- **Implementation handoff**: have `oracle` advise, then `worker` implement only after an approved direction
|
|
21
22
|
- **Recon and planning**: use `scout` or `context-builder`, then `planner`
|
|
22
23
|
- **Parallel exploration**: run multiple non-conflicting tasks concurrently
|
|
23
24
|
- **Regular skill specialists**: when discovery shows proactive skill subagent suggestions and the current work is broad enough, launch a small fresh-context fanout that asks one subagent per relevant regularly used skill to apply that skill's perspective to the task
|
|
24
|
-
- **Long-running work**: launch async/background runs and inspect them later
|
|
25
|
+
- **Long-running work**: launch async/background runs and inspect them later. For mutation-capable work, bound the delivery slice and elapsed runtime, then request checkpoints after active tool work returns. Reserve hard turn and tool-call caps for explicitly read-only children.
|
|
25
26
|
- **Subagent control**: watch needs-attention signals and soft-interrupt only when a delegated run is genuinely blocked
|
|
26
27
|
- **Agent authoring**: create, update, or override agents and chains for a project
|
|
27
28
|
|
|
@@ -34,7 +35,12 @@ Humans often use the slash-command layer instead:
|
|
|
34
35
|
- `/chain` — launch a chain of steps
|
|
35
36
|
- `/parallel` — launch top-level parallel tasks
|
|
36
37
|
- `/run-chain` — launch a saved `.chain.md` or `.chain.json` workflow
|
|
38
|
+
- `/subagent-cost` — show parent plus child token usage and cost for the session
|
|
39
|
+
- `/subagents-fleet` — open the live, inspection-only foreground/async fleet; `Ctrl+Alt+F` opens it during an active foreground turn, `↑↓`/`jk` selects children, and `PgUp`/`PgDn` scrolls transcript detail
|
|
37
40
|
- `/subagents-doctor` — diagnose setup, discovery, async paths, and intercom bridge state
|
|
41
|
+
- `/subagents-models [agent]` — show the live runtime-loaded builtin model mapping
|
|
42
|
+
- `/subagents-profiles`, `/subagents-load-profile`, `/subagents-refresh-provider-models`, `/subagents-generate-profiles`, `/subagents-check-profile` — manage model profiles and provider catalogs
|
|
43
|
+
- `/prompt-workflow` and `/chain-prompts` — run prompt templates through native subagent single/chain workflows
|
|
38
44
|
|
|
39
45
|
Prefer the tool when you are writing agent logic. Prefer the slash commands when
|
|
40
46
|
you are guiding a human through an interactive flow.
|
|
@@ -84,6 +90,8 @@ subagent({
|
|
|
84
90
|
|
|
85
91
|
Use this when the user wants implementation or current diff review to continue until reviewers stop finding fixes worth doing now. Keep the loop in the parent session: one async `worker` implements or fixes, fresh-context `reviewer` agents inspect the actual repo and diff, the parent synthesizes accepted fixes, and one async forked `worker` applies them. The parent can express the sequence up front as an async/background chain when the workflow is known, or continue with explicit follow-up subagent runs after each async completion. For an initial chain, pass `async: true` so the main chat is unblocked; do not set `clarify: true` unless the user explicitly wants the foreground clarify UI. Treat an async implementation worker handoff as an intermediate state, not final completion, unless the user explicitly asked for worker-only work, review-only output, or to stop after implementation. Stop when reviewers find no blockers or fixes worth doing now, remaining feedback is optional or deferred, an unapproved product/scope/architecture decision appears, or the max review-round cap is reached. Default to 3 review rounds unless the user sets a different cap. Do not loop for optional polish, and do not let children launch subagents or decide the loop outcome.
|
|
86
92
|
|
|
93
|
+
As a conservative orchestration policy, do not pass `turnBudget` or a hard `toolBudget` to an implementation worker, fix worker, reviewer with edit authority, or other mutation-capable child. The default tool budget blocks read/search tools rather than mutation tools, but count limits still do not measure delivery safety. Use a narrow task plus an outer elapsed deadline with enough margin, then request a checkpoint after the current tool returns. The checkpoint should report changed files, build/test state, remaining work, and commit or PR state. An elapsed timeout is not a mutation-safe boundary and must not be used as the checkpoint trigger.
|
|
94
|
+
|
|
87
95
|
### Parallel research technique
|
|
88
96
|
|
|
89
97
|
Use this when the question needs both external evidence and local implications. Combine `researcher` for official docs, specs, ecosystem behavior, recent changes, benchmarks, and primary sources with `scout` for repository files, patterns, constraints, tests, and likely integration points. Give each child a distinct angle: external evidence, local code context, and practical tradeoffs. Ask for source links or file ranges, confidence level, gaps, and decision implications. Do not ask these children to edit unless implementation was explicitly requested.
|
|
@@ -184,7 +192,7 @@ and user/project agents override builtins with the same name.
|
|
|
184
192
|
| `delegate` | Lightweight generic delegate | inherits default | No fixed output; generic delegated work |
|
|
185
193
|
| `oracle` | Decision-consistency advisory review | inherits default | Advisory review, intercom coordination |
|
|
186
194
|
|
|
187
|
-
Builtin agents inherit the current Pi default model unless a run, user setting,
|
|
195
|
+
Builtin agents inherit the current Pi default model unless a run, user setting, project setting, or `subagents.defaultModel` overrides `model`. Set `subagents.defaultModel` when subagents should use a different default model than the parent session. Override builtin defaults before copying full agent files when a small tweak is enough.
|
|
188
196
|
|
|
189
197
|
For one run, use inline config:
|
|
190
198
|
|
|
@@ -192,9 +200,11 @@ For one run, use inline config:
|
|
|
192
200
|
/run reviewer[model=anthropic/claude-sonnet-4] "Review this diff"
|
|
193
201
|
```
|
|
194
202
|
|
|
195
|
-
For persistent tweaks, edit `subagents.agentOverrides` in user or project settings. User overrides apply everywhere. Project overrides apply only in that repo and win over user overrides.
|
|
203
|
+
For persistent tweaks, edit `subagents.agentOverrides` in user or project settings. User overrides apply everywhere. Project overrides apply only in that repo and win over user overrides. Use `/subagents-models` or `subagent({ action: "models" })` to inspect the live mapping after settings and overrides load.
|
|
204
|
+
|
|
205
|
+
Model ids do not have to be exact. Separator variations (`claude-haiku-4.5` vs `claude-haiku-4-5`), case (`Claude-Sonnet-4`), and optional trailing date stamps (`claude-haiku-4-5-20251001`) all resolve to the same registry model. Exact `provider/id` wins; a qualified `provider/model` never switches providers. To constrain subagents to a budget or compliance profile, set `subagents.modelScope: { enforce: true, allow: ["anthropic/*", "openai/gpt-5-*"] }` in user or project settings. Out-of-scope models you pass explicitly error and abort; models inherited from frontmatter, `subagents.defaultModel`, agent frontmatter, or the parent session only warn.
|
|
196
206
|
|
|
197
|
-
|
|
207
|
+
For model fleets, use the profile commands instead of hand-editing repeated overrides: `/subagents-refresh-provider-models <provider>`, `/subagents-generate-profiles <provider>`, `/subagents-load-profile <name>`, and `/subagents-check-profile <name>`. Profiles live under `~/.pi/agent/profiles/pi-subagents/` and replace only `settings.subagents` when loaded.
|
|
198
208
|
|
|
199
209
|
## Prompting role subagents
|
|
200
210
|
|
|
@@ -226,7 +236,8 @@ Direct settings example:
|
|
|
226
236
|
"reviewer": {
|
|
227
237
|
"model": "anthropic/claude-sonnet-4",
|
|
228
238
|
"thinking": "high",
|
|
229
|
-
"fallbackModels": ["openai/gpt-5-mini"]
|
|
239
|
+
"fallbackModels": ["openai/gpt-5-mini"],
|
|
240
|
+
"acceptanceRole": "read-only"
|
|
230
241
|
}
|
|
231
242
|
}
|
|
232
243
|
}
|
|
@@ -235,7 +246,8 @@ Direct settings example:
|
|
|
235
246
|
|
|
236
247
|
Useful override fields: `model`, `fallbackModels`, `thinking`,
|
|
237
248
|
`systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `defaultContext`,
|
|
238
|
-
`disabled`, `skills`, `tools`, and `systemPrompt`.
|
|
249
|
+
`acceptanceRole`, `disabled`, `skills`, `tools`, and `systemPrompt`. Use
|
|
250
|
+
`acceptanceRole: false` to clear an override. Create a user or project
|
|
239
251
|
agent with the same name only when you want a substantially different agent.
|
|
240
252
|
|
|
241
253
|
If a provider rejects model IDs with thinking suffixes, use
|
|
@@ -243,7 +255,7 @@ If a provider rejects model IDs with thinking suffixes, use
|
|
|
243
255
|
builtin thinking defaults globally. A higher-precedence per-agent `thinking`
|
|
244
256
|
override can opt one builtin back in.
|
|
245
257
|
|
|
246
|
-
Tool description modes live in `~/.pi/agent/extensions/subagent/config.json`, not `subagents` settings. Set `toolDescriptionMode` to `compact` to reduce tool-description prompt cost while keeping the execution, async
|
|
258
|
+
Tool description modes live in `~/.pi/agent/extensions/subagent/config.json`, not `subagents` settings. Set `toolDescriptionMode` to `compact` to reduce tool-description prompt cost while keeping the execution, async/`subagent_wait`, child-safety, one-writer, management/action, and artifact/status guardrails. Set it to `custom` to read `subagent-tool-description.md` from the project config dir or agent dir; invalid custom files fall back to full mode and the safety guidance is still appended.
|
|
247
259
|
|
|
248
260
|
## Discovery and Scope Rules
|
|
249
261
|
|
|
@@ -312,7 +324,7 @@ subagent({
|
|
|
312
324
|
})
|
|
313
325
|
```
|
|
314
326
|
|
|
315
|
-
Avoid duplicate output paths in parallel tasks. Concurrent children should not write to the same file. For large saved outputs, set `outputMode: "file-only"` together with an `output` path. The parent result then contains only a compact reference like `Output saved to: /abs/report.md (48.2 KB, 2847 lines). Read this file if needed.` instead of the full saved content. Do not use `output: false` for this; `output: false` means no file output.
|
|
327
|
+
Avoid duplicate output paths in parallel tasks. Concurrent children should not write to the same file. For large saved outputs, set `outputMode: "file-only"` together with an `output` path. The parent result then contains only a compact reference like `Output saved to: /abs/report.md (48.2 KB, 2847 lines). Read this file if needed.` instead of the full saved content. Do not use `output: false` for this; `output: false` means no file output. Read-only children return the complete artifact in their final response and the runtime persists it, so missing write tools are not a supervisor blocker. Mutation-capable children still receive direct-write instructions. Failed runs and save errors still return inline details for debugging.
|
|
316
328
|
|
|
317
329
|
### Chain execution
|
|
318
330
|
|
|
@@ -342,9 +354,9 @@ Async does not mean parallel writes. Do not edit the same active worktree while
|
|
|
342
354
|
|
|
343
355
|
Do not end your turn immediately after launching an async child if you promised to keep working. Continue the local inspection, synthesis, or validation prep, then check the async run when its result is needed.
|
|
344
356
|
|
|
345
|
-
|
|
357
|
+
In an interactive chat, normally return control when ready to yield and let Pi wake the session on completion; do not call `subagent_wait()` merely to wait. Override that default and call it when the current request is run-to-completion — for example, the user asked you to report results back before continuing or a skill cannot return before its background work finishes. Headless sessions auto-drain exact current-session work at `agent_end`; call `subagent_wait()` when this turn must receive results before it ends. Never substitute sleep or status-polling loops.
|
|
346
358
|
|
|
347
|
-
|
|
359
|
+
`subagent_wait()` returns when the next initially active async run or registered provider item finishes or a subagent needs attention. Use `subagent_wait({ all: true })` for all work active at call time, `subagent_wait({ id: "..." })` for one async or remembered detached foreground run, and `subagent_wait({ timeoutMs })` to cap the block. If a foreground child detaches for supervisor coordination, reply first, then wait on its id; do not resume or launch a replacement while it remains detached. Headless sessions also auto-drain exact current-session work at `agent_end` as a final safeguard.
|
|
348
360
|
|
|
349
361
|
```typescript
|
|
350
362
|
subagent({
|
|
@@ -370,21 +382,25 @@ const run = subagent({
|
|
|
370
382
|
|
|
371
383
|
Inspect async runs with `subagent({ action: "status", id: "..." })` or `subagent({ action: "status" })` for active runs. Use `subagent({ action: "status", view: "fleet" })` when supervising several active foreground/background runs and `subagent({ action: "status", id: "...", view: "transcript", index: 0 })` when you need the latest child output without digging through artifacts. If a delegated fanout child launches nested runs, the parent status view shows them as a tree and you can target a nested run directly with its nested id.
|
|
372
384
|
|
|
373
|
-
Use `
|
|
385
|
+
Use `steer` for top-level live async guidance and `resume` after a delegated run pauses or finishes. Routed nested runs retain their existing non-destructive live follow-up path:
|
|
374
386
|
|
|
375
387
|
```typescript
|
|
388
|
+
subagent({ action: "steer", id: "run-id", message: "Focus on the failing test." })
|
|
376
389
|
subagent({ action: "resume", id: "run-id", message: "Follow up on this point." })
|
|
377
390
|
subagent({ action: "resume", id: "run-id", index: 1, message: "Continue reviewer 2." })
|
|
378
391
|
subagent({ action: "resume", id: "nested-run-id", message: "Continue this nested reviewer." })
|
|
379
392
|
```
|
|
380
393
|
|
|
381
394
|
Resume behavior:
|
|
382
|
-
-
|
|
395
|
+
- `resume` revives paused, completed, or failed async/foreground children from persisted session files; stopped runs remain non-resumable, and it does not interrupt live top-level async children.
|
|
396
|
+
- Use `steer` for acknowledged guidance to a live top-level async child.
|
|
397
|
+
- A live nested run can still receive a non-destructive `resume` follow-up through its owner route.
|
|
383
398
|
- If an async child has completed, `resume` revives it by starting a new async child from the persisted child session file.
|
|
384
399
|
- Multi-child async runs require `index` unless only one running child is selectable.
|
|
385
400
|
- Completed foreground single, parallel, and chain runs can also be revived by `index` while their run metadata remains in extension state.
|
|
386
401
|
- Nested runs can be resumed by nested id when a live route or persisted nested session metadata is available.
|
|
387
402
|
- Revive starts a new child process from the old session context; it does not restart the same OS process.
|
|
403
|
+
- Direct revival holds an exclusive cross-process lease on the canonical child session file until the new child finishes. Concurrent attempts fail before Pi starts and identify the owning revived run; stale ownership is reclaimed only when the recorded process is demonstrably gone or reused.
|
|
388
404
|
- If the chosen child has no persisted `.jsonl` session file, resume fails and reports that directly.
|
|
389
405
|
|
|
390
406
|
Use diagnostics when setup or child startup looks wrong:
|
|
@@ -410,7 +426,7 @@ subagent({ action: "schedule-status", id: "ab12" })
|
|
|
410
426
|
subagent({ action: "schedule-cancel", id: "ab12" })
|
|
411
427
|
```
|
|
412
428
|
|
|
413
|
-
`schedule` accepts the same execution fields as a normal async run (`agent`/`tasks`/`chain`, `cwd`, `model`, `output`, `reads`, `progress`, `acceptance`, `timeoutMs`) plus `schedule` (a relative delay like `+10m`/`+2h`/`+1d` or a future ISO timestamp with a timezone such as `2030-01-01T09:00:00Z`) and an optional `scheduleName`. Scheduled runs always launch async with fresh context; `context: "fork"`, `async: false`, and `clarify: true` are rejected. Once the timer fires, the run becomes a normal tracked async run: it appears in the async widget, is inspectable with `subagent({ action: "status" })`, can be awaited with `
|
|
429
|
+
`schedule` accepts the same execution fields as a normal async run (`agent`/`tasks`/`chain`, `cwd`, `model`, `output`, `reads`, `progress`, `acceptance`, `timeoutMs`) plus `schedule` (a relative delay like `+10m`/`+2h`/`+1d` or a future ISO timestamp with a timezone such as `2030-01-01T09:00:00Z`) and an optional `scheduleName`. Scheduled runs always launch async with fresh context; `context: "fork"`, `async: false`, and `clarify: true` are rejected. Once the timer fires, the run becomes a normal tracked async run: it appears in the async widget, is inspectable with `subagent({ action: "status" })`, can be awaited with `subagent_wait()`, and delivers the normal completion notification.
|
|
414
430
|
|
|
415
431
|
Schedules are persisted per session and restored after a Pi restart. A job whose scheduled time passed by more than `scheduledRuns.maxLatenessMs` (default 5 minutes) while Pi was unavailable is marked `missed` instead of firing late. `scheduledRuns.maxPending` (default 20) caps pending or running scheduled jobs per session.
|
|
416
432
|
|
|
@@ -452,6 +468,14 @@ subagent({
|
|
|
452
468
|
|
|
453
469
|
If the run already has an active intercom bridge target, needs-attention notifications can also prepare a compact intercom ping for the orchestrator. When a child route is available, the ping tells the orchestrator which agent needs attention and includes the exact `intercom({ action: "send", to: "..." })` target for a nudge. Do not invent a target or ask the child to self-report when no bridge exists.
|
|
454
470
|
|
|
471
|
+
Steering is acknowledged delivery, not a send attempt or model-compliance signal:
|
|
472
|
+
|
|
473
|
+
```typescript
|
|
474
|
+
subagent({ action: "steer", id: "abc123", message: "Focus on the failing test." })
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
The action waits up to three seconds for the child Pi session to accept the correlated user input and returns a request id with `delivered`, `scheduled`, `pending`, `partial`, `recovered`, or `failed` plus per-child states. Indexed pending children return `scheduled` immediately. Only a top-level single-child run may automatically interrupt after a missed acknowledgment and recover after confirmed pause within a further 15 seconds. Recovery preserves the original child contract and only its remaining deadline, turn, and tool budgets. If the session is missing, a budget is exhausted, the pause cannot be confirmed, or replacement launch fails, the source remains paused when pausing succeeded and the action returns the exact failure. Chain, parallel, and nested runs never auto-interrupt; inspect their per-child outcomes and handle failures explicitly. A late acknowledgment is recorded and cannot cancel committed recovery.
|
|
478
|
+
|
|
455
479
|
## Clarify TUI
|
|
456
480
|
|
|
457
481
|
Single and parallel runs support a clarification TUI when you want to preview or
|
|
@@ -529,6 +553,8 @@ Use `contact_supervisor` with `reason: "need_decision"` when:
|
|
|
529
553
|
- a child needs clarification instead of guessing
|
|
530
554
|
- an approval, product, API, or scope choice is required before continuing safely
|
|
531
555
|
|
|
556
|
+
Use `contact_supervisor` with `reason: "interview_request"` when the child needs structured supervisor input rather than a freeform answer. The request waits for a parent reply, so the child should stay alive and continue only after the reply arrives.
|
|
557
|
+
|
|
532
558
|
Do not use `contact_supervisor` just to resolve review-only/no-project-edit versus progress-writing or output-artifact instructions. The child must not modify project/source files, but returning findings through its normal response or configured output artifact is allowed unless the parent explicitly set `output: false`.
|
|
533
559
|
|
|
534
560
|
Use `contact_supervisor` with `reason: "progress_update"` when:
|
|
@@ -537,7 +563,7 @@ Use `contact_supervisor` with `reason: "progress_update"` when:
|
|
|
537
563
|
- a long-running child needs to report a blocked/progress checkpoint without waiting for normal tool return flow
|
|
538
564
|
|
|
539
565
|
Message conventions:
|
|
540
|
-
- `reason: "need_decision"`
|
|
566
|
+
- `reason: "need_decision"` and `reason: "interview_request"` wait for the parent reply and return it to the child.
|
|
541
567
|
- `reason: "progress_update"` is non-blocking and should stay concise.
|
|
542
568
|
- Child-side routine completion handoffs are not expected. Native supervisor messages are for decisions, structured input, and meaningful progress updates while a child is still running.
|
|
543
569
|
|
|
@@ -648,6 +674,8 @@ tools: read, grep, find, ls, bash
|
|
|
648
674
|
systemPromptMode: replace
|
|
649
675
|
inheritProjectContext: true
|
|
650
676
|
inheritSkills: false
|
|
677
|
+
skills: safe-bash, review-checklist
|
|
678
|
+
skillPath: ./skills, ../shared-skills
|
|
651
679
|
---
|
|
652
680
|
|
|
653
681
|
Your system prompt here.
|
|
@@ -658,7 +686,21 @@ That is only a starting point. Omit `package` for the traditional unqualified ru
|
|
|
658
686
|
- `defaultReads`
|
|
659
687
|
- `output`
|
|
660
688
|
- `fallbackModels`
|
|
689
|
+
- `subagentOnlyExtensions`
|
|
690
|
+
- `skills`
|
|
691
|
+
- `skillPath`
|
|
692
|
+
- `memory`
|
|
661
693
|
- `maxSubagentDepth`
|
|
694
|
+
- `acceptance`
|
|
695
|
+
- `acceptanceRole`
|
|
696
|
+
|
|
697
|
+
`acceptance` is a single-agent launch default. Use a scalar level such as `checked` or an inline/block YAML map such as `{ level: "none", reason: "lightweight lookup" }`. An explicit tool-call value wins; chain and parallel acceptance remains configured on the task or step. Management create/update accepts the same policy object, and `acceptance: ""` clears the frontmatter default (`false` remains the deprecated disabled-policy shorthand).
|
|
698
|
+
|
|
699
|
+
`acceptanceRole` is `read-only` or `writer` and controls automatic acceptance inference only. Explicit task mutation or no-edit intent wins; otherwise the role replaces agent-name guessing. Omission preserves the current name heuristics. The field does not grant or revoke tools. Management accepts `false` or an empty string to clear it.
|
|
700
|
+
|
|
701
|
+
`tools` is a strict child allowlist, not an extension loader. For a named extension tool, keep its registered name in `tools` and load its provider through normal Pi discovery, `extensions`, a path-like `tools` entry, or `subagentOnlyExtensions`. For example, pair `tools: read, fixture_search` with `subagentOnlyExtensions: ./tools/fixture-search.ts` when the provider should exist only in that agent's child sessions. The child now fails with the unavailable names and provider-loading guidance instead of silently continuing when a requested tool is absent; internal `structured_output` is allowed automatically when an output schema requires it.
|
|
702
|
+
|
|
703
|
+
`skillPath` adds invocation-private skill files or discovery directories relative to the agent file; it does not select them, so list the desired names under `skills`. Local matches win, unresolved or unreadable matches use normal discovery, and local candidates never enter the parent/global catalog. Use `memory: { scope: "project" | "user", path: "<name>" }` for opt-in role-specific durable memory under the dedicated `agent-memory/` namespace; it is separate from parent/session project memory.
|
|
662
704
|
|
|
663
705
|
For many customizations, builtin overrides in settings are lower-friction than
|
|
664
706
|
copying a full builtin file.
|
|
@@ -682,7 +724,7 @@ Additional user prompt templates can delegate into `pi-subagents` through the na
|
|
|
682
724
|
|
|
683
725
|
Other Pi extensions can call `pi-subagents` through the in-process event bus. The stable v1 channels are `subagents:rpc:v1:ready`, `subagents:rpc:v1:request`, and per-request replies at `subagents:rpc:v1:reply:<requestId>`. Envelopes use `{ version: 1, requestId, method, params }`, and replies use `{ version: 1, requestId, success, data | error }`.
|
|
684
726
|
|
|
685
|
-
Methods: `ping`, `status`, `spawn`, `interrupt`, and `stop`. `spawn` is async-only and rejects management actions, `async: false`, or `clarify: true`; it reuses the normal executor, so discovery, validation, session attribution, spawn
|
|
727
|
+
Methods: `ping`, `status`, `spawn`, `interrupt`, and `stop`. `spawn` is async-only and rejects management actions, `async: false`, or `clarify: true`; it reuses the normal executor, so discovery, validation, session attribution, configured spawn caps, child-safety depth, artifacts, and async status are shared with the `subagent` tool. `status` and `interrupt` map to the normal control actions. `stop` targets running async runs through the existing timeout control channel. `pi.events` is process-local, so separate Pi processes and child subagents need lifecycle artifact files or `pi-intercom` instead.
|
|
686
728
|
|
|
687
729
|
## Important Constraints
|
|
688
730
|
|
|
@@ -700,22 +742,28 @@ Methods: `ping`, `status`, `spawn`, `interrupt`, and `stop`. `spawn` is async-on
|
|
|
700
742
|
- **Keep conversational authority clear.** Advisory subagents should not silently
|
|
701
743
|
become second decision-makers.
|
|
702
744
|
|
|
745
|
+
Runtime config can change orchestration behavior. `asyncByDefault` and `forceTopLevelAsync` affect whether launches detach; `waitTool` can make direct `subagent_wait()` calls return immediately while headless auto-drain remains active, and its effective value is propagated to child runtimes; `globalConcurrencyLimit` bounds concurrent fanout, while a positive `maxSubagentSpawnsPerSession` optionally caps cumulative launches (`0` or unset is unlimited). Status and doctor report the budget; static work preflights declared capacity; only the settled root interactive parent can use `grant-spawn-budget` after native confirmation, with total grants bounded by the original cap. Compaction does not reset usage or grants; `singleRunOutputBaseDir` and `worktreeBaseDir` route outputs and worktrees; `completionBatch` groups async notifications. Per-run `artifacts: false` disables artifact capture for that launch. Async status and result artifacts are versioned with fields such as `lifecycleArtifactVersion`, `workflowGraph`, `steps`, `results`, `totalTokens`, `totalCost`, `turnCount`, `toolCount`, and nested `children`. Child protocol failures expose a structured `protocolError`; `protocol_output_limit` means a child emitted a JSONL line above the 4 MiB live-parser cap. Prefer these artifacts and `status` views over scraping terminal output.
|
|
746
|
+
|
|
703
747
|
## Best Practices
|
|
704
748
|
|
|
705
749
|
### Prefer async orchestration
|
|
706
750
|
|
|
707
751
|
Launch every subagent asynchronously by default. Use `async: true` for scouts, researchers, workers, reviewers, validators, oracle checks, one-off delegates, chains, and parallel groups unless you intentionally need a foreground/blocking run. The parent should keep moving: inspect code while scouts run, prepare validation while a worker implements, do a local diff pass while reviewers review, and synthesize or verify while a fix worker applies accepted feedback. Async is the default orchestration posture; foreground runs are the explicit opt-out.
|
|
708
752
|
|
|
709
|
-
### Use
|
|
753
|
+
### Use subagent_wait() to block until async runs finish
|
|
754
|
+
|
|
755
|
+
In an interactive chat, do not call `subagent_wait()` merely to wait after launching background work; return control to the user and Pi will wake the session on completion. Override that default when the current request is run-to-completion — for example, the user asked you to stay with the task and report results back this turn or a skill must finish in one turn. In a headless run, Pi auto-drains exact current-session work at `agent_end`; call `subagent_wait()` when this turn must receive results before it ends. In either case, `subagent_wait()` blocks the current turn until the next run completes or needs attention, keeps the turn alive for normal notification delivery, then returns.
|
|
756
|
+
|
|
757
|
+
- `subagent_wait()` — return when the next initially active async run or registered provider item finishes, or a subagent needs attention.
|
|
758
|
+
- `subagent_wait({ all: true })` — block until every async run and provider item active at call time finishes, or a subagent needs attention.
|
|
759
|
+
- `subagent_wait({ id: "..." })` — block on one async or remembered detached foreground run (id or prefix). Provider items are not selected through this parameter.
|
|
760
|
+
- `subagent_wait({ timeoutMs })` — cap the block; active work keeps running if it elapses.
|
|
710
761
|
|
|
711
|
-
|
|
762
|
+
Providers are discovered through the versioned `pi-subagents/background-work` registry and must return stable item IDs with exact owning session IDs. Child agents receive no provider automatically: keep `subagent_wait` in the child `tools` allowlist and load provider extensions through `extensions` or `subagentOnlyExtensions`.
|
|
712
763
|
|
|
713
|
-
- `
|
|
714
|
-
- `wait({ all: true })` — block until every active async run in this session finishes or one needs attention.
|
|
715
|
-
- `wait({ id: "..." })` — block on one run (id or prefix).
|
|
716
|
-
- `wait({ timeoutMs })` — cap the block; the runs keep going if it elapses.
|
|
764
|
+
For non-interactive fleet orchestration, `subagent_wait()` can keep N workers in flight: launch N, wait for the next completion, react to the result, launch a replacement if needed, then wait again. Use `subagent_wait({ all: true })` only when you intentionally want to drain the fleet to zero. If the turn ends first, headless `agent_end` auto-drain still waits for exact current-session work. In an interactive session, return to the user instead of holding the turn open just to await completion.
|
|
717
765
|
|
|
718
|
-
|
|
766
|
+
If config or `PI_SUBAGENT_WAIT_TOOL_ENABLED` disables blocking behavior, direct `subagent_wait` calls return immediately. Headless `agent_end` auto-drain remains active as a lifecycle safeguard and surfaces provider, reconciliation, or timeout failures.
|
|
719
767
|
|
|
720
768
|
### Keep writes single-threaded by default
|
|
721
769
|
|
|
@@ -737,7 +785,7 @@ Give subagents specific tasks rather than vague mandates.
|
|
|
737
785
|
### Escalate decisions upward
|
|
738
786
|
|
|
739
787
|
If a subagent encounters an unapproved product, architecture, or scope choice,
|
|
740
|
-
it should
|
|
788
|
+
it should use `contact_supervisor` and wait for the reply instead of deciding alone. Generic `intercom` is a fallback only when the bridge-provided supervisor tool is unavailable.
|
|
741
789
|
|
|
742
790
|
### Intervene only on clear control signals
|
|
743
791
|
|
|
@@ -761,9 +809,23 @@ subagent({
|
|
|
761
809
|
})
|
|
762
810
|
```
|
|
763
811
|
|
|
812
|
+
### Fable mode for complex work
|
|
813
|
+
|
|
814
|
+
Fable mode is the default orchestration posture for complex work. It is not a separate runtime mode; it is how the parent session uses `subagent`, `interview`, `subagent_wait`, acceptance contracts, artifacts, and fresh-context review when the work has real complexity. Use it for complex features, broad refactors, migrations, ambiguous goals, multi-system changes, expensive validation, user-visible behavior changes, or any request to plan/orchestrate end to end. Do not force it onto tiny one-shot delegation.
|
|
815
|
+
|
|
816
|
+
Run the work through seven gated phases:
|
|
817
|
+
|
|
818
|
+
1. **Understand** — use `scout` or `context-builder` fanout for breadth, but the parent personally reads the load-bearing files and lets direct source reading decide disagreements. Gate: the parent can quote the exact code or behavior being changed and knows the repo's verification harness.
|
|
819
|
+
2. **Decide** — separate user-owned decisions from implementation judgments. Use `interview` for product, naming, cost, taste, or risk decisions; decide routine engineering details in the parent and state them. Gate: every user-owned decision needed for design is answered.
|
|
820
|
+
3. **Design** — use `planner`, `context-builder`, or read-only design/review children for parallel perspectives. Before parallel workstreams, write seam contracts: ownership boundaries, composition points, assumptions, and validation handoffs. Gate: one parent-synthesized plan and written seams for parallel work.
|
|
821
|
+
4. **Implement** — capture a baseline first, then launch one async `worker` as the sole writer for the active worktree unless isolated worktrees were intentionally requested. Break large work into serial milestones instead of concurrent writes. Gate: build/typecheck is green and every output or diff delta is characterized as intended or fixed.
|
|
822
|
+
5. **Verify** — climb the spend ladder: static checks, free end-to-end/dry-run, cheapest live probe, targeted changed-path live test, then full realistic run when warranted. Observe the artifact itself, not only exit codes or scores, and confirm the changed code actually executed. Gate: the highest necessary rung has directly observed evidence matching intent.
|
|
823
|
+
6. **Iterate** — when a gate or reviewer finds a defect, the parent names the failure class, searches for siblings, synthesizes fixes, and sends exactly one fix worker for accepted changes. For LLM judges, gates, or detectors, trigger on concrete findings rather than scores, record pass/violations/error verdicts, cache nondeterministic verdicts by input hash, budget enough output tokens, and sanitize judge text before reusing it downstream. Gate: the class is fixed or explicitly bounded, and recurrence detection exists when feasible.
|
|
824
|
+
7. **Ship** — run adversarial fresh-context review/validation outside the implementation path, disposition every finding, rerun affected gates, then have the parent inspect the final diff. Commit, push, release, or open PRs only inside user-approved boundaries. Gate: findings are dispositioned, gates re-pass, and the final summary names evidence, artifacts, residual risks, and output paths.
|
|
825
|
+
|
|
764
826
|
### Clarify → Plan → Implement → Review (self-orchestrated workflow)
|
|
765
827
|
|
|
766
|
-
|
|
828
|
+
For straightforward non-trivial work, this sequence is the lightweight version of the parent-owned loop. When the task is complex, use Fable mode above. In either case, factor in the packaged prompt workflows without literally invoking slash commands. Use the same patterns through tools and subagents.
|
|
767
829
|
|
|
768
830
|
Keep builtin agent defaults unless the user explicitly asks for a different model, thinking level, skills, output behavior, context mode, or other override. Do not add overrides just because you are orchestrating; the defaults encode the intended role behavior. In particular, packaged `planner`, `worker`, and `oracle` default to forked context.
|
|
769
831
|
|
|
@@ -785,7 +847,7 @@ clarify → validation contract → planner → async worker → parallel async
|
|
|
785
847
|
|
|
786
848
|
The validation contract defines acceptance before code is written: expected behavior, acceptance checks, commands or user flows to exercise, and evidence the worker should return. Keep it lightweight for small tasks, but make it explicit enough that reviewers and validators are checking the intended outcome rather than the worker’s own assumptions.
|
|
787
849
|
|
|
788
|
-
Use the structured `acceptance` field when the run should carry an explicit acceptance contract. If omitted, subagents infer an effective acceptance policy from role, mode, and risk. Use `level: "checked"` for ordinary writer evidence gates
|
|
850
|
+
Use the structured `acceptance` field when the run should carry an explicit acceptance contract. If omitted, subagents infer an effective acceptance policy from role, mode, and risk. Use `level: "checked"` for ordinary writer evidence gates and `level: "verified"` when the runtime should run explicit validation commands. Do not explicitly request `level: "reviewed"`: the current run cannot supply an independent reviewer result, so that level is reserved for inferred policy. Orchestrate a separate reviewer instead. To disable gates, use `{ level: "none", reason: "..." }`; the bare string `"none"` is rejected, and `false` is accepted only as a deprecated shorthand. Do not call a run reviewed just because the worker says it is done; reviewed means a reviewer gate returned a result. Child-reported command success is evidence, not runtime verification.
|
|
789
851
|
|
|
790
852
|
The first `worker` implements the approved plan. The parent continues with independent inspection or validation prep while it runs, not parallel edits to the same worktree. When the async worker completes, treat its handoff as the transition into review, not as final completion, unless the user explicitly asked for worker-only work, review-only output, or to stop after implementation. Parallel reviewers inspect the resulting diff from fresh context. Validators check behavior with the best available evidence: commands, tests, browser/CLI interaction, screenshots, logs, or manual reproduction notes. The final `worker` applies synthesized review fixes in forked context, then the parent looks over the final diff before completing. The parent may launch these steps as an initial async chain when the workflow is already clear, or as follow-up subagent runs after each async completion. Initial chains should pass `async: true` so the main chat is unblocked; avoid `clarify: true` unless the user asked for foreground clarification. Do not stop after parallel review unless the user explicitly asked for review-only output or the review surfaced a decision that needs approval first.
|
|
791
853
|
|