pi-subagents 0.31.1 → 0.33.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 +67 -4
- package/README.md +219 -40
- package/install.mjs +2 -1
- package/package.json +3 -2
- package/skills/pi-subagents/SKILL.md +71 -10
- package/src/agents/agent-management.ts +179 -2
- package/src/agents/agent-memory.ts +254 -0
- package/src/agents/agent-serializer.ts +11 -0
- package/src/agents/agents.ts +193 -19
- package/src/agents/chain-serializer.ts +27 -2
- package/src/extension/config.ts +27 -4
- package/src/extension/doctor.ts +1 -7
- package/src/extension/fanout-child.ts +3 -2
- package/src/extension/index.ts +70 -41
- package/src/extension/rpc.ts +369 -0
- package/src/extension/schemas.ts +54 -10
- package/src/extension/tool-description.ts +200 -0
- package/src/intercom/intercom-bridge.ts +21 -253
- package/src/intercom/native-supervisor-channel.ts +510 -0
- package/src/runs/background/async-execution.ts +187 -38
- package/src/runs/background/async-job-tracker.ts +88 -2
- package/src/runs/background/async-status.ts +67 -10
- package/src/runs/background/chain-root-attachment.ts +34 -4
- package/src/runs/background/completion-batcher.ts +166 -0
- package/src/runs/background/control-channel.ts +156 -1
- package/src/runs/background/fleet-view.ts +515 -0
- package/src/runs/background/notify.ts +161 -44
- package/src/runs/background/result-watcher.ts +1 -2
- package/src/runs/background/run-id-resolver.ts +3 -2
- package/src/runs/background/run-status.ts +167 -6
- package/src/runs/background/scheduled-runs.ts +514 -0
- package/src/runs/background/stale-run-reconciler.ts +28 -1
- package/src/runs/background/subagent-runner.ts +840 -127
- package/src/runs/background/wait.ts +353 -0
- package/src/runs/foreground/chain-execution.ts +123 -27
- package/src/runs/foreground/execution.ts +174 -27
- package/src/runs/foreground/subagent-executor.ts +569 -81
- package/src/runs/shared/acceptance.ts +45 -22
- package/src/runs/shared/dynamic-fanout.ts +2 -2
- package/src/runs/shared/model-fallback.ts +171 -20
- package/src/runs/shared/model-scope.ts +128 -0
- package/src/runs/shared/nested-events.ts +89 -0
- package/src/runs/shared/parallel-utils.ts +50 -1
- package/src/runs/shared/pi-args.ts +35 -4
- package/src/runs/shared/pi-spawn.ts +52 -20
- package/src/runs/shared/single-output.ts +2 -0
- package/src/runs/shared/subagent-prompt-runtime.ts +110 -4
- package/src/runs/shared/tool-budget.ts +74 -0
- package/src/runs/shared/turn-budget.ts +52 -0
- package/src/runs/shared/worktree.ts +28 -5
- package/src/shared/artifacts.ts +16 -1
- package/src/shared/atomic-json.ts +15 -2
- package/src/shared/child-transcript.ts +212 -0
- package/src/shared/fork-context.ts +133 -22
- package/src/shared/settings.ts +3 -1
- package/src/shared/types.ts +197 -4
- package/src/shared/utils.ts +99 -14
- package/src/slash/prompt-workflows.ts +330 -0
- package/src/slash/slash-commands.ts +133 -2
- package/src/tui/render.ts +32 -12
package/README.md
CHANGED
|
@@ -95,7 +95,7 @@ Those are ordinary Pi requests. Pi decides whether to call `subagent`, which age
|
|
|
95
95
|
| Run in the background | “Run this in the background.” |
|
|
96
96
|
| Browse agents | “Show me the available subagents.” |
|
|
97
97
|
| Use a saved workflow | “Run the review chain on this branch.” |
|
|
98
|
-
| See running work | “Show active async runs.” |
|
|
98
|
+
| See running work | “Show active async runs.” or “Show the subagent fleet.” |
|
|
99
99
|
| Check setup | “Check whether subagents are configured correctly.” |
|
|
100
100
|
|
|
101
101
|
The extension ships with builtin agents you can use immediately.
|
|
@@ -117,7 +117,21 @@ A simple rule of thumb: use `scout` before you understand the code, `researcher`
|
|
|
117
117
|
|
|
118
118
|
## Changing an agent's model
|
|
119
119
|
|
|
120
|
-
Builtin agents inherit your current Pi default model by default. This keeps new installs from depending on a provider you may not have configured. If you want a role to use a specific model, set an override instead of copying the bundled agent file.
|
|
120
|
+
Builtin agents inherit your current Pi default model by default. This keeps new installs from depending on a provider you may not have configured. If you want every subagent without its own model to use a different default, set `subagents.defaultModel`. If you want a role to use a specific model, set an override instead of copying the bundled agent file.
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"defaultModel": "deepseek-v4-pro",
|
|
125
|
+
"subagents": {
|
|
126
|
+
"defaultModel": "deepseek-v4-flash",
|
|
127
|
+
"agentOverrides": {
|
|
128
|
+
"oracle": {
|
|
129
|
+
"model": "deepseek-v4-pro"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
121
135
|
|
|
122
136
|
For one run, put the override in the command:
|
|
123
137
|
|
|
@@ -141,7 +155,7 @@ For a persistent override, edit settings. This example pins the reviewer everywh
|
|
|
141
155
|
}
|
|
142
156
|
```
|
|
143
157
|
|
|
144
|
-
Use `~/.pi/agent/settings.json` for a user override or the project config settings file (`.pi/settings.json` in standard Pi) for a project override. The same `agentOverrides` block can change `tools`, `skills`, inherited context, prompt text, or disable a builtin. Matching user and project agents also receive override fields that their frontmatter leaves unset, so a shared project config agent can keep the persona while local settings choose the model.
|
|
158
|
+
Use `~/.pi/agent/settings.json` for a user override or the project config settings file (`.pi/settings.json` in standard Pi) for a project override. `subagents.defaultModel` applies to builtin, package, user, and project agents that do not set `model` in frontmatter. Per-run model overrides and `agentOverrides.<name>.model` still win, and explicit agent frontmatter still wins over the global default. The same `agentOverrides` block can change `tools`, `skills`, inherited context, prompt text, or disable a builtin. Matching user and project agents also receive override fields that their frontmatter leaves unset, so a shared project config agent can keep the persona while local settings choose the model.
|
|
145
159
|
|
|
146
160
|
If your provider rejects model IDs with thinking suffixes, set `subagents.disableThinking: true` in user or project settings. That clears bundled builtin thinking defaults in one place; an explicit higher-precedence `agentOverrides.<name>.thinking` value can opt a role back in.
|
|
147
161
|
|
|
@@ -154,11 +168,28 @@ To inspect what `pi-subagents` has actually loaded right now, use:
|
|
|
154
168
|
|
|
155
169
|
That reports the live runtime mapping, which can differ from settings on disk until you reload Pi.
|
|
156
170
|
|
|
171
|
+
You do not have to spell a model exactly. Model ids are matched fuzzily against the registry, so provider separator variations (`anthropic/claude-sonnet-4`, `anthropic:claude-sonnet-4`, or `anthropic.claude-sonnet-4`), id separator variations (`claude-haiku-4.5` vs `claude-haiku-4-5`), case differences (`Claude-Sonnet-4` vs `claude-sonnet-4`), and optional trailing date stamps (`claude-haiku-4-5-20251001` or `claude-haiku-4-5-2025-10-01` vs `claude-haiku-4-5`) all resolve to the same model. Exact `provider/id` matches still win, and a qualified provider query never silently switches providers — it only matches within the named provider. Ambiguous bare ids that exist under multiple providers still require a provider prefix or the current session's provider to disambiguate.
|
|
172
|
+
|
|
173
|
+
To keep subagents inside a budget or compliance profile, enforce a model scope. Put `subagents.modelScope` in user or project settings (project overrides user):
|
|
174
|
+
|
|
175
|
+
```json
|
|
176
|
+
{
|
|
177
|
+
"subagents": {
|
|
178
|
+
"modelScope": {
|
|
179
|
+
"enforce": true,
|
|
180
|
+
"allow": ["anthropic/*", "openai/gpt-5-*"]
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
`allow` is a list of glob patterns matched against the resolved `provider/id` (only `*` is special, case-insensitive). A resolved model that matches none of the patterns is rejected. Models you pass explicitly — the tool-call `model`, `--model`, or a clarify pick — error and abort the run. Models that come from agent frontmatter, `subagents.defaultModel`, or the inherited parent session model only warn, so existing configurations keep working while you tighten the scope. `enforce: true` requires a non-empty `allow` list; otherwise the config is rejected at load time.
|
|
187
|
+
|
|
157
188
|
## Where running subagents show up
|
|
158
189
|
|
|
159
190
|
Foreground runs stream progress in the conversation while they run.
|
|
160
191
|
|
|
161
|
-
Background runs keep working after control returns to you. Inspect active runs with `subagent({ action: "status" })`, or a specific run with `subagent({ action: "status", id: "..." })`.
|
|
192
|
+
Background runs keep working after control returns to you. Inspect active runs with `subagent({ action: "status" })`, or a specific run with `subagent({ action: "status", id: "..." })`. For a read-only fleet view across active foreground and background work, use `/subagents-fleet` or `subagent({ action: "status", view: "fleet" })`. To inspect what a background child is saying without hunting through artifact directories, tail its live transcript with `subagent({ action: "status", id: "...", view: "transcript" })`; add `index` for a specific child in a parallel or chain run.
|
|
162
193
|
|
|
163
194
|
They also show a compact async widget and send completion notifications. Parallel background runs show per-agent progress instead of fake chain steps. 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.
|
|
164
195
|
|
|
@@ -168,6 +199,30 @@ You can also ask naturally:
|
|
|
168
199
|
Show me the current async runs.
|
|
169
200
|
```
|
|
170
201
|
|
|
202
|
+
Async runs also write machine-readable lifecycle artifacts for observability and workflow gates. For a top-level async run, `details.asyncDir` points at a directory containing `status.json`, `events.jsonl`, `output-<index>.log`, and `subagent-log-<runId>.md`; the final summary is written to Pi's subagent results directory as `<runId>.json`. Nested async runs use the same shape under the nested async root and are discoverable through status projections that read the nested-run registry. These files are append/update artifacts only; interactive foreground behavior is unchanged.
|
|
203
|
+
|
|
204
|
+
The stable v1 status/result fields are `lifecycleArtifactVersion`, `runId`/`id`, `sessionId`, `mode`, `state`, `startedAt`, `lastUpdate`, `endedAt`, `durationMs`, `cwd`, `asyncDir`, `sessionFile`, `outputFile`, `workflowGraph`, `steps`, `results`, `totalTokens`, `totalCost`, `model`/`attemptedModels`/`modelAttempts`, `toolCount`, `turnCount`, and nested `children` when a child is allowed to launch subagents. `events.jsonl` records lifecycle transitions such as `subagent.run.started`, `subagent.step.started`, `subagent.step.completed`/`failed`/`paused`, control attention events, nested interrupt failures, and `subagent.run.completed`; run boundary events include the lifecycle artifact version. Consumers should read these JSON files instead of scraping terminal output; unknown fields and event types should be ignored for forward compatibility.
|
|
205
|
+
|
|
206
|
+
Other Pi extensions can use the versioned in-process event-bus RPC instead of scraping slash output or calling internal modules. Listen for `subagents:rpc:v1:ready`, send requests on `subagents:rpc:v1:request`, and read replies from `subagents:rpc:v1:reply:<requestId>`.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
const requestId = crypto.randomUUID();
|
|
210
|
+
pi.events.on(`subagents:rpc:v1:reply:${requestId}`, (reply) => {
|
|
211
|
+
// { version: 1, requestId, success: true, data } or
|
|
212
|
+
// { version: 1, requestId, success: false, error: { code, message } }
|
|
213
|
+
});
|
|
214
|
+
pi.events.emit("subagents:rpc:v1:request", {
|
|
215
|
+
version: 1,
|
|
216
|
+
requestId,
|
|
217
|
+
method: "spawn",
|
|
218
|
+
params: { agent: "reviewer", task: "Review the current diff", context: "fresh" }
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
The v1 methods are `ping`, `status`, `spawn`, `interrupt`, and `stop`. `status` and `interrupt` reuse the normal control actions. `spawn` is async-only: omit `async` or set `async: true`, omit `clarify` or set `clarify: false`, and do not pass management `action` values. It goes through the same executor as the `subagent` tool, so agent discovery, validation, session attribution, spawn limits, child-safety depth, artifacts, and async status all behave the same. `stop` targets running async runs through the existing timeout control channel.
|
|
223
|
+
|
|
224
|
+
`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.
|
|
225
|
+
|
|
171
226
|
If something feels misconfigured, run:
|
|
172
227
|
|
|
173
228
|
```text
|
|
@@ -210,15 +265,9 @@ The package includes reusable prompt templates for common workflows. You do not
|
|
|
210
265
|
|
|
211
266
|
Add `autofix` to `/parallel-review` or `/parallel-cleanup` to apply only the synthesized fixes worth doing now after reviewers return.
|
|
212
267
|
|
|
213
|
-
##
|
|
214
|
-
|
|
215
|
-
`pi-subagents` works without `pi-intercom`. Install `pi-intercom` only if you want child agents to talk back to the parent Pi session while they are running.
|
|
216
|
-
|
|
217
|
-
```bash
|
|
218
|
-
pi install npm:pi-intercom
|
|
219
|
-
```
|
|
268
|
+
## Native supervisor coordination
|
|
220
269
|
|
|
221
|
-
|
|
270
|
+
Child agents can talk back to the parent Pi session without installing `pi-intercom`. `pi-subagents` now provides the child-facing `contact_supervisor` tool and the parent-facing `intercom({ action: "reply" })` path natively.
|
|
222
271
|
|
|
223
272
|
Use it for work where the child might need a decision instead of guessing:
|
|
224
273
|
|
|
@@ -232,11 +281,11 @@ Ask oracle to review this plan. If it sees a decision I need to make, have it as
|
|
|
232
281
|
|
|
233
282
|
The child can use one dedicated coordination tool:
|
|
234
283
|
|
|
235
|
-
- `contact_supervisor`: the child contacts the parent/supervisor session that delegated the task. Use `reason: "need_decision"` for blocking decisions or clarification, and `reason: "progress_update"` for short non-blocking updates when a discovery changes the plan. Do not ask for clarification when the only conflict is review-only/no-edit versus progress-writing or artifact-writing instructions; no-edit wins.
|
|
284
|
+
- `contact_supervisor`: the child contacts the parent/supervisor session that delegated the task. Use `reason: "need_decision"` for blocking decisions or clarification, `reason: "interview_request"` for structured input, and `reason: "progress_update"` for short non-blocking updates when a discovery changes the plan. Do not ask for clarification when the only conflict is review-only/no-edit versus progress-writing or artifact-writing instructions; no-edit wins.
|
|
236
285
|
|
|
237
|
-
|
|
286
|
+
Supervisor messages are scoped to the exact Pi session id that spawned the child. A second Pi session in the same repository does not receive those requests.
|
|
238
287
|
|
|
239
|
-
If a child appears stalled, needs-attention notices can show up in the parent session with useful next actions, such as checking `subagent({ action: "status" })`, interrupting the run, or nudging the child.
|
|
288
|
+
Child-side routine completion handoffs are still not expected. If a child appears stalled, needs-attention notices can show up in the parent session with useful next actions, such as checking `subagent({ action: "status" })`, interrupting the run, or nudging the child.
|
|
240
289
|
|
|
241
290
|
If messages do not show up, run:
|
|
242
291
|
|
|
@@ -332,6 +381,7 @@ Skip this section until you want exact syntax.
|
|
|
332
381
|
| `/chain scout "scan" -> (reviewer "A" \| reviewer "B") -> writer "fix"` | Run a chain with a static parallel group inline |
|
|
333
382
|
| `/parallel agent1 "task1" -> agent2 "task2"` | Run agents in parallel |
|
|
334
383
|
| `/run-chain <chainName> -- <task>` | Launch a saved `.chain.md` or `.chain.json` workflow |
|
|
384
|
+
| `/subagent-cost` | Show parent plus child subagent token usage and cost for this session |
|
|
335
385
|
| `/subagents-doctor` | Show read-only setup diagnostics |
|
|
336
386
|
| `/subagents-models [agent]` | Show the runtime-loaded builtin model mapping, optionally filtered to one builtin |
|
|
337
387
|
| `/subagents-profiles` | List saved subagent profiles from `~/.pi/agent/profiles/pi-subagents/` |
|
|
@@ -440,7 +490,7 @@ Append `[key=value,...]` to an agent name to override defaults. `/chain` applies
|
|
|
440
490
|
|
|
441
491
|
| Key | Example | Description |
|
|
442
492
|
|-----|---------|-------------|
|
|
443
|
-
| `output` | `output=context.md` | Write results to a file.
|
|
493
|
+
| `output` | `output=context.md` | Write results to a file. Absolute paths are used as-is. Relative paths in `/run` resolve under `singleRunOutputBaseDir` when configured, otherwise under the run's output artifact directory. Relative paths in `/chain` and `/parallel` live under the chain or parallel run directory. |
|
|
444
494
|
| `outputMode` | `outputMode=file-only` | Return only a concise file reference for saved output instead of the full saved content. Requires `output`; default is `inline`. |
|
|
445
495
|
| `reads` | `reads=a.md+b.md` | Read files before executing. `+` separates multiple paths. |
|
|
446
496
|
| `model` | `model=anthropic/claude-sonnet-4` | Override model for this step. |
|
|
@@ -483,13 +533,15 @@ You can combine them in either order:
|
|
|
483
533
|
/run reviewer "review this diff" --bg --fork
|
|
484
534
|
```
|
|
485
535
|
|
|
486
|
-
Background runs are detached. If the parent agent has other independent work, it should keep working.
|
|
536
|
+
Background runs are detached. If the parent agent has other independent work, it should keep working. When it has nothing useful to do until a background result arrives, it should call the `wait` tool instead of running sleep or status-polling loops. `wait()` returns when the next active run finishes or needs attention and keeps the turn alive for normal notification delivery; use `wait({ all: true })` to drain every active run, `wait({ id })` for one run, and `wait({ timeoutMs })` to cap the block.
|
|
537
|
+
|
|
538
|
+
`wait` is what lets a background-launching skill keep moving in a single turn, including non-interactive `pi -p` invocations where there is no subsequent turn to receive a completion notification. Ending the turn to wait for a completion only works in an interactive session where the user will prompt the agent again; in a run-to-completion skill or a non-interactive run, use `wait` so the still-running children are not abandoned.
|
|
487
539
|
|
|
488
540
|
The `oracle` and `worker` builtins are designed for an explicit decision loop. A typical pattern is to ask `oracle` for diagnosis and a recommended execution prompt, then only run `worker` after the main agent approves that direction.
|
|
489
541
|
|
|
490
542
|
## Clarify and launch UI
|
|
491
543
|
|
|
492
|
-
|
|
544
|
+
Tool calls launch directly by default. Set `clarify: true` on single, parallel, or chain runs when you want to preview and edit the workflow before it runs; slash commands launch directly.
|
|
493
545
|
|
|
494
546
|
Common clarify keys:
|
|
495
547
|
|
|
@@ -521,7 +573,7 @@ Agent locations, lowest to highest priority:
|
|
|
521
573
|
|
|
522
574
|
Project discovery also reads legacy `.agents/**/*.md` files. Nested subdirectories are discovered recursively. `.chain.md` files do not define agents. Installed Pi packages can expose agent directories from either `{"pi-subagents":{"agents":["./agents"]}}` or `{"pi":{"subagents":{"agents":["./agents"]}}}` in their package manifest. Package agents load above builtins and below user/project agents. If both `.agents/` and the project config agents directory define the same parsed runtime agent name, the project config directory wins. Use `agentScope: "user" | "project" | "both"` to control discovery; `both` is the default and project definitions win runtime-name collisions.
|
|
523
575
|
|
|
524
|
-
Builtin agents load at the lowest priority, so a user or project agent with the same name overrides them. They do not pin a provider model; they inherit your current Pi default model unless you set `subagents.agentOverrides.<name>.model`. `oracle` is an advisory reviewer that critiques direction and proposes an execution prompt without editing files. `worker` is the implementation agent for normal tasks and approved oracle handoffs.
|
|
576
|
+
Builtin agents load at the lowest priority, so a user or project agent with the same name overrides them. They do not pin a provider model; they inherit your current Pi default model unless you set `subagents.defaultModel` or `subagents.agentOverrides.<name>.model`. `oracle` is an advisory reviewer that critiques direction and proposes an execution prompt without editing files. `worker` is the implementation agent for normal tasks and approved oracle handoffs.
|
|
525
577
|
|
|
526
578
|
The `researcher` builtin uses `web_search`, `fetch_content`, and `get_search_content`; those require [pi-web-access](https://github.com/nicobailon/pi-web-access):
|
|
527
579
|
|
|
@@ -552,7 +604,9 @@ Example:
|
|
|
552
604
|
|
|
553
605
|
Supported override fields are `model`, `fallbackModels`, `thinking`, `systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `defaultContext`, `disabled`, `skills`, `tools`, and `systemPrompt`. Use `defaultContext: false` in builtin overrides to clear an inherited context default. Project overrides beat user overrides.
|
|
554
606
|
|
|
555
|
-
Set `
|
|
607
|
+
Set `subagents.defaultModel` to give all subagents without an explicit model their own default model, separate from the parent session model. Per-agent model overrides and agent frontmatter still win.
|
|
608
|
+
|
|
609
|
+
Set `disabled: true` to hide a builtin from runtime discovery and agent-facing `subagent({ action: "list" })` output. For bulk control, set `subagents.disableBuiltins: true` in settings. You can also toggle a single agent without editing settings by hand: `subagent({ action: "disable", agent: "reviewer" })` writes that override, and `subagent({ action: "enable", agent: "reviewer" })` removes it.
|
|
556
610
|
|
|
557
611
|
Set `subagents.disableThinking: true` to clear bundled builtin thinking defaults globally for providers that do not support `:low`, `:medium`, `:high`, or similar model suffixes. A higher-precedence per-agent `thinking` override can opt one builtin back in.
|
|
558
612
|
|
|
@@ -623,7 +677,22 @@ Important fields:
|
|
|
623
677
|
| `defaultProgress` | Maintain `progress.md`. |
|
|
624
678
|
| `completionGuard` | Set `false` only for non-implementation agents that may mention implementation words while using mutation-capable tools such as `bash`. |
|
|
625
679
|
| `interactive` | Parsed for compatibility but not enforced in v1. |
|
|
626
|
-
| `maxSubagentDepth` | Tightens nested delegation for this agent
|
|
680
|
+
| `maxSubagentDepth` | Tightens nested delegation for this agent's children. |
|
|
681
|
+
| `memory` | Opt-in role-specific persistent memory. `memory: { scope: "project" \| "user", path: "<name>" }` injects the first lines of a `MEMORY.md` from a dedicated `agent-memory/` directory into the child system prompt. Agents with write tools (`edit`/`write`/`bash`) get a read-write block; read-only agents get a read-only fallback. Project scope resolves under `<project>/.pi/agent-memory/`, user scope under `~/.pi/agent/agent-memory/`. Paths are validated against traversal and symlink escape. |
|
|
682
|
+
|
|
683
|
+
### Per-agent persistent memory
|
|
684
|
+
|
|
685
|
+
A recurring custom agent can opt into a durable, role-specific memory scope with the `memory` frontmatter field. This is independent of Pi's own parent/session/project memory system and writes nothing to it; memory lives under a dedicated `agent-memory/` namespace so the two never collide.
|
|
686
|
+
|
|
687
|
+
```yaml
|
|
688
|
+
memory:
|
|
689
|
+
scope: project
|
|
690
|
+
path: security-reviewer
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
On each run, the first 200 lines of `MEMORY.md` in the resolved memory directory are injected into the child system prompt so the agent can recall accumulated role notes such as threat-model entries, release gotchas, or verified commands. Agents that have write tools (`edit`, `write`, or `bash`, or no `tools` allowlist at all) are told they may append concise dated entries to the file. Agents without write tools receive a read-only memory block and are not instructed to edit it, so a read-only reviewer can still recall prior notes without being granted write capability. The memory directory is never created eagerly; the agent's own `write` tool creates it (and `MEMORY.md`) on the first persist. Memory paths are validated against `.`/`..` traversal and symlink escape, and an unsafe or unresolvable scope is silently skipped rather than breaking the run.
|
|
694
|
+
|
|
695
|
+
Project-scoped memory resolves under `<project>/.pi/agent-memory/<path>` and travels with the repo. User-scoped memory resolves under `~/.pi/agent/agent-memory/<path>` and is shared across projects for that agent.
|
|
627
696
|
|
|
628
697
|
### Tool and extension selection
|
|
629
698
|
|
|
@@ -815,7 +884,7 @@ What the bundled skill covers:
|
|
|
815
884
|
- **Prompt workflow recipes**: how to apply the packaged techniques directly with `subagent(...)` when the user describes the workflow in natural language instead of invoking a slash command. This includes parallel review, review-loop, parallel research, parallel context-build, parallel handoff-plan, gather-context-and-clarify, and parallel cleanup
|
|
816
885
|
- **Role-agent prompting guidance**: compact contract prompts instead of long scripts, what to include in role-specific meta prompts, and retrieval budgets for researchers
|
|
817
886
|
- **Safety boundaries**: child agents must not run subagents unless their resolved builtin tools explicitly include `subagent`, must not invent intercom targets, and must escalate unapproved decisions
|
|
818
|
-
- **Intercom conventions**: when to ask vs send, and how parent-side result delivery works
|
|
887
|
+
- **Intercom conventions**: when to ask vs send, and how parent-side supervisor/result delivery works through the native channel
|
|
819
888
|
- **Control and diagnostics**: attention signals, soft interrupts, status, and the `doctor` action
|
|
820
889
|
|
|
821
890
|
If you are writing an agent that orchestrates subagents, the bundled skill helps it behave correctly without guessing the patterns. If you are a human user, you do not need to read it directly; the README and prompt shortcuts encode the same workflows in user-facing form.
|
|
@@ -951,32 +1020,45 @@ Agent definitions are not loaded into context by default. Management actions let
|
|
|
951
1020
|
{ action: "update", chainName: "review-pipeline", config: { steps: [...] } }
|
|
952
1021
|
{ action: "delete", agent: "scout" }
|
|
953
1022
|
{ action: "delete", chainName: "review-pipeline" }
|
|
1023
|
+
|
|
1024
|
+
{ action: "eject", agent: "reviewer" }
|
|
1025
|
+
{ action: "eject", agent: "reviewer", agentScope: "project" }
|
|
1026
|
+
{ action: "disable", agent: "reviewer" }
|
|
1027
|
+
{ action: "enable", agent: "reviewer", agentScope: "project" }
|
|
1028
|
+
{ action: "reset", agent: "reviewer" }
|
|
954
1029
|
```
|
|
955
1030
|
|
|
956
1031
|
`create` uses `config.scope`, not `agentScope`. `config.name` is the local frontmatter name; optional `config.package` registers the runtime name as `{package}.{name}` and is saved as separate `name` and `package` frontmatter. `update` and `delete` use the runtime name and `agentScope` only when the same runtime name exists in multiple scopes. To clear optional string fields, including `package`, set them to `false` or `""`.
|
|
957
1032
|
|
|
1033
|
+
`eject` copies a bundled builtin or package agent verbatim into the user or project agent dir (default `user`) as an editable custom file that shadows the original, so you can customize a builtin without hunting package files. `disable` writes a reversible `agentOverrides.<name>.disabled: true` entry to the user or project settings file (default `user`); the agent stays on disk but is hidden from runtime discovery and `list`. `enable` removes that `disabled` field while preserving any other override fields on the same entry. `reset` deletes the scope's custom agent file and/or settings override entry, restoring the bundled default; it refuses if no bundled default exists (use `delete` for purely custom agents). All four accept `agentScope: "user" | "project"` and operate in one scope at a time; project overrides still win over user ones, so a project-scope disable survives a user-scope `enable` until you target the project scope.
|
|
1034
|
+
|
|
958
1035
|
### Parameter reference
|
|
959
1036
|
|
|
960
1037
|
| Param | Type | Default | Description |
|
|
961
1038
|
|-------|------|---------|-------------|
|
|
962
1039
|
| `agent` | string | - | Agent name for single mode, or target for management actions. |
|
|
963
1040
|
| `task` | string | - | Task string for single mode. |
|
|
964
|
-
| `action` | string | - | `list`, `get`, `create`, `update`, `delete`, `status`, `interrupt`, `resume`, `append-step`, or `doctor`. |
|
|
1041
|
+
| `action` | string | - | `list`, `get`, `create`, `update`, `delete`, `status`, `interrupt`, `resume`, `steer`, `append-step`, or `doctor`. |
|
|
965
1042
|
| `chainName` | string | - | Chain name for management actions. |
|
|
966
1043
|
| `config` | object/string | - | Agent or chain config for create/update. |
|
|
967
1044
|
| `output` | `string \| false` | agent default | Override single-agent output file. |
|
|
968
1045
|
| `outputMode` | `"inline" \| "file-only"` | `inline` | Return saved output inline or as a concise saved-file reference. `file-only` requires an `output` path. |
|
|
969
1046
|
| `skill` | `string \| string[] \| false` | agent default | Override skills or disable all. |
|
|
970
1047
|
| `model` | string | agent default | Override model. |
|
|
971
|
-
| `tasks` | array | - | Top-level parallel tasks. Supports `agent`, `task`, `cwd`, `count`, `output`, `outputMode`, `reads`, `progress`, `skill`, `model`, and `acceptance`. |
|
|
1048
|
+
| `tasks` | array | - | Top-level parallel tasks. Supports `agent`, `task`, `cwd`, `count`, `output`, `outputMode`, `reads`, `progress`, `skill`, `model`, `toolBudget`, and `acceptance`. |
|
|
972
1049
|
| `concurrency` | number | config or `4` | Top-level parallel concurrency. |
|
|
973
1050
|
| `worktree` | boolean | false | Create isolated git worktrees for parallel tasks. |
|
|
974
1051
|
| `chain` | array | - | Sequential, static parallel, and dynamic fanout chain steps. Steps and chain parallel tasks support `phase`, `label`, `as`, `outputSchema`, and `acceptance` in addition to the usual execution fields. Dynamic fanout uses `expand`, one child `parallel` template, and `collect`. With `action: "append-step"`, pass exactly one step to append to a running async chain. |
|
|
975
1052
|
| `context` | `fresh \| fork` | per-agent default or `fresh` | Explicit `fresh` or `fork` overrides every child. When omitted, each agent uses its own `defaultContext`; `fork` creates real branched sessions from the parent leaf. Packaged `planner`, `worker`, and `oracle` default to `fork`. |
|
|
976
1053
|
| `chainDir` | string | temp chain dir | Persistent directory for chain artifacts. |
|
|
977
|
-
| `
|
|
1054
|
+
| `view` | `fleet \| transcript` | - | Optional `status` view for the active fleet surface or transcript tail inspection. |
|
|
1055
|
+
| `lines` | number | `80` | Maximum transcript lines for `action: "status", view: "transcript"`; capped at 500. |
|
|
1056
|
+
| `clarify` | boolean | false | Show TUI preview/edit flow. Explicit `clarify: true` keeps the run foreground for the clarify UI. |
|
|
978
1057
|
| `agentScope` | `user \| project \| both` | `both` | Agent discovery scope. Project wins on collisions. |
|
|
979
1058
|
| `async` | boolean | false | Background execution. For chains, `clarify: true` explicitly keeps the run foreground for the clarify UI. |
|
|
1059
|
+
| `timeoutMs` / `maxRuntimeMs` | number | none | Optional run-level max runtime in milliseconds for foreground and async/background runs. |
|
|
1060
|
+
| `turnBudget` | object | none | Optional assistant-turn budget `{ maxTurns, graceTurns }`. At `maxTurns` the child is warned to wrap up; after `graceTurns` (default 1) more assistant turns the run is aborted and partial output is returned. |
|
|
1061
|
+
| `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`, or use `"*"` to block every tool call. Final assistant text is never blocked. |
|
|
980
1062
|
| `cwd` | string | runtime cwd | Override working directory. |
|
|
981
1063
|
| `maxOutput` | object | 200KB, 5000 lines | Final output truncation limits. |
|
|
982
1064
|
| `artifacts` | boolean | true | Write debug artifacts. |
|
|
@@ -985,31 +1067,37 @@ Agent definitions are not loaded into context by default. Management actions let
|
|
|
985
1067
|
| `sessionDir` | string | derived | Override session log directory. |
|
|
986
1068
|
| `acceptance` | string/object/false | inferred | Override the run's inferred acceptance gates. Use `"auto"`, `"attested"`, `"checked"`, `"verified"`, `"reviewed"`, or `{ level: "none", reason: "..." }`. |
|
|
987
1069
|
|
|
988
|
-
`context: "fork"` fails fast when the parent session is not persisted, the current leaf is missing, or the branched child session cannot be created.
|
|
1070
|
+
`context: "fork"` fails fast when the parent session is not persisted, the current leaf is missing, or the branched child session cannot be created. When the inherited transcript contains signed Anthropic `thinking` / `redacted_thinking` blocks, `pi-subagents` strips those provider-private blocks from the forked child session and forces the child run's thinking level to `off` so Anthropic does not reject modified signatures after branching or compaction. Forking never silently downgrades to `fresh`. In multi-agent runs that omit `context`, each agent/task/step follows its own `defaultContext`, so a fresh-default scout can run fresh beside a fork-default worker. Pass explicit `context: "fork"` or `context: "fresh"` when you intentionally want one context for every child.
|
|
989
1071
|
|
|
990
1072
|
Use `outputMode: "file-only"` when a saved output may be large and the parent only needs a pointer. The returned text is a compact reference like `Output saved to: /abs/report.md (48.2 KB, 2847 lines). Read this file if needed.` Failed runs and save errors still return normal inline output for debugging. In chains, later `{previous}` steps receive the same compact reference when the prior step used file-only mode.
|
|
991
1073
|
|
|
992
|
-
Sequential and parallel chain tasks accept `agent`, `task`, `phase`, `label`, `as`, `outputSchema`, `cwd`, `output`, `outputMode`, `reads`, `progress`, `skill`, and `
|
|
1074
|
+
Sequential and parallel chain tasks accept `agent`, `task`, `phase`, `label`, `as`, `outputSchema`, `cwd`, `output`, `outputMode`, `reads`, `progress`, `skill`, `model`, and `toolBudget`. Parallel tasks also accept `count`. Parallel step groups accept `parallel`, `concurrency`, `failFast`, and `worktree`. If `outputSchema` is present, the child must call `structured_output` with schema-valid JSON; prose-only completion or invalid JSON fails the step. Validated structured values are preserved on the step result, and `as` also exposes a compact text representation through `{outputs.name}`.
|
|
993
1075
|
|
|
994
1076
|
Status and control actions:
|
|
995
1077
|
|
|
996
1078
|
```ts
|
|
997
1079
|
subagent({ action: "status" })
|
|
1080
|
+
subagent({ action: "status", view: "fleet" })
|
|
998
1081
|
subagent({ action: "status", id: "<run-id>" })
|
|
1082
|
+
subagent({ action: "status", id: "<run-id>", view: "transcript", index: 0, lines: 80 })
|
|
999
1083
|
subagent({ action: "status", id: "<nested-run-id>" })
|
|
1000
1084
|
subagent({ action: "interrupt", id: "<run-id>" })
|
|
1001
1085
|
subagent({ action: "interrupt", id: "<nested-run-id>" })
|
|
1002
1086
|
subagent({ action: "resume", id: "<run-id>", message: "follow-up question" })
|
|
1003
1087
|
subagent({ action: "resume", id: "<run-id>", index: 1, message: "follow-up for child 2" })
|
|
1004
1088
|
subagent({ action: "resume", id: "<nested-run-id>", message: "follow-up for a nested child" })
|
|
1089
|
+
subagent({ action: "steer", id: "<run-id>", message: "guidance for the running child" })
|
|
1090
|
+
subagent({ action: "steer", id: "<run-id>", index: 1, message: "guidance for child 2" })
|
|
1005
1091
|
subagent({ action: "append-step", id: "<run-id>", chain: [{ agent: "worker", task: "Continue from {previous}" }] })
|
|
1006
1092
|
subagent({ action: "doctor" })
|
|
1007
1093
|
```
|
|
1008
1094
|
|
|
1009
|
-
`status` resolves exact foreground ids, top-level async ids, and nested run ids before falling back to prefix matching. Nested status shows the root/parent path, nested children, session/artifact paths when known, and nested control commands. Inside child-safe fanout mode, bare `status` requires an id when no local foreground run is active, so children cannot enumerate unrelated top-level async runs. Bare `interrupt` still targets only the visible top-level run; interrupting a nested run requires its explicit nested id.
|
|
1095
|
+
`status` resolves exact foreground ids, top-level async ids, and nested run ids before falling back to prefix matching. `view: "fleet"` is an optional read-only active-run surface with transcript commands; it does not add steering or stop controls. `view: "transcript"` tails the selected run's live `output-<index>.log` or persisted session transcript, with `lines` capped at 500. Nested status shows the root/parent path, nested children, session/artifact paths when known, and nested control commands. Inside child-safe fanout mode, bare `status` requires an id when no local foreground run is active, so children cannot enumerate unrelated top-level async runs. Bare `interrupt` still targets only the visible top-level run; interrupting a nested run requires its explicit nested id.
|
|
1010
1096
|
|
|
1011
1097
|
`resume` sends the follow-up directly when an async child is still reachable over intercom. After completion, it revives the child by starting a new async child from the stored child session file. Multi-child async runs and remembered foreground single, parallel, or chain runs can be revived by passing `index` to choose the child. Nested runs can be resumed by nested id when their live route or persisted session metadata is available. Revive starts a new child process from the old session context; it does not restart the same OS process, and it requires the chosen child to have a persisted `.jsonl` session file.
|
|
1012
1098
|
|
|
1099
|
+
`steer` queues non-terminal guidance for a running async Pi child, or for a pending indexed child that will start later in the same async run. It does not interrupt, pause, or revive a child. Delivery requires the spawned Pi session to support mid-run `sendUserMessage(..., { deliverAs: "steer" })`; unsupported runtimes keep the request visible in control artifacts but cannot receive it live. Use `index` for multi-child runs when you want to steer one child; without `index`, steering targets the currently running child or children.
|
|
1100
|
+
|
|
1013
1101
|
`append-step` accepts exactly one sequential, static parallel, or dynamic fanout chain step for a top-level async chain whose status is still `running`. The step is persisted in the run directory and becomes eligible only after the chain's already-queued steps finish; completed, failed, paused, foreground, single, and top-level parallel runs reject appends.
|
|
1014
1102
|
|
|
1015
1103
|
## Worktree isolation
|
|
@@ -1040,12 +1128,24 @@ Requirements:
|
|
|
1040
1128
|
- task-level `cwd` overrides must be omitted or match the shared cwd
|
|
1041
1129
|
- configured `worktreeSetupHook` must return valid JSON before timeout
|
|
1042
1130
|
|
|
1131
|
+
By default, worktrees are created under the system temp directory. Set `worktreeBaseDir` in config, or `PI_SUBAGENTS_WORKTREE_DIR` when config is unset, to put them under a stable trusted directory. Missing base directories are created automatically.
|
|
1132
|
+
|
|
1043
1133
|
After a worktree parallel step completes, per-agent diff stats are appended to the output and full patch files are written to artifacts. Worktrees and temp branches are cleaned up in `finally` blocks.
|
|
1044
1134
|
|
|
1045
1135
|
## Configuration
|
|
1046
1136
|
|
|
1047
1137
|
`pi-subagents` reads optional JSON config from `~/.pi/agent/extensions/subagent/config.json`.
|
|
1048
1138
|
|
|
1139
|
+
### `toolDescriptionMode`
|
|
1140
|
+
|
|
1141
|
+
```json
|
|
1142
|
+
{ "toolDescriptionMode": "compact" }
|
|
1143
|
+
```
|
|
1144
|
+
|
|
1145
|
+
Controls the parent-facing `subagent` tool description registered at startup. `full` is the default. `compact` keeps the execution modes, async/wait guidance, child-safety boundary, management/action split, one-writer review guidance, and artifact/status essentials with less prompt bloat.
|
|
1146
|
+
|
|
1147
|
+
`custom` reads `subagent-tool-description.md` from the project config directory, then from `~/.pi/agent/subagent-tool-description.md`. Missing, empty, unreadable, or oversized custom files fall back to the full description. Custom templates may use `{{fullDescription}}`, `{{compactDescription}}`, `{{safetyGuidance}}`, `{{agentDir}}`, and `{{projectConfigDir}}`; the safety guidance is always present so custom prose cannot remove the runtime guardrails. Restart Pi after changing the mode or custom file.
|
|
1148
|
+
|
|
1049
1149
|
### `asyncByDefault`
|
|
1050
1150
|
|
|
1051
1151
|
```json
|
|
@@ -1062,6 +1162,30 @@ Makes top-level calls use background execution when the request does not explici
|
|
|
1062
1162
|
|
|
1063
1163
|
Forces depth-0 single, parallel, and chain runs into background mode and bypasses clarify UI by forcing `clarify: false`. Nested calls keep their own inherited settings.
|
|
1064
1164
|
|
|
1165
|
+
### `globalConcurrencyLimit`
|
|
1166
|
+
|
|
1167
|
+
```json
|
|
1168
|
+
{ "globalConcurrencyLimit": 20 }
|
|
1169
|
+
```
|
|
1170
|
+
|
|
1171
|
+
Caps simultaneously running subagent tasks within a single run across top-level parallel tasks, inline chain parallel groups, and dynamic fanout groups. The default is `20`; invalid values are clamped to `1`. Per-step `concurrency` and `parallel.concurrency` still apply, so effective concurrency is the lower of the local cap and the available global slots.
|
|
1172
|
+
|
|
1173
|
+
### `maxSubagentSpawnsPerSession`
|
|
1174
|
+
|
|
1175
|
+
```json
|
|
1176
|
+
{ "maxSubagentSpawnsPerSession": 40 }
|
|
1177
|
+
```
|
|
1178
|
+
|
|
1179
|
+
Caps the total number of child subagent launches allowed during one parent session, including single runs, parallel task counts, static chain steps, and bounded dynamic fanout children. Set `PI_SUBAGENT_MAX_SPAWNS_PER_SESSION` to override the config for a process. The default is `40`; `0` blocks new subagent launches for that session.
|
|
1180
|
+
|
|
1181
|
+
### `scheduledRuns`
|
|
1182
|
+
|
|
1183
|
+
```json
|
|
1184
|
+
{ "scheduledRuns": { "enabled": true, "maxPending": 20, "maxLatenessMs": 300000 } }
|
|
1185
|
+
```
|
|
1186
|
+
|
|
1187
|
+
Enables optional one-shot scheduled subagent runs. When enabled, `subagent({ action: "schedule", agent, task?, schedule: "+10m" | "2030-01-01T09:00:00Z", scheduleName? })` defers a subagent launch until a future time. Absolute ISO timestamps must include a timezone (`Z` or an offset such as `+05:30`). The scheduled run launches as a normal tracked async run with fresh context once it fires, and joins the existing async widget, status, `wait`, and completion-notification paths. `schedule-list`, `schedule-status`, and `schedule-cancel` manage pending jobs. Schedules are persisted per session and restored after a Pi restart; a job missed by more than `maxLatenessMs` while Pi is unavailable is marked `missed` instead of firing late. `maxPending` caps the number of pending or running scheduled jobs per session (default `20`). The feature is opt-in: leave `enabled` unset to keep scheduling out of the tool surface and prompt. Only schedule explicit delayed runs the user asked for.
|
|
1188
|
+
|
|
1065
1189
|
### `parallel`
|
|
1066
1190
|
|
|
1067
1191
|
```json
|
|
@@ -1083,6 +1207,14 @@ Forces depth-0 single, parallel, and chain runs into background mode and bypasse
|
|
|
1083
1207
|
|
|
1084
1208
|
Session directory precedence is: `params.sessionDir`, then `config.defaultSessionDir`, then a directory derived from the parent session. Sessions are always enabled.
|
|
1085
1209
|
|
|
1210
|
+
### `singleRunOutputBaseDir`
|
|
1211
|
+
|
|
1212
|
+
```json
|
|
1213
|
+
{ "singleRunOutputBaseDir": "~/.pi/subagent-outputs" }
|
|
1214
|
+
```
|
|
1215
|
+
|
|
1216
|
+
Routes relative `output` paths for single-agent `/run` calls under this directory. Absolute per-call or agent output paths are still used as-is. When unset, relative single-run outputs go under the run's output artifact directory instead of the project root.
|
|
1217
|
+
|
|
1086
1218
|
### `maxSubagentDepth`
|
|
1087
1219
|
|
|
1088
1220
|
```json
|
|
@@ -1091,6 +1223,14 @@ Session directory precedence is: `params.sessionDir`, then `config.defaultSessio
|
|
|
1091
1223
|
|
|
1092
1224
|
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.
|
|
1093
1225
|
|
|
1226
|
+
### `PI_SUBAGENT_PI_BINARY`
|
|
1227
|
+
|
|
1228
|
+
```bash
|
|
1229
|
+
export PI_SUBAGENT_PI_BINARY=/path/to/pi-or-wrapper
|
|
1230
|
+
```
|
|
1231
|
+
|
|
1232
|
+
Overrides the command used to launch child Pi processes. Package wrappers can set this to their own `pi`/agent binary so subagents inherit wrapper flags, environment setup, and bundled resources without relying on `PATH` ordering. Empty or whitespace-only values are ignored.
|
|
1233
|
+
|
|
1094
1234
|
### `intercomBridge`
|
|
1095
1235
|
|
|
1096
1236
|
```json
|
|
@@ -1109,10 +1249,18 @@ Fields:
|
|
|
1109
1249
|
- `mode`: default `always`; use `fork-only` to inject only for forked runs, or `off` to disable the bridge.
|
|
1110
1250
|
- `instructionFile`: optional Markdown template replacing the default bridge instructions. `{orchestratorTarget}` is interpolated. Relative paths resolve from `~/.pi/agent/extensions/subagent/`.
|
|
1111
1251
|
|
|
1112
|
-
Bridge activation
|
|
1252
|
+
Bridge activation requires a targetable current parent session id, which `pi-subagents` passes to children automatically. It no longer depends on an external `pi-intercom` installation or per-agent extension allowlists.
|
|
1113
1253
|
|
|
1114
1254
|
The default injected guidance tells children to use `contact_supervisor` with `reason: "need_decision"` when blocked or needing a decision, `reason: "progress_update"` only for meaningful blocked/progress updates, generic `intercom` as fallback plumbing, and avoid routine completion handoffs.
|
|
1115
1255
|
|
|
1256
|
+
### `worktreeBaseDir`
|
|
1257
|
+
|
|
1258
|
+
```json
|
|
1259
|
+
{ "worktreeBaseDir": "/Users/matt/code/.worktrees/pi-subagents" }
|
|
1260
|
+
```
|
|
1261
|
+
|
|
1262
|
+
Sets the base directory for `worktree: true` runs. Relative paths resolve from the repository root, `~/...` expands to your home directory, and `PI_SUBAGENTS_WORKTREE_DIR` is used when config is unset. The default remains the system temp directory.
|
|
1263
|
+
|
|
1116
1264
|
### `worktreeSetupHook`
|
|
1117
1265
|
|
|
1118
1266
|
```json
|
|
@@ -1132,6 +1280,25 @@ stdin is a JSON object with `repoRoot`, `worktreePath`, `agentCwd`, `branch`, `i
|
|
|
1132
1280
|
|
|
1133
1281
|
`syntheticPaths` must be relative to the worktree root. They are removed before diff capture so helper files do not pollute patches. Tracked files are never excluded; marking a tracked path as synthetic fails setup. Default timeout is `30000` ms.
|
|
1134
1282
|
|
|
1283
|
+
### `completionBatch`
|
|
1284
|
+
|
|
1285
|
+
```json
|
|
1286
|
+
{
|
|
1287
|
+
"completionBatch": {
|
|
1288
|
+
"enabled": true,
|
|
1289
|
+
"debounceMs": 150,
|
|
1290
|
+
"maxWaitMs": 1000,
|
|
1291
|
+
"stragglerDebounceMs": 75,
|
|
1292
|
+
"stragglerMaxWaitMs": 400,
|
|
1293
|
+
"stragglerWindowMs": 2000
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
```
|
|
1297
|
+
|
|
1298
|
+
Controls smart batching of async-completion notifications. When several background subagents finish within a short window, their successful completions are held briefly and delivered as a single grouped message instead of separate notifications. A hard `maxWaitMs` cap (measured from the first completion in a group) guarantees nothing is held indefinitely, and late-finishing siblings that arrive within `stragglerWindowMs` of a group emit join a shorter straggler group governed by `stragglerDebounceMs` and `stragglerMaxWaitMs`.
|
|
1299
|
+
|
|
1300
|
+
Failed and paused completions bypass batching and fire immediately, flushing any held successes first, so failure and needs-attention signals are never delayed. Set `enabled` to `false` to restore the original one-notification-per-completion behavior. Changes apply on the next session start.
|
|
1301
|
+
|
|
1135
1302
|
## Files, logs, and observability
|
|
1136
1303
|
|
|
1137
1304
|
Each chain run creates a user-scoped temp directory like:
|
|
@@ -1142,7 +1309,7 @@ Each chain run creates a user-scoped temp directory like:
|
|
|
1142
1309
|
|
|
1143
1310
|
It may contain files such as `context.md`, `plan.md`, `progress.md`, and `parallel-{stepIndex}/.../output.md`. Directories older than 24 hours are cleaned up on extension startup.
|
|
1144
1311
|
|
|
1145
|
-
Debug artifacts live under `{sessionDir}/subagent-artifacts/` or a user-scoped temp artifact directory. Per task you may see:
|
|
1312
|
+
Debug artifacts live under `{sessionDir}/subagent-artifacts/`, `.pi-subagents/artifacts/` for project-scoped runs, or a user-scoped temp artifact directory. Single-run relative `output` files are saved under `{artifactsDir}/outputs/{runId}/` unless `singleRunOutputBaseDir` is configured. Per task you may see:
|
|
1146
1313
|
|
|
1147
1314
|
- `{runId}_{agent}_input.md`
|
|
1148
1315
|
- `{runId}_{agent}_output.md`
|
|
@@ -1153,7 +1320,7 @@ Metadata records timing, usage, exit code, final model, attempted models, and fa
|
|
|
1153
1320
|
|
|
1154
1321
|
Session files are stored under a per-run session directory. With `context: "fork"`, each child starts with `--session <branched-session-file>` produced from the parent’s current leaf. That is a real session fork, not an injected summary.
|
|
1155
1322
|
|
|
1156
|
-
Async completions notify only the originating session. The result watcher emits `subagent:async-complete`, and the extension consumes that event to render completion notifications.
|
|
1323
|
+
Async completions notify only the originating session. The result watcher emits `subagent:async-complete`, and the extension consumes that event to render completion notifications. Successful sibling completions are held briefly and delivered as a single grouped message when they finish within a short window (see `completionBatch`); failed and paused completions always fire immediately.
|
|
1157
1324
|
|
|
1158
1325
|
Async runs write:
|
|
1159
1326
|
|
|
@@ -1165,7 +1332,7 @@ Async runs write:
|
|
|
1165
1332
|
subagent-log-<id>.md
|
|
1166
1333
|
```
|
|
1167
1334
|
|
|
1168
|
-
`status.json` powers the widget and `subagent({ action: "status" })` output. `events.jsonl` contains wrapper events plus child Pi JSON events annotated with run and step metadata. Nested fanout status is stored as compact sidecar event/registry metadata and merged into parent status views and result/intercom payloads; full recursive status snapshots are not embedded in parent result files. `output-<n>.log` is a live human-readable tail. Fallback information is persisted so background runs are debuggable after completion.
|
|
1335
|
+
`status.json` powers the widget and `subagent({ action: "status" })` output. `events.jsonl` contains wrapper events plus child Pi JSON events annotated with run and step metadata, including `subagent.steer.requested` when live async steering is queued. Nested fanout status is stored as compact sidecar event/registry metadata and merged into parent status views and result/intercom payloads; full recursive status snapshots are not embedded in parent result files. `output-<n>.log` is a live human-readable tail. Fallback information is persisted so background runs are debuggable after completion.
|
|
1169
1336
|
|
|
1170
1337
|
## Acceptance Gates
|
|
1171
1338
|
|
|
@@ -1199,9 +1366,9 @@ For `attested` or stricter levels, the child prompt includes a standardized acce
|
|
|
1199
1366
|
|
|
1200
1367
|
## Live progress
|
|
1201
1368
|
|
|
1202
|
-
Foreground runs show compact live progress for single, chain, and parallel modes: current tool, recent output, token counts, duration, activity freshness, current-tool duration, and chain graph metadata when available.
|
|
1369
|
+
Foreground runs show compact live progress for single, chain, and parallel modes: current tool, recent output, token counts, aggregate cost, duration, activity freshness, current-tool duration, and chain graph metadata when available.
|
|
1203
1370
|
|
|
1204
|
-
Press `Ctrl+O` to expand the full streaming view with complete output per step.
|
|
1371
|
+
Press Pi's configured expand key (`Ctrl+O` by default) to expand the full streaming view with complete output per step.
|
|
1205
1372
|
|
|
1206
1373
|
Sequential chains show a flow line like `done scout → running planner`. Chains with parallel steps show per-step cards instead. Chain status uses `label` and `phase` metadata when present, while falling back to agent names for older chains.
|
|
1207
1374
|
|
|
@@ -1247,13 +1414,13 @@ Intercom delivery events:
|
|
|
1247
1414
|
- `subagent:control-intercom`
|
|
1248
1415
|
- `subagent:result-intercom`
|
|
1249
1416
|
|
|
1250
|
-
The result watcher emits `subagent:async-complete`; `src/extension/index.ts` registers the notification handler that consumes it. Control/attention events are surfaced as visible parent notices and persisted for async runs.
|
|
1417
|
+
The result watcher emits `subagent:async-complete`; `src/extension/index.ts` registers the notification handler that consumes it. Control/attention events are surfaced as visible parent notices and persisted for async runs. Native supervisor requests are delivered only to the exact parent session that spawned the child.
|
|
1251
1418
|
|
|
1252
1419
|
## Prompt-template integration
|
|
1253
1420
|
|
|
1254
|
-
`pi-subagents` works standalone through natural language, the `subagent` tool, slash commands, and the packaged prompt shortcuts listed near the top of this README.
|
|
1421
|
+
`pi-subagents` works standalone through natural language, the `subagent` tool, slash commands, and the packaged prompt shortcuts listed near the top of this README. It also includes a native prompt-workflow adapter for reusable subagent prompt templates, so you do not need `pi-prompt-template-model` for the common subagent workflow path.
|
|
1255
1422
|
|
|
1256
|
-
|
|
1423
|
+
Create a prompt in `.pi/prompts/` or `~/.pi/agent/prompts/`:
|
|
1257
1424
|
|
|
1258
1425
|
```md
|
|
1259
1426
|
---
|
|
@@ -1265,9 +1432,21 @@ cwd: /tmp/screenshots
|
|
|
1265
1432
|
Use url in the prompt to take screenshot: $@
|
|
1266
1433
|
```
|
|
1267
1434
|
|
|
1268
|
-
Then
|
|
1435
|
+
Then run it through the native adapter:
|
|
1436
|
+
|
|
1437
|
+
```text
|
|
1438
|
+
/prompt-workflow take-screenshot https://example.com
|
|
1439
|
+
```
|
|
1440
|
+
|
|
1441
|
+
The adapter delegates to the named subagent, applies `model`, `skill`, `cwd`, `worktree`, and fork/fresh context metadata, and supports runtime overrides such as `--subagent reviewer`, `--fork`, `--fresh`, `--worktree`, and `--bg`.
|
|
1442
|
+
|
|
1443
|
+
For prompt-template chains, use:
|
|
1444
|
+
|
|
1445
|
+
```text
|
|
1446
|
+
/chain-prompts analyze -> fix -- user arguments here
|
|
1447
|
+
```
|
|
1269
1448
|
|
|
1270
|
-
|
|
1449
|
+
Each named prompt becomes a native `subagent` chain step. This is intentionally scoped to subagent workflows; compare-style prompt features such as `/best-of-n` are not part of the built-in adapter.
|
|
1271
1450
|
|
|
1272
1451
|
## Runtime files
|
|
1273
1452
|
|
|
@@ -1287,4 +1466,4 @@ The main runtime files are:
|
|
|
1287
1466
|
| `src/runs/shared/worktree.ts` | Git worktree isolation. |
|
|
1288
1467
|
| `src/intercom/intercom-bridge.ts` | Runtime intercom bridge instructions and diagnostics. |
|
|
1289
1468
|
| `src/extension/schemas.ts` / `src/shared/types.ts` | Tool schemas, shared types, and event constants. |
|
|
1290
|
-
| `test/unit/` / `test/integration/` | Unit
|
|
1469
|
+
| `test/unit/` / `test/integration/` / `test/e2e/` | Unit, loader-based integration, and real-session E2E tests. |
|
package/install.mjs
CHANGED
|
@@ -85,8 +85,9 @@ if (fs.existsSync(EXTENSION_DIR)) {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
console.log(`
|
|
88
|
-
The extension is now available in pi.
|
|
88
|
+
The extension is now available in pi. Tools added:
|
|
89
89
|
• subagent - Delegate tasks to agents and inspect run status
|
|
90
|
+
• wait - Block until background subagent runs finish (delivers their results)
|
|
90
91
|
|
|
91
92
|
Documentation: ${EXTENSION_DIR}/README.md
|
|
92
93
|
`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-subagents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.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",
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"test": "npm run test:unit",
|
|
39
39
|
"test:unit": "node --experimental-strip-types --test test/unit/*.test.ts",
|
|
40
40
|
"test:integration": "node --experimental-transform-types --import ./test/support/register-loader.mjs --test test/integration/*.test.ts",
|
|
41
|
-
"test:
|
|
41
|
+
"test:e2e": "node --experimental-transform-types --import ./test/support/register-loader.mjs --test test/e2e/*.test.ts",
|
|
42
|
+
"test:all": "npm run test:unit && npm run test:integration && npm run test:e2e"
|
|
42
43
|
},
|
|
43
44
|
"pi": {
|
|
44
45
|
"extensions": [
|