pi-subagents 0.32.0 → 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 +30 -3
- package/README.md +147 -58
- package/install.mjs +2 -1
- package/package.json +3 -2
- package/skills/pi-subagents/SKILL.md +70 -14
- package/src/agents/agent-management.ts +177 -5
- package/src/agents/agent-memory.ts +254 -0
- package/src/agents/agent-serializer.ts +11 -0
- package/src/agents/agents.ts +142 -12
- package/src/agents/chain-serializer.ts +27 -2
- package/src/extension/doctor.ts +1 -9
- package/src/extension/fanout-child.ts +2 -2
- package/src/extension/index.ts +65 -90
- package/src/extension/rpc.ts +369 -0
- package/src/extension/schemas.ts +52 -8
- 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 +51 -7
- package/src/runs/background/async-job-tracker.ts +12 -2
- package/src/runs/background/async-status.ts +27 -2
- package/src/runs/background/completion-batcher.ts +166 -0
- package/src/runs/background/control-channel.ts +106 -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 +166 -6
- package/src/runs/background/scheduled-runs.ts +514 -0
- package/src/runs/background/subagent-runner.ts +409 -35
- package/src/runs/background/wait.ts +353 -0
- package/src/runs/foreground/chain-execution.ts +95 -21
- package/src/runs/foreground/execution.ts +150 -21
- package/src/runs/foreground/subagent-executor.ts +378 -64
- package/src/runs/shared/dynamic-fanout.ts +1 -1
- package/src/runs/shared/model-fallback.ts +167 -20
- package/src/runs/shared/model-scope.ts +128 -0
- package/src/runs/shared/nested-events.ts +31 -0
- package/src/runs/shared/parallel-utils.ts +1 -0
- package/src/runs/shared/pi-args.ts +30 -1
- package/src/runs/shared/subagent-prompt-runtime.ts +108 -2
- package/src/runs/shared/tool-budget.ts +74 -0
- package/src/runs/shared/turn-budget.ts +52 -0
- package/src/shared/artifacts.ts +1 -0
- package/src/shared/atomic-json.ts +15 -2
- package/src/shared/child-transcript.ts +212 -0
- package/src/shared/settings.ts +3 -1
- package/src/shared/types.ts +134 -19
- package/src/slash/prompt-workflows.ts +330 -0
- package/src/slash/slash-commands.ts +16 -2
- package/src/tui/render.ts +16 -8
- package/src/extension/companion-suggestions.ts +0 -359
package/CHANGELOG.md
CHANGED
|
@@ -2,16 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## [0.33.0] - 2026-07-03
|
|
6
6
|
|
|
7
|
-
###
|
|
7
|
+
### Added
|
|
8
|
+
- Added optional `toolBudget` limits for child subagent tool calls. Runs, steps, and agents can set `{ soft?, hard, block? }`; the child runtime nudges at the soft limit and blocks configured tools after the hard limit so runaway browsing can still finish with final text.
|
|
9
|
+
- Added a stable v1 in-process event-bus RPC for other Pi extensions, with `ping`, `status`, async-only `spawn`, `interrupt`, and async `stop` over versioned request/reply envelopes.
|
|
10
|
+
- Added `toolDescriptionMode` with `full`, `compact`, and `custom` modes for the parent-facing `subagent` tool description. Compact mode reduces prompt bloat while keeping safety-critical orchestration guidance, and invalid custom descriptions fall back to full mode.
|
|
11
|
+
- Added an optional read-only subagent fleet/status view with `/subagents-fleet` and `subagent({ action: "status", view: "fleet" })`, plus `view: "transcript"` to tail active async child output/session artifacts.
|
|
12
|
+
- Added uniform per-child transcript artifacts (`<run>_<agent>_transcript.jsonl`) for foreground and async subagent runs, gated by `subagents.artifacts.includeTranscript` (default on). Each transcript is a versioned JSONL stream of child messages, tool starts/ends, and stdout/stderr lines with a byte cap and truncation marker.
|
|
13
|
+
- Added `subagent({ action: "steer", id, message, index? })` for non-terminal guidance to live async Pi child sessions, with file-backed control requests, per-child steering inboxes, status/event visibility, and queued delivery for pending indexed async children when the runtime supports mid-run steering.
|
|
14
|
+
- Added an optional `turnBudget` (`maxTurns` with `graceTurns`) for foreground and async/background subagent runs. At the soft `maxTurns` limit the child is warned via its system prompt to wrap up; after `graceTurns` additional assistant turns the run is aborted and partial output is returned. `turnBudget`, `turnBudgetExceeded`, and `wrapUpRequested` propagate through results, async status, and nested summaries.
|
|
15
|
+
- Added optional scheduled subagent runs so callers can defer a subagent launch until a future time. `subagent({ action: "schedule", agent, task?, schedule: "+10m" | "2030-01-01T09:00:00Z", scheduleName? })` arms a one-shot timer that launches the run as a normal tracked async run once it fires, with `schedule-list`, `schedule-status`, and `schedule-cancel` management actions. Schedules are persisted per session and restored after a Pi restart; jobs missed by more than the configured lateness window are marked `missed` instead of firing late. The feature is opt-in and requires `{ "scheduledRuns": { "enabled": true } }` in `~/.pi/agent/extensions/subagent/config.json`. Only schedule explicit delayed runs the user asked for. Thanks to @tintinweb for the concept.
|
|
16
|
+
- Added a real Pi-session E2E test lane with faux provider routing to verify parent-child subagent result delivery without network model calls.
|
|
17
|
+
- Hardened the `wait` tool's wake path so an event wake cancels its poll-interval fallback timer instead of letting both run, and so an already-aborted turn resolves immediately. Added a test that verifies an event wakes `wait` before the poll interval elapses.
|
|
18
|
+
- Added smart completion batching for async subagent notifications. Successful sibling completions that finish within a short window now arrive as a single grouped message instead of separate notifications; a hard max-wait cap prevents holding them indefinitely, and late-finishing siblings join a shorter straggler group. Failed and paused completions bypass batching and fire immediately so failure and attention signals are never delayed. The debounce window, max-wait cap, and straggler windows are configurable via `completionBatch` in `config.json`.
|
|
19
|
+
- Added `subagent({ action: "eject" })`, `disable`, `enable`, and `reset` management actions for bundled and custom agents. `eject` copies a builtin or package agent to user/project scope as an editable custom file that shadows the original; `disable`/`enable` toggle a reversible `agentOverrides.<name>.disabled` settings override without deleting the agent; `reset` removes the scope's custom agent file and/or settings override to restore the bundled default. All four accept `agentScope: "user" | "project"` (default `user`) and are blocked from child-safe fanout mode alongside `create`/`update`/`delete`.
|
|
20
|
+
- Added fuzzy model resolution so callers can specify models with provider separator variations, optional date-stamp parts, and case differences instead of exact `provider/modelId` strings. When `subagents.modelScope: { enforce: true, allow: [...] }` is configured, explicit caller-supplied out-of-scope models error while frontmatter/parent-inherited/fallback models warn. Inspired by @tintinweb's pi-subagents.
|
|
21
|
+
- Added a parent-side `wait` tool for detached async subagent runs. `wait()` returns when the next active run finishes or needs attention, `wait({ all: true })` drains all active runs, `wait({ id })` targets one run, and `wait({ timeoutMs })` caps the block. This lets background-launching skills and non-interactive `pi -p` runs keep going without sleep/status-polling loops or abandoned children. Thanks to RoboBryce (@robobryce) for #365.
|
|
22
|
+
- Added an opt-in `memory` frontmatter field for agent definitions so recurring custom agents can maintain role-specific durable memory (e.g. a security reviewer accumulating threat-model notes). `memory: { scope: "project" | "user", path: "<name>" }` resolves a safe `agent-memory/` directory, injects the first 200 lines of a `MEMORY.md` into the child system prompt, and falls back to a read-only memory block for agents without write tools. Memory lives under a dedicated namespace that does not conflict with Pi's parent/session/project memory system. Inspired by @tintinweb's pi-subagents.
|
|
23
|
+
- Added native supervisor coordination for child subagents. Children can use `contact_supervisor` without installing `pi-intercom`, and parent-side requests are scoped to the exact session id that spawned the child.
|
|
24
|
+
- Added native prompt workflow commands: `/prompt-workflow` runs a prompt template through a subagent, and `/chain-prompts` turns prompt templates into native subagent chain steps.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- Let foreground sequential chain tool calls launch directly when `clarify` is omitted; use `clarify: true` to opt into the clarify UI. Addresses #385.
|
|
28
|
+
- Tolerate execution-mode action aliases such as `single`, `parallel`, `PARALLEL`, and `tasks` when the matching execution fields are present, while preserving clear runtime errors for unknown management actions, addressing #382.
|
|
29
|
+
- Removed companion-package recommendation messages from session start, `subagent({ action: "list" })`, and `/subagents-doctor`, addressing #381.
|
|
30
|
+
- Scope async subagent completion notifications to the exact owning Pi session so another session in the same repo no longer receives result notices.
|
|
31
|
+
- Harden scheduled-run timestamp parsing and persisted store validation so ambiguous absolute times and corrupted job records fail clearly instead of being normalized or dropped.
|
|
32
|
+
- Derive live-detail and full-notification hints from Pi's configured expand key instead of hard-coding `Ctrl+O`. Thanks to Kylegl (@kylegl) for #364.
|
|
33
|
+
- Tolerate transient Windows `EPERM`/`EBUSY`/`EACCES` locks when atomically replacing async JSON files. Thanks to ThanhNT29Jacky (@ThanhNT29Jacky) for #380.
|
|
34
|
+
- Hardened the async timeout integration test to wait for the mock child to spawn before asserting the timeout result, fixing a race where the timeout could fire before the child existed.
|
|
8
35
|
|
|
9
36
|
## [0.32.0] - 2026-07-01
|
|
10
37
|
|
|
11
38
|
### Added
|
|
12
39
|
- Added `subagents.defaultModel` so subagents can have a global default model separate from the parent session model. Thanks to Artem Timofeev (@atimofeev) for #339.
|
|
13
40
|
- Added `/subagent-cost` and `totalChildUsage` run details so parent sessions can inspect aggregate subagent child usage and cost. Thanks to Aaron Ky-Riesenbach (@aaronkyriesenbach) for #343.
|
|
14
|
-
- Added configurable companion package recommendations for `pi-intercom` and `pi-prompt-template-model`, surfaced in session-start transcript messages, `subagent({ action: "list" })`, and `/subagents-doctor`, with `/subagents-companions` hide/show/status controls.
|
|
41
|
+
- Added configurable companion package recommendations for `pi-intercom` and `pi-prompt-template-model`, surfaced in session-start transcript messages, `subagent({ action: "list" })`, and `/subagents-doctor`, with `/subagents-companions` hide/show/status controls. Removed again in the next release after #381 because context-visible package recommendations were too noisy.
|
|
15
42
|
- Added detached async runner stdout and stderr log files. Thanks to Daniel Mateos Carballares (@danim47c) for #358.
|
|
16
43
|
- Added `totalCost` rollups to foreground single, parallel, and chain run details, including nested foreground subagent costs and compact progress display. Thanks to Clark Everson (@gr3enarr0w) for #345.
|
|
17
44
|
- Added `globalConcurrencyLimit` to cap simultaneously running subagent tasks across parallel groups in a single run. Thanks to Clark Everson (@gr3enarr0w) for #349.
|
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.
|
|
@@ -168,11 +168,28 @@ To inspect what `pi-subagents` has actually loaded right now, use:
|
|
|
168
168
|
|
|
169
169
|
That reports the live runtime mapping, which can differ from settings on disk until you reload Pi.
|
|
170
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
|
+
|
|
171
188
|
## Where running subagents show up
|
|
172
189
|
|
|
173
190
|
Foreground runs stream progress in the conversation while they run.
|
|
174
191
|
|
|
175
|
-
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.
|
|
176
193
|
|
|
177
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.
|
|
178
195
|
|
|
@@ -186,6 +203,26 @@ Async runs also write machine-readable lifecycle artifacts for observability and
|
|
|
186
203
|
|
|
187
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.
|
|
188
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
|
+
|
|
189
226
|
If something feels misconfigured, run:
|
|
190
227
|
|
|
191
228
|
```text
|
|
@@ -228,17 +265,9 @@ The package includes reusable prompt templates for common workflows. You do not
|
|
|
228
265
|
|
|
229
266
|
Add `autofix` to `/parallel-review` or `/parallel-cleanup` to apply only the synthesized fixes worth doing now after reviewers return.
|
|
230
267
|
|
|
231
|
-
##
|
|
232
|
-
|
|
233
|
-
`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.
|
|
268
|
+
## Native supervisor coordination
|
|
234
269
|
|
|
235
|
-
|
|
236
|
-
pi install npm:pi-intercom
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
When `pi-intercom` is not active, `pi-subagents` may recommend it at session start, in `subagent({ action: "list" })`, and in `/subagents-doctor`. The recommendation is visible to the assistant so it can offer to run the install command or hide the recommendation after you approve that action.
|
|
240
|
-
|
|
241
|
-
Most users do not call `intercom` directly. After `pi-intercom` is installed, `pi-subagents` can automatically give child agents a private coordination channel back to the parent session. The bridge recognizes the normal `pi install npm:pi-intercom` package install as well as legacy local extension checkouts.
|
|
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.
|
|
242
271
|
|
|
243
272
|
Use it for work where the child might need a decision instead of guessing:
|
|
244
273
|
|
|
@@ -252,11 +281,11 @@ Ask oracle to review this plan. If it sees a decision I need to make, have it as
|
|
|
252
281
|
|
|
253
282
|
The child can use one dedicated coordination tool:
|
|
254
283
|
|
|
255
|
-
- `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.
|
|
256
285
|
|
|
257
|
-
|
|
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.
|
|
258
287
|
|
|
259
|
-
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.
|
|
260
289
|
|
|
261
290
|
If messages do not show up, run:
|
|
262
291
|
|
|
@@ -504,13 +533,15 @@ You can combine them in either order:
|
|
|
504
533
|
/run reviewer "review this diff" --bg --fork
|
|
505
534
|
```
|
|
506
535
|
|
|
507
|
-
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.
|
|
508
539
|
|
|
509
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.
|
|
510
541
|
|
|
511
542
|
## Clarify and launch UI
|
|
512
543
|
|
|
513
|
-
|
|
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.
|
|
514
545
|
|
|
515
546
|
Common clarify keys:
|
|
516
547
|
|
|
@@ -575,7 +606,7 @@ Supported override fields are `model`, `fallbackModels`, `thinking`, `systemProm
|
|
|
575
606
|
|
|
576
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.
|
|
577
608
|
|
|
578
|
-
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.
|
|
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.
|
|
579
610
|
|
|
580
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.
|
|
581
612
|
|
|
@@ -646,7 +677,22 @@ Important fields:
|
|
|
646
677
|
| `defaultProgress` | Maintain `progress.md`. |
|
|
647
678
|
| `completionGuard` | Set `false` only for non-implementation agents that may mention implementation words while using mutation-capable tools such as `bash`. |
|
|
648
679
|
| `interactive` | Parsed for compatibility but not enforced in v1. |
|
|
649
|
-
| `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.
|
|
650
696
|
|
|
651
697
|
### Tool and extension selection
|
|
652
698
|
|
|
@@ -838,7 +884,7 @@ What the bundled skill covers:
|
|
|
838
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
|
|
839
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
|
|
840
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
|
|
841
|
-
- **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
|
|
842
888
|
- **Control and diagnostics**: attention signals, soft interrupts, status, and the `doctor` action
|
|
843
889
|
|
|
844
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.
|
|
@@ -974,33 +1020,45 @@ Agent definitions are not loaded into context by default. Management actions let
|
|
|
974
1020
|
{ action: "update", chainName: "review-pipeline", config: { steps: [...] } }
|
|
975
1021
|
{ action: "delete", agent: "scout" }
|
|
976
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" }
|
|
977
1029
|
```
|
|
978
1030
|
|
|
979
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 `""`.
|
|
980
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
|
+
|
|
981
1035
|
### Parameter reference
|
|
982
1036
|
|
|
983
1037
|
| Param | Type | Default | Description |
|
|
984
1038
|
|-------|------|---------|-------------|
|
|
985
1039
|
| `agent` | string | - | Agent name for single mode, or target for management actions. |
|
|
986
1040
|
| `task` | string | - | Task string for single mode. |
|
|
987
|
-
| `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`. |
|
|
988
1042
|
| `chainName` | string | - | Chain name for management actions. |
|
|
989
1043
|
| `config` | object/string | - | Agent or chain config for create/update. |
|
|
990
1044
|
| `output` | `string \| false` | agent default | Override single-agent output file. |
|
|
991
1045
|
| `outputMode` | `"inline" \| "file-only"` | `inline` | Return saved output inline or as a concise saved-file reference. `file-only` requires an `output` path. |
|
|
992
1046
|
| `skill` | `string \| string[] \| false` | agent default | Override skills or disable all. |
|
|
993
1047
|
| `model` | string | agent default | Override model. |
|
|
994
|
-
| `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`. |
|
|
995
1049
|
| `concurrency` | number | config or `4` | Top-level parallel concurrency. |
|
|
996
1050
|
| `worktree` | boolean | false | Create isolated git worktrees for parallel tasks. |
|
|
997
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. |
|
|
998
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`. |
|
|
999
1053
|
| `chainDir` | string | temp chain dir | Persistent directory for chain artifacts. |
|
|
1000
|
-
| `
|
|
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. |
|
|
1001
1057
|
| `agentScope` | `user \| project \| both` | `both` | Agent discovery scope. Project wins on collisions. |
|
|
1002
1058
|
| `async` | boolean | false | Background execution. For chains, `clarify: true` explicitly keeps the run foreground for the clarify UI. |
|
|
1003
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. |
|
|
1004
1062
|
| `cwd` | string | runtime cwd | Override working directory. |
|
|
1005
1063
|
| `maxOutput` | object | 200KB, 5000 lines | Final output truncation limits. |
|
|
1006
1064
|
| `artifacts` | boolean | true | Write debug artifacts. |
|
|
@@ -1013,27 +1071,33 @@ Agent definitions are not loaded into context by default. Management actions let
|
|
|
1013
1071
|
|
|
1014
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.
|
|
1015
1073
|
|
|
1016
|
-
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}`.
|
|
1017
1075
|
|
|
1018
1076
|
Status and control actions:
|
|
1019
1077
|
|
|
1020
1078
|
```ts
|
|
1021
1079
|
subagent({ action: "status" })
|
|
1080
|
+
subagent({ action: "status", view: "fleet" })
|
|
1022
1081
|
subagent({ action: "status", id: "<run-id>" })
|
|
1082
|
+
subagent({ action: "status", id: "<run-id>", view: "transcript", index: 0, lines: 80 })
|
|
1023
1083
|
subagent({ action: "status", id: "<nested-run-id>" })
|
|
1024
1084
|
subagent({ action: "interrupt", id: "<run-id>" })
|
|
1025
1085
|
subagent({ action: "interrupt", id: "<nested-run-id>" })
|
|
1026
1086
|
subagent({ action: "resume", id: "<run-id>", message: "follow-up question" })
|
|
1027
1087
|
subagent({ action: "resume", id: "<run-id>", index: 1, message: "follow-up for child 2" })
|
|
1028
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" })
|
|
1029
1091
|
subagent({ action: "append-step", id: "<run-id>", chain: [{ agent: "worker", task: "Continue from {previous}" }] })
|
|
1030
1092
|
subagent({ action: "doctor" })
|
|
1031
1093
|
```
|
|
1032
1094
|
|
|
1033
|
-
`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.
|
|
1034
1096
|
|
|
1035
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.
|
|
1036
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
|
+
|
|
1037
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.
|
|
1038
1102
|
|
|
1039
1103
|
## Worktree isolation
|
|
@@ -1072,6 +1136,16 @@ After a worktree parallel step completes, per-agent diff stats are appended to t
|
|
|
1072
1136
|
|
|
1073
1137
|
`pi-subagents` reads optional JSON config from `~/.pi/agent/extensions/subagent/config.json`.
|
|
1074
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
|
+
|
|
1075
1149
|
### `asyncByDefault`
|
|
1076
1150
|
|
|
1077
1151
|
```json
|
|
@@ -1104,6 +1178,14 @@ Caps simultaneously running subagent tasks within a single run across top-level
|
|
|
1104
1178
|
|
|
1105
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.
|
|
1106
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
|
+
|
|
1107
1189
|
### `parallel`
|
|
1108
1190
|
|
|
1109
1191
|
```json
|
|
@@ -1167,32 +1249,10 @@ Fields:
|
|
|
1167
1249
|
- `mode`: default `always`; use `fork-only` to inject only for forked runs, or `off` to disable the bridge.
|
|
1168
1250
|
- `instructionFile`: optional Markdown template replacing the default bridge instructions. `{orchestratorTarget}` is interpolated. Relative paths resolve from `~/.pi/agent/extensions/subagent/`.
|
|
1169
1251
|
|
|
1170
|
-
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.
|
|
1171
1253
|
|
|
1172
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.
|
|
1173
1255
|
|
|
1174
|
-
### `companionSuggestions`
|
|
1175
|
-
|
|
1176
|
-
```json
|
|
1177
|
-
{
|
|
1178
|
-
"companionSuggestions": {
|
|
1179
|
-
"enabled": true,
|
|
1180
|
-
"packages": {
|
|
1181
|
-
"pi-intercom": {
|
|
1182
|
-
"surfaces": ["session_start", "list", "doctor"]
|
|
1183
|
-
},
|
|
1184
|
-
"pi-prompt-template-model": {
|
|
1185
|
-
"surfaces": ["session_start", "list", "doctor"]
|
|
1186
|
-
}
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
|
-
```
|
|
1191
|
-
|
|
1192
|
-
Controls recommendations for optional companion packages. `pi-intercom` enables live supervisor decisions, progress updates, and grouped result delivery. `pi-prompt-template-model` makes subagent workflows reusable as prompt templates with model/thinking/skill/subagent frontmatter.
|
|
1193
|
-
|
|
1194
|
-
Use `/subagents-companions status` to inspect recommendation status. Use `/subagents-companions hide pi-intercom workspace` or `/subagents-companions hide pi-prompt-template-model user` to hide a recommendation. Use `/subagents-companions show <package>` to show a workspace recommendation again. Set `companionSuggestions` to `false` to disable all companion recommendations.
|
|
1195
|
-
|
|
1196
1256
|
### `worktreeBaseDir`
|
|
1197
1257
|
|
|
1198
1258
|
```json
|
|
@@ -1220,6 +1280,25 @@ stdin is a JSON object with `repoRoot`, `worktreePath`, `agentCwd`, `branch`, `i
|
|
|
1220
1280
|
|
|
1221
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.
|
|
1222
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
|
+
|
|
1223
1302
|
## Files, logs, and observability
|
|
1224
1303
|
|
|
1225
1304
|
Each chain run creates a user-scoped temp directory like:
|
|
@@ -1241,7 +1320,7 @@ Metadata records timing, usage, exit code, final model, attempted models, and fa
|
|
|
1241
1320
|
|
|
1242
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.
|
|
1243
1322
|
|
|
1244
|
-
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.
|
|
1245
1324
|
|
|
1246
1325
|
Async runs write:
|
|
1247
1326
|
|
|
@@ -1253,7 +1332,7 @@ Async runs write:
|
|
|
1253
1332
|
subagent-log-<id>.md
|
|
1254
1333
|
```
|
|
1255
1334
|
|
|
1256
|
-
`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.
|
|
1257
1336
|
|
|
1258
1337
|
## Acceptance Gates
|
|
1259
1338
|
|
|
@@ -1289,7 +1368,7 @@ For `attested` or stricter levels, the child prompt includes a standardized acce
|
|
|
1289
1368
|
|
|
1290
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.
|
|
1291
1370
|
|
|
1292
|
-
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.
|
|
1293
1372
|
|
|
1294
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.
|
|
1295
1374
|
|
|
@@ -1335,13 +1414,13 @@ Intercom delivery events:
|
|
|
1335
1414
|
- `subagent:control-intercom`
|
|
1336
1415
|
- `subagent:result-intercom`
|
|
1337
1416
|
|
|
1338
|
-
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.
|
|
1339
1418
|
|
|
1340
1419
|
## Prompt-template integration
|
|
1341
1420
|
|
|
1342
|
-
`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.
|
|
1343
1422
|
|
|
1344
|
-
|
|
1423
|
+
Create a prompt in `.pi/prompts/` or `~/.pi/agent/prompts/`:
|
|
1345
1424
|
|
|
1346
1425
|
```md
|
|
1347
1426
|
---
|
|
@@ -1353,11 +1432,21 @@ cwd: /tmp/screenshots
|
|
|
1353
1432
|
Use url in the prompt to take screenshot: $@
|
|
1354
1433
|
```
|
|
1355
1434
|
|
|
1356
|
-
Then
|
|
1435
|
+
Then run it through the native adapter:
|
|
1436
|
+
|
|
1437
|
+
```text
|
|
1438
|
+
/prompt-workflow take-screenshot https://example.com
|
|
1439
|
+
```
|
|
1357
1440
|
|
|
1358
|
-
|
|
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
|
+
```
|
|
1359
1448
|
|
|
1360
|
-
|
|
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.
|
|
1361
1450
|
|
|
1362
1451
|
## Runtime files
|
|
1363
1452
|
|
|
@@ -1377,4 +1466,4 @@ The main runtime files are:
|
|
|
1377
1466
|
| `src/runs/shared/worktree.ts` | Git worktree isolation. |
|
|
1378
1467
|
| `src/intercom/intercom-bridge.ts` | Runtime intercom bridge instructions and diagnostics. |
|
|
1379
1468
|
| `src/extension/schemas.ts` / `src/shared/types.ts` | Tool schemas, shared types, and event constants. |
|
|
1380
|
-
| `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": [
|