pi-subagents 0.40.0 → 0.41.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 +76 -0
- package/README.md +246 -525
- package/agents/oracle.md +1 -0
- package/package.json +12 -4
- package/prompts/parallel-context-build.md +1 -1
- package/prompts/parallel-handoff-plan.md +1 -1
- package/prompts/review-loop.md +1 -1
- package/skills/pi-subagents/SKILL.md +6 -6
- package/skills/pi-subagents/references/constraints-and-recipes.md +19 -26
- package/skills/pi-subagents/references/execution-controls.md +98 -97
- package/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
- package/skills/pi-subagents/references/prompting-and-roles.md +18 -27
- package/src/agents/agent-management.ts +155 -65
- package/src/agents/agent-serializer.ts +19 -0
- package/src/agents/agents.ts +154 -71
- package/src/agents/chain-serializer.ts +10 -7
- package/src/agents/frontmatter.ts +5 -3
- package/src/agents/identity.ts +1 -1
- package/src/agents/proactive-skills.ts +13 -10
- package/src/agents/skills.ts +23 -6
- package/src/api/control-channel.ts +4 -0
- package/src/api/delegation.ts +26 -194
- package/src/api/external-runs.ts +129 -0
- package/src/api/intercom-bridge.ts +3 -0
- package/src/api/pi-args.ts +5 -0
- package/src/api/preflight.ts +3 -3
- package/src/api/shared-types.ts +19 -0
- package/src/extension/config.ts +10 -0
- package/src/extension/control-notices.ts +5 -39
- package/src/extension/doctor.ts +10 -9
- package/src/extension/fanout-child.ts +7 -4
- package/src/extension/index.ts +232 -68
- package/src/extension/rpc.ts +18 -12
- package/src/extension/schemas.ts +48 -37
- package/src/extension/tool-description.ts +36 -86
- package/src/inspectors/herdr/actions.ts +229 -0
- package/src/inspectors/herdr/client.ts +130 -0
- package/src/inspectors/herdr/inspector-runner.ts +141 -0
- package/src/inspectors/herdr/project-panes.ts +154 -0
- package/src/integrations/herdr-status.ts +330 -0
- package/src/intercom/intercom-bridge.ts +3 -2
- package/src/intercom/result-intercom.ts +5 -1
- package/src/missions/actions.ts +372 -0
- package/src/missions/lifecycle.ts +314 -0
- package/src/missions/store.ts +442 -0
- package/src/missions/types.ts +135 -0
- package/src/policy/authority.ts +46 -0
- package/src/profiles/profiles.ts +29 -3
- package/src/runs/background/async-execution.ts +98 -49
- package/src/runs/background/async-job-tracker.ts +10 -2
- package/src/runs/background/async-resume.ts +6 -6
- package/src/runs/background/async-status.ts +29 -1
- package/src/runs/background/auto-drain.ts +3 -3
- package/src/runs/background/chain-append.ts +3 -2
- package/src/runs/background/control-channel.ts +9 -7
- package/src/runs/background/fleet-view.ts +3 -4
- package/src/runs/background/notify.ts +2 -1
- package/src/runs/background/process-terminal.ts +5 -5
- package/src/runs/background/result-watcher.ts +13 -5
- package/src/runs/background/run-id-resolver.ts +3 -3
- package/src/runs/background/run-status.ts +35 -8
- package/src/runs/background/scheduled-runs.ts +602 -375
- package/src/runs/background/stale-run-reconciler.ts +3 -3
- package/src/runs/background/subagent-runner.ts +608 -445
- package/src/runs/background/subagent-wait.ts +50 -9
- package/src/runs/background/wait-subscriptions.ts +253 -0
- package/src/runs/background/wait-tool.ts +12 -4
- package/src/runs/foreground/async-steering-action.ts +3 -3
- package/src/runs/foreground/chain-clarify.ts +8 -4
- package/src/runs/foreground/chain-execution.ts +56 -30
- package/src/runs/foreground/execution.ts +15 -2
- package/src/runs/foreground/subagent-executor.ts +1023 -273
- package/src/runs/shared/acceptance.ts +28 -6
- package/src/runs/shared/child-protocol.ts +302 -22
- package/src/runs/shared/dynamic-fanout.ts +1 -1
- package/src/runs/shared/external-cli-runner.ts +130 -0
- package/src/runs/shared/long-running-guard.ts +42 -1
- package/src/runs/shared/nested-events.ts +59 -5
- package/src/runs/shared/nested-render.ts +9 -4
- package/src/runs/shared/parallel-handoff.ts +86 -2
- package/src/runs/shared/parallel-utils.ts +11 -2
- package/src/runs/shared/permissions.ts +95 -0
- package/src/runs/shared/pi-args.ts +11 -1
- package/src/runs/shared/pi-spawn.ts +11 -1
- package/src/runs/shared/run-history.ts +1 -1
- package/src/runs/shared/subagent-prompt-runtime.ts +36 -5
- package/src/runs/shared/subagent-startup-retry.ts +5 -2
- package/src/runs/shared/turn-budget.ts +6 -6
- package/src/runs/shared/worktree.ts +122 -12
- package/src/shared/accessible-dir.ts +29 -7
- package/src/shared/artifacts.ts +18 -1
- package/src/shared/fork-context.ts +3 -2
- package/src/shared/launch-contract.ts +1 -0
- package/src/shared/settings.ts +10 -0
- package/src/shared/types.ts +156 -14
- package/src/shared/utils.ts +8 -6
- package/src/slash/delegation-adapters.ts +32 -194
- package/src/slash/delegation-request.ts +43 -126
- package/src/slash/prompt-template-bridge.ts +158 -205
- package/src/slash/prompt-workflows.ts +21 -57
- package/src/slash/slash-bridge.ts +14 -0
- package/src/slash/slash-commands.ts +31 -632
- package/src/slash/subagents-admin.ts +18 -14
- package/src/tui/fleet-status.ts +156 -21
- package/src/tui/fleet-transcript.ts +110 -5
- package/src/tui/fleet.ts +56 -24
- package/src/tui/render.ts +291 -109
- package/src/types/pi-runtime-compat.d.ts +14 -0
- package/src/watchdog/lsp-diagnostics.ts +12 -7
- package/src/watchdog/model-selection.ts +2 -2
- package/src/watchdog/permission-arbiter.ts +145 -0
- package/src/watchdog/register-child.ts +1 -1
- package/src/watchdog/register-main.ts +1 -1
- package/src/watchdog/review.ts +4 -1
- package/src/watchdog/runtime.ts +3 -2
- package/src/workflows/chat-progress.ts +140 -0
- package/src/workflows/scripted-workflow.ts +415 -0
- package/agents/advisor.md +0 -73
- package/src/extension/chain-validation.ts +0 -181
package/README.md
CHANGED
|
@@ -38,6 +38,21 @@ Run parallel reviewers: one for correctness, one for tests, and one for unnecess
|
|
|
38
38
|
|
|
39
39
|
That is enough to start.
|
|
40
40
|
|
|
41
|
+
## External CLI agent profiles
|
|
42
|
+
|
|
43
|
+
Agent profiles can opt into a local one-shot command instead of a Pi child. External runners add no install dependency, but the configured executable must exist at runtime. They are async-only, receive one combined system/task prompt over stdin, and use argv arrays without a shell:
|
|
44
|
+
|
|
45
|
+
```yaml
|
|
46
|
+
runner:
|
|
47
|
+
type: external-cli
|
|
48
|
+
command: node
|
|
49
|
+
args: ["./scripts/local-reviewer.mjs"]
|
|
50
|
+
promptDelivery: stdin
|
|
51
|
+
async: true
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
External CLI runners support status artifacts, stdout/stderr logs, timeout, and stop. Full stdout and stderr are written to log files, while the in-memory final stdout response and stderr error are limited to their last 64 KiB. Foreground/clarify, steer/resume/interrupt-as-pause, Pi models/tools/extensions, skills, structured output, nested subagents, and fallback models are intentionally unsupported.
|
|
55
|
+
|
|
41
56
|
## What happens
|
|
42
57
|
|
|
43
58
|
Pi is the parent session. A subagent is a focused child Pi session with its own job.
|
|
@@ -78,7 +93,7 @@ Run a review loop on this change until reviewers stop finding fixes worth doing,
|
|
|
78
93
|
Use scout to understand the auth flow, then have planner turn that into an implementation plan.
|
|
79
94
|
```
|
|
80
95
|
|
|
81
|
-
Those are ordinary Pi requests. Pi decides whether to call `subagent`, which agent to use, and
|
|
96
|
+
Those are ordinary Pi requests. Pi decides whether to call `subagent`, which agent to use, and how to express composed work with `workflowScript`.
|
|
82
97
|
|
|
83
98
|
## Common workflows
|
|
84
99
|
|
|
@@ -342,11 +357,43 @@ To keep subagents inside a budget or compliance profile, enforce a model scope.
|
|
|
342
357
|
|
|
343
358
|
Foreground runs stream progress in the conversation while they run. They default to a generous 30-minute wall-clock timeout when neither the call nor the selected agent provides a timeout; explicit `timeoutMs`/`maxRuntimeMs` and agent defaults win.
|
|
344
359
|
|
|
345
|
-
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: "..." })`. In the TUI, a persistent FleetView below the editor
|
|
360
|
+
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: "..." })`. In the TUI, a persistent FleetView below the editor keeps active work visible as a compact summary. Set `fleetViewPlacement` to `"aboveEditor"` to move it above the editor. When the focused editor is empty, press `↓` or `←` to expand the summary into `main` plus active children with task, elapsed time, and token totals; then use `↑`/`↓` or `j`/`k` to select a child and `Enter` to inspect it. Printable navigation keys are never intercepted before activation.
|
|
346
361
|
|
|
347
362
|
`/subagents-fleet` opens the live fleet inspector with current-session foreground work, recent async children, structured Markdown/tool transcripts, and completed output/session paths. Use `↑`/`↓` or `j`/`k` to select a child, `Shift+K`/`Shift+J` to scroll one line, `PgUp`/`PgDn` to scroll one page, `x`/`Ctrl+O` to toggle tool details, `r` to refresh, and `Esc` to close. For a selected live async child, `s` sends an acknowledged steer message and `D` stops its top-level async run after confirmation. `Ctrl+Alt+F` opens the same inspector even while a foreground turn is active and slash input is queued. Without a TUI, `/subagents-fleet` retains the textual `subagent({ action: "status", view: "fleet" })` fallback, and mutations use explicit commands: run `/subagents-stop` and pick from the selector, or use `/subagents-stop <run-id>` / `subagent({ action: "stop", id: "..." })` when you already know the id. Use `/subagents-detach [run-id]` only for an active foreground single-subagent run you want to leave running without terminating; the eventual result remains available through status/wait. To inspect one background child in text, use `subagent({ action: "status", id: "...", view: "transcript" })`; add `index` for a specific child in a parallel or chain run.
|
|
348
363
|
|
|
349
|
-
FleetView replaces the legacy above-editor async widget by default, while
|
|
364
|
+
FleetView replaces the legacy above-editor async widget by default. Successful background completions stay quiet so inactive Pi tabs are not marked unread, while failed or paused completions still notify the originating session. Parallel runs show every active child independently. Chains with parallel groups keep their grouped shape in progress and results, so failed or paused agents stay visible next to completed ones. When a child is explicitly allowed to fan out with `tools: subagent`, its nested runs appear under that parent child in the main status tree instead of being hidden inside the child process.
|
|
365
|
+
|
|
366
|
+
When Pi runs inside [Herdr](https://herdr.dev), pi-subagents automatically reports active async-run counts through Herdr pane metadata. The bridge is enabled only when Herdr supplies `HERDR_ENV=1` and `HERDR_PANE_ID`; outside Herdr it registers no listeners or timers. It restores current-session active runs after `/reload` or `/resume`, refreshes metadata while work is active, and clears it on completion or shutdown. To show the reported label in the expanded Agent sidebar, include `state_text` or `$summary` in its row layout, for example:
|
|
367
|
+
|
|
368
|
+
```toml
|
|
369
|
+
[ui.sidebar.agents]
|
|
370
|
+
rows = [
|
|
371
|
+
["state_icon", "workspace", "tab"],
|
|
372
|
+
["agent", "state_text"],
|
|
373
|
+
]
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
The bridge uses Herdr's existing `herdr:blocked` sibling event when an async child needs attention. It also emits `herdr:busy` while async work remains. Herdr versions that support that sibling event keep the pane's semantic state `working`; older versions ignore it safely and still display the metadata label while the Pi integration remains the lifecycle authority.
|
|
377
|
+
|
|
378
|
+
Herdr 0.7.5+ can also open an on-demand inspector for an existing async run:
|
|
379
|
+
|
|
380
|
+
```ts
|
|
381
|
+
subagent({ action: "inspector.open", id: "<run-id>", index: 0, focus: true })
|
|
382
|
+
subagent({ action: "inspector.status", id: "<run-id>", index: 0 })
|
|
383
|
+
subagent({ action: "inspector.close", id: "<run-id>", index: 0 })
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
The inspector is a raw dashboard pane, not the child process and not a literal attach. It reads lifecycle/status/output/mission artifacts and sends `steer` or `stop` through pi-subagents' existing control inbox. Closing it never stops the run. Herdr remains optional, ordinary launches stay headless, and missing/older Herdr versions affect only Herdr-specific inspector and project-pane actions. FleetView opens the selected active async child with `H`. Use `focus` only with `inspector.open`; Herdr 0.7.5 cannot focus an arbitrary existing raw pane id.
|
|
387
|
+
|
|
388
|
+
For substantial work in another codebase, Herdr 0.7.5+ can open a project-owned Pi pane rooted in that repository:
|
|
389
|
+
|
|
390
|
+
```ts
|
|
391
|
+
subagent({ action: "project.open", cwd: "/path/to/repo", message: "Own the auth refresh mission for this project." })
|
|
392
|
+
subagent({ action: "project.status", cwd: "/path/to/repo" })
|
|
393
|
+
subagent({ action: "project.close", cwd: "/path/to/repo" })
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
A project pane runs its own Pi session in the target directory, so subagents launched from that pane use that project's config, agents, skills, files, git state, and missions. The parent session keeps coordination authority; existing headless runs are not moved into the pane. Pane bindings live under `<projectRoot>/.pi-subagents/project-panes/herdr.json` and are only a local pointer to the Herdr pane.
|
|
350
397
|
|
|
351
398
|
You can also ask naturally:
|
|
352
399
|
|
|
@@ -358,11 +405,11 @@ Lifecycle artifact v3 adds `process-terminal-candidate.json` (private runner evi
|
|
|
358
405
|
|
|
359
406
|
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.
|
|
360
407
|
|
|
361
|
-
Foreground and async runners share bounded child-protocol handling. A child JSONL line above
|
|
408
|
+
Foreground and async runners share bounded child-protocol handling. A child JSONL line above 16 MiB fails with structured `protocolError` code `protocol_output_limit`; oversized Pi `turn_end` and `agent_end` aggregates are the exception because they duplicate granular events, so runners replace them with bounded lifecycle records while preserving `agent_end.willRetry`. Stderr retains only its latest 128 KiB, split UTF-8 and final unterminated JSON events remain valid, and `agent_end.willRetry` defers completion until the child settles. Current Pi builds use `agent_settled` as the terminal watermark; older builds retain the bounded terminal-message fallback.
|
|
362
409
|
|
|
363
|
-
The
|
|
410
|
+
The 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`, optional `launchResolvedExtensions`, optional `runtimeAcknowledgedExtensions`, and nested `children` when a child is allowed to launch subagents. `launchResolvedExtensions` is parent-resolved launch intent only: it reports opaque extension identifiers and whether ambient extensions were disabled, without exposing raw extension paths or claiming the child runtime acknowledged that those extensions loaded. Cooperating child extensions can acknowledge child-runtime registration by emitting `subagent:acknowledge-extension` on the child process `pi.events` bus with payload `{ id: string }`. Acknowledgement ids are self-declared opaque strings, must be non-empty, at most 128 characters, contain only `A-Z`, `a-z`, `0-9`, `.`, `_`, `:`, `@`, `+`, or `-`, and must not contain `/`, `\\`, or `..`. The reported `runtimeAcknowledgedExtensions` projection is `{ version: 1, source: "child-runtime", ids, omitted }`, deduplicates ids, keeps at most 32 ids, and counts additional valid unique ids in `omitted`. It is best-effort observability only: absence means no cooperating extension acknowledged, and presence means only that the extension registered in the child runtime, not that its tools, health checks, or features succeeded. Late acknowledgements after terminal serialization are ignored. `events.jsonl` records lifecycle transitions such as `subagent.run.started`, `subagent.step.started`, `subagent.step.completed`/`failed`/`paused`/`stopped`, control attention events, nested interrupt failures, and `subagent.run.completed`/`stopped`; 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.
|
|
364
411
|
|
|
365
|
-
Other Pi extensions can use the
|
|
412
|
+
Other Pi extensions can use the 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>`. The `ping` capability metadata also advertises `events.asyncComplete` for exact process-local completion correlation after RPC `spawn`. Structured delegation progress updates carry `runId` as soon as foreground execution allocates it, so a caller can retain the package-owned revival target even if its own tool turn is interrupted before the terminal response. Foreground `details.results[]` rows also include a numeric `index` that is unique within the run and stable across partial progress snapshots and the final result; use `(runId, index)` instead of row position to correlate single, counted parallel, and chain children.
|
|
366
413
|
|
|
367
414
|
```typescript
|
|
368
415
|
const requestId = crypto.randomUUID();
|
|
@@ -378,7 +425,7 @@ pi.events.emit("subagents:rpc:v1:request", {
|
|
|
378
425
|
});
|
|
379
426
|
```
|
|
380
427
|
|
|
381
|
-
The
|
|
428
|
+
The RPC methods are `ping`, `status`, `spawn`, `steer`, `interrupt`, `stop`, and `resume`. `status`, `steer`, `interrupt`, and `resume` reuse the normal package-owned actions. `ping.capabilities.launchResolvedExtensions` advertises the optional launch-resolved extension projection in status details. `ping.capabilities.runtimeAcknowledgedExtensions` advertises the optional child-runtime acknowledgement projection and event name. When `ping.capabilities.fleetStatus` is `{ version: 1 }`, successful `status` replies additionally include `data.fleet`: `{ version: 1, entries, totalActive, omitted }`. Entries are bounded, current-session public display records with an opaque reconciliation `key`, resolved `agent`, optional `role`, `model`, `effort`, caller-facing `goal`, safe `startedAt`, and `{ input, output, total }` tokens. `totalActive` and `omitted` preserve overflow information beyond the bounded entry window. The DTO intentionally never exposes run, async, or tool IDs; clients must ignore unknown fields and fall back to status text when the capability is absent. `steer` requires an async run `id` (plus optional child `index`) and a non-empty `message`; its reply preserves the normal acknowledged-delivery result. RPC steering disables the direct tool's pause-and-revive recovery so an extension keeps authority over the exact child it spawned; `ping.capabilities.nonRecoveringSteer` advertises this guarantee. `resume` requires a run target and non-empty `message`; it delegates to the existing revival path, which validates current-session ownership, persisted session/recovery metadata, stopped/live state, capability ceilings, and the exclusive session lease before returning the new async run details. Callers may request a `file-only` output path for the revived result without overriding its model, tools, or budgets. `ping.capabilities.resume` advertises this seam. `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, configured spawn caps, child-safety depth, artifacts, and async status all behave the same. `stop` targets current-session top-level async runs through the stop control channel and records a `stopped` lifecycle instead of reporting a timeout.
|
|
382
429
|
|
|
383
430
|
`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.
|
|
384
431
|
|
|
@@ -454,107 +501,50 @@ If messages do not show up, run:
|
|
|
454
501
|
|
|
455
502
|
For normal use, you do not need to configure anything. Advanced users can tune the bridge with `intercomBridge` in the configuration section below.
|
|
456
503
|
|
|
457
|
-
At this point, you know enough to use the plugin. The rest of this README is reference material for exact command syntax, custom agents,
|
|
458
|
-
|
|
459
|
-
## Optional pi-permission-system integration
|
|
460
|
-
|
|
461
|
-
[`@gotgenes/pi-permission-system`](https://github.com/gotgenes/pi-packages/tree/main/packages/pi-permission-system)
|
|
462
|
-
adds a second policy layer — `allow` / `ask` / `deny` — on top of
|
|
463
|
-
pi-subagents' visibility-based tool restrictions.
|
|
504
|
+
At this point, you know enough to use the plugin. The rest of this README is reference material for exact command syntax, custom agents, scripted workflows, and configuration.
|
|
464
505
|
|
|
465
|
-
|
|
506
|
+
## Native child tool permissions
|
|
466
507
|
|
|
467
|
-
|
|
468
|
-
|-------|-----------------|-----------------|
|
|
469
|
-
| Visibility | Which tools are registered before the session starts | pi-subagents (`tools:` frontmatter key) |
|
|
470
|
-
| Policy | Runtime allow/ask/deny decisions on every tool call, bash command, MCP operation | pi-permission-system (`permission:` frontmatter key) |
|
|
508
|
+
Native permissions are opt-in and apply only to Pi child runtimes. With no rules configured, every tool call passes through unchanged. Configure explicit non-bash rules globally in `~/.pi/agent/extensions/subagent/config.json`:
|
|
471
509
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
510
|
+
```json
|
|
511
|
+
{
|
|
512
|
+
"permissions": {
|
|
513
|
+
"rules": {
|
|
514
|
+
"read": "allow",
|
|
515
|
+
"write": "ask",
|
|
516
|
+
"edit": "deny"
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
476
520
|
```
|
|
477
521
|
|
|
478
|
-
|
|
479
|
-
extensions are installed. pi-subagents passes the parent session identity
|
|
480
|
-
to child processes via the `PI_SUBAGENT_PARENT_SESSION` environment variable,
|
|
481
|
-
which the permission system uses to forward `ask` prompts from headless
|
|
482
|
-
subagent processes back to the parent session's UI.
|
|
483
|
-
|
|
484
|
-
### Per-agent permission frontmatter
|
|
485
|
-
|
|
486
|
-
Agent files can include a `permission:` block alongside the standard `tools:`
|
|
487
|
-
key. The permission system reads it independently:
|
|
522
|
+
Custom agents can override matching global rules with a `permission:` or `permissions:` frontmatter block:
|
|
488
523
|
|
|
489
524
|
```yaml
|
|
490
525
|
---
|
|
491
526
|
name: worker
|
|
492
|
-
tools: bash,read,write,edit
|
|
493
527
|
permission:
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
bash:
|
|
497
|
-
"*": ask
|
|
498
|
-
"git *": allow
|
|
499
|
-
"npm test": allow
|
|
528
|
+
write: allow
|
|
529
|
+
edit: ask
|
|
500
530
|
---
|
|
501
531
|
```
|
|
502
532
|
|
|
503
|
-
|
|
504
|
-
and the permission system then applies `ask`/`allow` policy within that
|
|
505
|
-
visible set. Both keys coexist without collision.
|
|
533
|
+
Rules support `allow`, `ask`, and `deny`. Agent rules override matching global rules; omitted and unknown tools default to `allow`. Explicit `allow` removes an inherited restriction. The gate is not registered when the resolved policy has no `ask` or `deny` rules.
|
|
506
534
|
|
|
507
|
-
|
|
535
|
+
An explicit `ask` pauses that exact tool call and sends a bounded, redacted preview to a one-call permission arbiter owned by the built-in child watchdog. The arbiter uses the configured child-watchdog model and returns only `approve` or `deny`; it does not notify the parent agent. Enable and configure `subagents.watchdog.children` before using `ask` rules. A disabled watchdog, missing model/auth, timeout, malformed response, or runtime error denies the call with a clear error.
|
|
508
536
|
|
|
509
|
-
|
|
510
|
-
If `ask` prompts from children are not reaching the parent UI, verify both
|
|
511
|
-
extensions are installed:
|
|
537
|
+
Asked requests and decisions are written to bounded audit JSONL, including `decisionSource: "watchdog"` and bounded failure reasons. Ordinary direction and clarification through `contact_supervisor` or the optional `pi-intercom` extension remain separate and are never permission-gated.
|
|
512
538
|
|
|
513
|
-
|
|
514
|
-
pi list
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
### How it works
|
|
539
|
+
`bash` is always passed through by pi-subagents. Bash rules are rejected rather than parsed, gated, denied, or audited. Install and configure `pi-guard` when command-level bash policy is needed.
|
|
518
540
|
|
|
519
|
-
|
|
520
|
-
`PI_SUBAGENT_PARENT_SESSION`. When pi-subagents launches a child, it passes the
|
|
521
|
-
launching session's identity to that child explicitly, falling back to the
|
|
522
|
-
inherited environment variable. When the permission system inside a child
|
|
523
|
-
encounters an `ask` permission, it reads this variable to locate the parent
|
|
524
|
-
session and forwards the confirmation request there.
|
|
541
|
+
A pi-subagents child is headless, so a pi-guard rule that resolves to `ask` cannot request approval from the parent Pi UI. Native permissions do not forward pi-guard decisions; they only apply to the separate non-bash child permission gate. For child-specific policy, use `PI_GUARD` through a `PI_SUBAGENT_PI_BINARY` wrapper or an equivalent launch wrapper, and configure explicit `allow` or `deny` rules. An `allow` rule grants execution; it is not approval forwarding, so retain explicit denies for commands the child must not run.
|
|
525
542
|
|
|
526
|
-
|
|
527
|
-
interactive session — i.e. for the direct children of the root session. A
|
|
528
|
-
nested child's parent is itself a headless subagent process with no UI to
|
|
529
|
-
surface the prompt, so `ask` policies are best placed on agents that run as
|
|
530
|
-
direct children of the interactive session.
|
|
543
|
+
External CLI profiles are opaque processes, so native permissions cannot intercept their tools. A launch with effective `ask` or `deny` rules is rejected for an external CLI agent instead of claiming enforcement.
|
|
531
544
|
|
|
532
545
|
## Direct commands
|
|
533
546
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
| Command | Description |
|
|
537
|
-
|---------|-------------|
|
|
538
|
-
| `/run <agent> [task]` | Run one agent; omit the task for self-contained agents |
|
|
539
|
-
| `/chain agent1 "task1" -> agent2 "task2"` | Run agents in sequence |
|
|
540
|
-
| `/chain scout "scan" -> (reviewer "A" \| reviewer "B") -> writer "fix"` | Run a chain with a static parallel group inline |
|
|
541
|
-
| `/parallel agent1 "task1" -> agent2 "task2"` | Run agents in parallel |
|
|
542
|
-
| `/run-chain <chainName> -- <task>` | Launch a saved `.chain.md` or `.chain.json` workflow |
|
|
543
|
-
| `/subagent-cost` | Show parent plus child subagent token usage and cost for this session |
|
|
544
|
-
| `/subagents [agent] [model\|thinking\|prompt\|details]` | Interactively inspect or edit an agent's model, thinking level, or system prompt |
|
|
545
|
-
| `/subagents-doctor` | Show read-only setup diagnostics |
|
|
546
|
-
| `/subagents-detach [run-id]` | Detach an active foreground single-subagent run without terminating its child |
|
|
547
|
-
| `/subagents-models [agent]` | Show the runtime-loaded builtin model mapping, optionally filtered to one builtin |
|
|
548
|
-
| `/subagents-watchdog [status|on|off|recommend-model|model ...|session model ...|check]` | Show or configure the opt-in watchdog; use a strong complementary model such as Opus 4.8 high or GPT 5.5 high |
|
|
549
|
-
| `/subagents-profiles` | List saved subagent profiles from `~/.pi/agent/profiles/pi-subagents/` |
|
|
550
|
-
| `/subagents-load-profile <name>` | Replace only `settings.subagents` with a saved profile and optionally switch this session to the profile worker model |
|
|
551
|
-
| `/subagents-refresh-provider-models <provider> [--force]` | Create or refresh the cached provider model catalog |
|
|
552
|
-
| `/subagents-generate-profiles <provider>` | Generate `<provider>.quota.json` and `<provider>.quality.json` profiles |
|
|
553
|
-
| `/subagents-check-profile <name>` | Check a saved profile against the current registry and live model probes |
|
|
554
|
-
|
|
555
|
-
Commands validate agent names locally, support tab completion, and send results back into the conversation.
|
|
556
|
-
|
|
557
|
-
`/subagents` opens a compact administration flow for builtin, package, user, and project agents. Model choices refresh Pi's model registry first, thinking choices are filtered to levels declared by the selected model, and prompt editing uses Pi's native multiline editor; press Ctrl+G to open the configured external editor. Full metadata is opt-in through `details`. Edits are persisted to the field-owning layer: explicit custom-agent frontmatter remains in the agent file, while settings/profile-managed fields remain in `settings.subagents.agentOverrides`. Package-owned fields and definitions loaded through `PI_SUBAGENT_EXTRA_AGENT_DIRS` stay read-only; settings can still supply model or thinking fields omitted by a package definition.
|
|
547
|
+
Use `/run <agent> [task] [--bg] [--fork]` for one child. Multi-agent orchestration is expressed through `workflowScript` in the `subagent` tool; the legacy `/chain`, `/parallel`, and `/run-chain` commands are not registered.
|
|
558
548
|
|
|
559
549
|
### Profiles and provider model catalogs
|
|
560
550
|
|
|
@@ -582,132 +572,24 @@ Use the profile workflow like this:
|
|
|
582
572
|
|
|
583
573
|
`/subagents-generate-profiles` uses the provider catalog to produce quota and quality profiles. `/subagents-check-profile` re-checks each assigned model in a saved profile against the current registry and a live probe so you can detect model removals, auth problems, or stale assignments.
|
|
584
574
|
|
|
585
|
-
###
|
|
586
|
-
|
|
587
|
-
Use `->` to separate steps and give each step its own task:
|
|
588
|
-
|
|
589
|
-
```text
|
|
590
|
-
/chain scout "scan the codebase" -> planner "create an implementation plan"
|
|
591
|
-
/parallel scanner "find security issues" -> reviewer "check code style"
|
|
592
|
-
```
|
|
593
|
-
|
|
594
|
-
Both double and single quotes work. You can also use `--` as a delimiter:
|
|
595
|
-
|
|
596
|
-
```text
|
|
597
|
-
/chain scout -- scan code -> planner -- analyze auth
|
|
598
|
-
```
|
|
599
|
-
|
|
600
|
-
Steps without a task inherit behavior from the execution mode. Chain steps get `{previous}`, the prior step’s output. Parallel steps use the first available task as a fallback.
|
|
601
|
-
|
|
602
|
-
### Inline parallel groups in `/chain`
|
|
603
|
-
|
|
604
|
-
Wrap a group of agents in parentheses and separate them with `|` to fan them out within a single chain step. The group runs all of its tasks concurrently, then the next `->` step continues once they finish:
|
|
605
|
-
|
|
606
|
-
```text
|
|
607
|
-
/chain scout "scan" -> (reviewer "review A" | reviewer "review B") -> writer "fix"
|
|
608
|
-
```
|
|
609
|
-
|
|
610
|
-
Notes:
|
|
611
|
-
|
|
612
|
-
- Groups must contain at least two tasks separated by ` | `, each with its own task.
|
|
613
|
-
- Group syntax is only valid between ` -> ` separators, and the group must appear as a complete step.
|
|
614
|
-
- Only a step that *opens* with `(` is a group. Parentheses inside a shared `--` task (e.g. `/chain scout -- inspect auth (backend)`) stay literal text and keep the legacy single-agent behavior.
|
|
615
|
-
- A group is treated as the prior step’s output for the next sequential step.
|
|
616
|
-
- Tab completion suggests agents inside groups — after `(`, after `|`, and on each new `->` step.
|
|
617
|
-
|
|
618
|
-
Add a `[...]` suffix right after the closing `)` to set step-level options on the group:
|
|
575
|
+
### WorkflowScript replacements
|
|
619
576
|
|
|
620
|
-
|
|
621
|
-
/chain scout "scan" -> (reviewer "A" | reviewer "B")[concurrency=2,failFast,worktree] -> writer "fix"
|
|
622
|
-
```
|
|
623
|
-
|
|
624
|
-
| Group option | Description |
|
|
625
|
-
|--------------|-------------|
|
|
626
|
-
| `concurrency=N` | Max tasks running at once within the group. |
|
|
627
|
-
| `failFast` | Stop the group as soon as one task fails. |
|
|
628
|
-
| `worktree` | Run each group task in its own git worktree. |
|
|
629
|
-
|
|
630
|
-
Dynamic fanout (`expand` / `collect`) is intentionally not available inline — use the
|
|
631
|
-
`subagent({ chain: [...] })` tool API or a saved `.chain.json` for data-driven fan-out.
|
|
632
|
-
|
|
633
|
-
```text
|
|
634
|
-
/chain scout "analyze auth" -> planner -> worker
|
|
635
|
-
# scout gets "analyze auth"; planner gets scout output; worker gets planner output
|
|
636
|
-
```
|
|
637
|
-
|
|
638
|
-
For a shared task, list agents and place one `--` before the task:
|
|
639
|
-
|
|
640
|
-
```text
|
|
641
|
-
/chain scout planner -- analyze the auth system
|
|
642
|
-
/parallel scout reviewer -- check for security issues
|
|
643
|
-
```
|
|
644
|
-
|
|
645
|
-
### Inline per-step config
|
|
646
|
-
|
|
647
|
-
Append `[key=value,...]` to an agent name to override defaults. `/chain` applies every key below; `/run` and `/parallel` use the execution-behavior keys (`output`, `outputMode`, `reads`, `model`, `skills`, `progress`) and ignore chain-only metadata such as `as`, `label`, `phase`, `count`, `outputSchema`, and `acceptance`.
|
|
648
|
-
|
|
649
|
-
```text
|
|
650
|
-
/chain scout[output=context.md] "scan code" -> planner[reads=context.md] "analyze auth"
|
|
651
|
-
/run scout[model=anthropic/claude-sonnet-4] summarize this codebase
|
|
652
|
-
/parallel reviewer[skills=code-review+security] "review backend" -> reviewer[model=openai/gpt-5-mini] "review frontend"
|
|
653
|
-
```
|
|
654
|
-
|
|
655
|
-
| Key | Example | Description |
|
|
656
|
-
|-----|---------|-------------|
|
|
657
|
-
| `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. |
|
|
658
|
-
| `outputMode` | `outputMode=file-only` | Return only a concise file reference for saved output instead of the full saved content. Requires `output`; default is `inline`. |
|
|
659
|
-
| `reads` | `reads=a.md+b.md` | Read files before executing. `+` separates multiple paths. |
|
|
660
|
-
| `model` | `model=anthropic/claude-sonnet-4` | Override model for this step. |
|
|
661
|
-
| `skills` | `skills=planning+review` | Override available skills. `+` separates multiple skills. |
|
|
662
|
-
| `progress` | `progress` | Enable progress tracking. |
|
|
663
|
-
| `as` | `as=context` | Name this step’s output so later steps can reference it. |
|
|
664
|
-
| `label` | `label=Recon` | Human-readable label for the step. |
|
|
665
|
-
| `phase` | `phase=analysis` | Group steps into a named phase. |
|
|
666
|
-
| `cwd` | `cwd=packages/api` | Run the step in a subdirectory. |
|
|
667
|
-
| `count` | `count=3` | Fan a group task into N copies (only inside a `( ... )` group). |
|
|
668
|
-
| `outputSchema` | `outputSchema=schema.json` | Validate structured output against a JSON Schema file (path resolved against the session cwd, not an inline step `cwd`). |
|
|
669
|
-
| `acceptance` | `acceptance=checked` | Inline evidence level: `auto`, `attested`, or `checked`. Use the tool API or saved `.chain.json` for object contracts such as `none`, `verified`, or an orthogonal review requirement. `reviewed` is an achieved status, not an input level. |
|
|
670
|
-
|
|
671
|
-
Set `output=false`, `reads=false`, or `skills=false` to disable that behavior explicitly. Do not use `output=false` for file-only returns; use `outputMode=file-only` with an `output` path.
|
|
672
|
-
|
|
673
|
-
Inline `[...]` values must not contain spaces or commas — keep `label`/`phase` to single tokens.
|
|
674
|
-
|
|
675
|
-
### Background and forked runs
|
|
676
|
-
|
|
677
|
-
Add `--bg` to run in the background:
|
|
678
|
-
|
|
679
|
-
```text
|
|
680
|
-
/run scout "audit the codebase" --bg
|
|
681
|
-
/chain scout "analyze auth" -> planner "design refactor" -> worker --bg
|
|
682
|
-
/parallel scout "scan frontend" -> scout "scan backend" --bg
|
|
683
|
-
```
|
|
684
|
-
|
|
685
|
-
Add `--fork` to start each child from a real branched session created from the parent’s current leaf:
|
|
686
|
-
|
|
687
|
-
```text
|
|
688
|
-
/run reviewer "review this diff" --fork
|
|
689
|
-
/chain scout "analyze this branch" -> planner "plan next steps" --fork
|
|
690
|
-
/parallel scout "audit frontend" -> reviewer "audit backend" --fork
|
|
691
|
-
```
|
|
577
|
+
Use stable keys and ordinary JavaScript for sequence and parallelism. For watched same-repo workflows, pass `async:false` to show the live in-chat workflow card; `chatProgress` can force `off`, `terminal`, `milestones`, or `live-card` when the automatic policy is not what you want.
|
|
692
578
|
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
579
|
+
```js
|
|
580
|
+
subagent({ workflowScript: `
|
|
581
|
+
const scan = await runs.run("scan", { agent: "scout", task: "Scan the codebase" });
|
|
582
|
+
const reviews = await runs.all([
|
|
583
|
+
{ key: "correctness", agent: "reviewer", task: "Review correctness: " + scan.output },
|
|
584
|
+
{ key: "tests", agent: "reviewer", task: "Review tests: " + scan.output }
|
|
585
|
+
]);
|
|
586
|
+
return reviews.map(result => result.output);
|
|
587
|
+
` });
|
|
698
588
|
```
|
|
699
589
|
|
|
700
|
-
Background runs are detached. If the parent agent has other independent work, it should keep working. In an interactive chat, it should normally return control when ready to yield and let Pi deliver the completion notification instead of blocking merely to wait. Override that default and use `subagent_wait` when the current request is run-to-completion — for example, the user asked you to report results back before continuing or a skill cannot return before its work finishes. In a non-interactive run, Pi auto-drains current-session work at `agent_end`; use `subagent_wait` when this turn must receive results before it ends. It returns when the next initially active run or registered provider item finishes or a subagent needs attention; use `subagent_wait({ all: true })` for all work active at call time, `subagent_wait({ id })` for one async or remembered detached foreground run, and `subagent_wait({ timeoutMs })` to cap the block.
|
|
701
|
-
|
|
702
|
-
A foreground child can detach while it waits for a supervisor reply. Reply first, then call `subagent_wait({ id: runId })`. While that wait blocks, it streams the detached child's current tool and recent transcript activity into the pending tool row when transcript artifacts are available. The remembered run stays pending until the child exits, then emits a session-scoped completion notification with recovered output and remains inspectable through `subagent({ action: "status", id: runId })`. Do not call `resume` or launch a replacement while the child remains detached.
|
|
703
|
-
|
|
704
|
-
Headless sessions also auto-drain current-session subagent and registered provider work at `agent_end`, using one absolute timeout and continuing through attention states. This is a final lifecycle safeguard rather than a replacement for explicit orchestration: `subagent_wait` still lets a model react to each result during the turn. Provider, reconciliation, timeout, and malformed-state failures remain visible errors instead of being treated as successful drains.
|
|
705
|
-
|
|
706
|
-
The `oracle`/`advisor` and `worker` builtins are designed for an explicit decision loop. A typical pattern is to ask `oracle` or its `advisor` alias for diagnosis and a recommended execution prompt, then only run `worker` after the main agent approves that direction.
|
|
707
|
-
|
|
708
590
|
## Clarify and launch UI
|
|
709
591
|
|
|
710
|
-
Tool calls
|
|
592
|
+
Tool calls start background work by default. Set `async: false` when the current turn needs a foreground result, or `clarify: true` on single, parallel, or chain runs when you want to preview and edit the workflow before it runs; clarify stays foreground.
|
|
711
593
|
|
|
712
594
|
Common clarify keys:
|
|
713
595
|
|
|
@@ -724,7 +606,7 @@ Common clarify keys:
|
|
|
724
606
|
- `p` toggles progress tracking where supported
|
|
725
607
|
Picker screens use `↑↓`, `Enter`, `Esc`, and type-to-filter. The full-screen editor supports word wrapping, paste, `Esc` to save, and `Ctrl+C` to discard.
|
|
726
608
|
|
|
727
|
-
## Agents
|
|
609
|
+
## Agents
|
|
728
610
|
|
|
729
611
|
Agents are markdown files with YAML frontmatter and a system prompt body. They define the specialist that will run in the child Pi process.
|
|
730
612
|
|
|
@@ -846,7 +728,7 @@ Important fields:
|
|
|
846
728
|
| Field | Notes |
|
|
847
729
|
|-------|-------|
|
|
848
730
|
| `package` | Optional package identifier. A file with `name: scout` and `package: code-analysis` registers as `code-analysis.scout`; serialization keeps `name` and `package` separate. |
|
|
849
|
-
| `aliases` | Optional comma-separated or block-list names that resolve to this agent for selection and explicit `agent
|
|
731
|
+
| `aliases` | Optional comma-separated or block-list names that resolve to this agent for selection and explicit `agent` and task inputs. Runtime status, persistence, and config still use the canonical `name`; exact canonical names take precedence over aliases, and alias collisions between distinct canonical agents fail as ambiguous. |
|
|
850
732
|
| `tools` | Strict child tool allowlist. Named extension tools must also have their provider loaded. `mcp:` entries select direct MCP tools when `pi-mcp-adapter` is installed. |
|
|
851
733
|
| `extensions` | Omitted means normal extensions; empty means no extensions; list values allowlist specific extensions. |
|
|
852
734
|
| `subagentOnlyExtensions` | Extension paths loaded only in spawned child sessions for this agent. Tools registered there are unavailable to the main agent unless also installed through normal Pi extension configuration. |
|
|
@@ -860,7 +742,7 @@ Important fields:
|
|
|
860
742
|
| `skills` | Selects specific skills for the child, regardless of `inheritSkills`. |
|
|
861
743
|
| `skillPath` | Invocation-private skill files or discovery directories. Relative paths resolve from the agent definition file. Local matches take precedence, while unresolved or unreadable matches fall back to normal skill discovery. This field discovers candidates only; `skills` still selects what the child receives. |
|
|
862
744
|
| `output` | Default single-agent output file. |
|
|
863
|
-
| `defaultReads` | Files to read before running
|
|
745
|
+
| `defaultReads` | Files to read before running the agent. |
|
|
864
746
|
| `defaultProgress` | Maintain `progress.md`. |
|
|
865
747
|
| `async` | Default a single-agent launch to background (`true`) or foreground (`false`) when the call omits `async`. Explicit call values and `forceTopLevelAsync` win. |
|
|
866
748
|
| `timeoutMs` | Positive integer default runtime deadline in milliseconds for single-agent launches. Foreground launches use 30 minutes when neither the call nor agent provides a timeout; explicit `timeoutMs`/`maxRuntimeMs` and agent defaults win. |
|
|
@@ -868,7 +750,7 @@ Important fields:
|
|
|
868
750
|
| `acceptance` | Acceptance default for single-agent launches. Use a scalar level such as `checked` or an inline/block YAML map such as `{ level: "none", reason: "lightweight lookup" }`. Explicit call values win; chain and parallel acceptance remains task/step configuration. |
|
|
869
751
|
| `acceptanceRole` | Optional `read-only` or `writer` role for automatic acceptance inference. Explicit task mutation or no-edit intent wins; otherwise the declared role replaces agent-name guessing. This does not grant or revoke tools. |
|
|
870
752
|
| `completionGuard` | Set `false` only for non-implementation agents that may mention implementation words while using mutation-capable tools such as `bash`. |
|
|
871
|
-
| `interactive` | Parsed for compatibility but not enforced
|
|
753
|
+
| `interactive` | Parsed for compatibility but not currently enforced. |
|
|
872
754
|
| `maxSubagentDepth` | Tightens nested delegation for this agent's children. |
|
|
873
755
|
| `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. |
|
|
874
756
|
|
|
@@ -922,114 +804,6 @@ To apply the same `extensions` allowlist to every agent that does not declare it
|
|
|
922
804
|
|
|
923
805
|
Before the first model turn, the child runtime compares every explicit tool name with Pi's final filtered registry. A missing provider now fails the run with the unavailable names and concrete `subagentOnlyExtensions`/`extensions` guidance instead of letting a direct or chained child silently continue without its requested tools.
|
|
924
806
|
|
|
925
|
-
## Chain files
|
|
926
|
-
|
|
927
|
-
Chains are reusable workflows stored separately from agent files. Use `.chain.md` for simple sequential saved chains. Use `.chain.json` when a chain needs dynamic fanout.
|
|
928
|
-
|
|
929
|
-
| Scope | Path |
|
|
930
|
-
|-------|------|
|
|
931
|
-
| Installed package | `package.json` `pi-subagents.chains` or `pi.subagents.chains` |
|
|
932
|
-
| User | `~/.pi/agent/chains/**/*.chain.md`, `~/.pi/agent/chains/**/*.chain.json` |
|
|
933
|
-
| Project | Project config `chains/**/*.chain.md`, `chains/**/*.chain.json` (`.pi/chains/...` in standard Pi) |
|
|
934
|
-
|
|
935
|
-
Nested subdirectories are discovered recursively. Installed Pi packages can expose chain directories from either `{"pi-subagents":{"chains":["./chains"]}}` or `{"pi":{"subagents":{"chains":["./chains"]}}}` in their package manifest. Package chains load below user/project chains. If both `.chain.md` and `.chain.json` define the same parsed runtime chain name in the same scope, `.chain.json` wins. If user and project scopes define the same parsed runtime chain name, the project chain wins. Chains support the same optional `package` frontmatter as agents; `name: review-flow` plus `package: code-analysis` runs as `code-analysis.review-flow`.
|
|
936
|
-
|
|
937
|
-
Example:
|
|
938
|
-
|
|
939
|
-
```md
|
|
940
|
-
---
|
|
941
|
-
name: scout-planner
|
|
942
|
-
description: Gather context then plan implementation
|
|
943
|
-
---
|
|
944
|
-
|
|
945
|
-
## scout
|
|
946
|
-
phase: Context
|
|
947
|
-
label: Map auth flow
|
|
948
|
-
as: context
|
|
949
|
-
output: context.md
|
|
950
|
-
|
|
951
|
-
Analyze the codebase for {task}
|
|
952
|
-
|
|
953
|
-
## planner
|
|
954
|
-
phase: Planning
|
|
955
|
-
label: Implementation plan
|
|
956
|
-
reads: context.md
|
|
957
|
-
model: anthropic/claude-sonnet-4-5:high
|
|
958
|
-
progress: true
|
|
959
|
-
|
|
960
|
-
Create an implementation plan based on {outputs.context}
|
|
961
|
-
```
|
|
962
|
-
|
|
963
|
-
Each `.chain.md` `## agent-name` section is a step. Config lines such as `phase`, `label`, `as`, `outputSchema`, `output`, `outputMode`, `reads`, `model`, `skills`, and `progress` go immediately after the header. A blank line separates config from task text. In saved `.chain.md` files, `outputSchema` is a path to a JSON Schema file; direct tool calls and `.chain.json` files can pass the schema object inline.
|
|
964
|
-
|
|
965
|
-
For `output`, `reads`, `skills`, and `progress`, chain behavior is three-state: omitted inherits from the agent, a value overrides, and `false` disables.
|
|
966
|
-
|
|
967
|
-
Use `phase` to group related work in status output, `label` for a readable step name, and `as` to store a successful step or parallel task result for later `{outputs.name}` references. Duplicate `as` names, invalid identifiers, and unknown output references fail before child execution.
|
|
968
|
-
|
|
969
|
-
Dynamic fanout is available only through direct `subagent({ chain: [...] })` JSON or saved `.chain.json` files. It expands an array from a prior structured named output, runs one child template per item, and stores the ordered collection under `collect.as`. The source must be structured output; prose is never parsed. `expand.maxItems` is required, over-limit arrays fail, nested fanout and arbitrary expressions are not supported, and `.chain.md` has no dynamic syntax in this release.
|
|
970
|
-
|
|
971
|
-
```json
|
|
972
|
-
{
|
|
973
|
-
"name": "dynamic-review",
|
|
974
|
-
"description": "Find review targets, fan out reviewers, then synthesize.",
|
|
975
|
-
"chain": [
|
|
976
|
-
{
|
|
977
|
-
"agent": "scout",
|
|
978
|
-
"task": "Return {\"items\":[{\"path\":\"...\",\"reason\":\"...\"}]} via structured_output.",
|
|
979
|
-
"as": "targets",
|
|
980
|
-
"outputSchema": { "type": "object" }
|
|
981
|
-
},
|
|
982
|
-
{
|
|
983
|
-
"expand": {
|
|
984
|
-
"from": { "output": "targets", "path": "/items" },
|
|
985
|
-
"item": "target",
|
|
986
|
-
"key": "/path",
|
|
987
|
-
"maxItems": 12
|
|
988
|
-
},
|
|
989
|
-
"parallel": {
|
|
990
|
-
"agent": "reviewer",
|
|
991
|
-
"label": "Review {target.path}",
|
|
992
|
-
"task": "Review {target.path}. Reason: {target.reason}",
|
|
993
|
-
"outputSchema": { "type": "object" }
|
|
994
|
-
},
|
|
995
|
-
"collect": { "as": "reviews" },
|
|
996
|
-
"concurrency": 4
|
|
997
|
-
},
|
|
998
|
-
{
|
|
999
|
-
"agent": "worker",
|
|
1000
|
-
"task": "Synthesize fixes from {outputs.reviews}"
|
|
1001
|
-
}
|
|
1002
|
-
]
|
|
1003
|
-
}
|
|
1004
|
-
```
|
|
1005
|
-
|
|
1006
|
-
Create simple `.chain.md` chains by writing files directly or with the `subagent({ action: "create", config: ... })` management action. Create dynamic `.chain.json` chains by writing the JSON file directly. Run saved chains with natural language or:
|
|
1007
|
-
|
|
1008
|
-
```text
|
|
1009
|
-
/run-chain scout-planner -- refactor authentication
|
|
1010
|
-
```
|
|
1011
|
-
|
|
1012
|
-
## Chain variables
|
|
1013
|
-
|
|
1014
|
-
Task templates support:
|
|
1015
|
-
|
|
1016
|
-
| Variable | Description |
|
|
1017
|
-
|----------|-------------|
|
|
1018
|
-
| `{task}` | Original task from the first step. |
|
|
1019
|
-
| `{previous}` | Output from the prior step, or aggregated output from a parallel step. |
|
|
1020
|
-
| `{chain_dir}` | Path to the chain artifact directory. |
|
|
1021
|
-
| `{outputs.name}` | Text value from a prior step or completed parallel task with `as: "name"`. |
|
|
1022
|
-
|
|
1023
|
-
Parallel outputs are aggregated with clear separators before being passed to the next step:
|
|
1024
|
-
|
|
1025
|
-
```text
|
|
1026
|
-
=== Parallel Task 1 (worker) ===
|
|
1027
|
-
...
|
|
1028
|
-
|
|
1029
|
-
=== Parallel Task 2 (worker) ===
|
|
1030
|
-
...
|
|
1031
|
-
```
|
|
1032
|
-
|
|
1033
807
|
## Skills
|
|
1034
808
|
|
|
1035
809
|
Skills are `SKILL.md` files made available to an agent. The prompt includes skill metadata and the file location; the agent reads the full skill file only when the task matches.
|
|
@@ -1119,11 +893,14 @@ if (!result.ok) {
|
|
|
1119
893
|
console.log(result.contract.digest, result.contract.tools.effectiveAllowlist);
|
|
1120
894
|
```
|
|
1121
895
|
|
|
1122
|
-
Preflight covers ordinary single-agent launch resolution
|
|
896
|
+
Preflight covers ordinary single-agent launch resolution: selected agent identity and shadowed candidates, a parsed-definition digest (including system prompt and launch-affecting model, tool, skill, extension, output, and memory fields), fresh/fork context, effective model and thinking, skill and tool resolution, direct MCP selections, runtime/configured extensions, artifact/session paths, async lifecycle/status/result/event/process-terminal paths, package/lifecycle versions, capability-ceiling audit data, and stable digests. `launchContractDigest` is the canonical digest of the caller task, effective system prompt (including the resolved `turnBudget` prompt augmentation when supplied), model candidates, effective tools/extensions/MCP (including inherited capability ceilings), output binding, and structured-output schema that ordinary foreground and async execution report in results/status/events and metadata. Runtime acceptance prose and output-task annotations are intentionally excluded because side-effect-free preflight does not resolve those host/runtime augmentations; the launch and task digests make that boundary explicit. Raw prompts are not exposed in public contract output. It is side-effect-free for launch state: it does not create child sessions, temp prompt files, structured-output runtimes, tool-diagnostic files, or run artifacts. Some host-owned facts, such as exact fork snapshots, nested async roots, and live model registries, can only be proven by the Pi host; those appear as `host_required` diagnostics instead of silently pretending to be exact.
|
|
1123
897
|
|
|
1124
|
-
###
|
|
898
|
+
### Structured delegation API
|
|
1125
899
|
|
|
1126
|
-
|
|
900
|
+
Other Pi extensions can ask `pi-subagents` to run one configured foreground leaf
|
|
901
|
+
agent through the structured delegation API. It uses the established
|
|
902
|
+
`prompt-template:subagent:*` event family and the same executor as the
|
|
903
|
+
`subagent` tool; it does not add another launcher.
|
|
1127
904
|
|
|
1128
905
|
```ts
|
|
1129
906
|
import {
|
|
@@ -1134,51 +911,6 @@ import {
|
|
|
1134
911
|
} from "pi-subagents/delegation";
|
|
1135
912
|
|
|
1136
913
|
const request: SubagentDelegationRequest = {
|
|
1137
|
-
version: 1,
|
|
1138
|
-
requestId: crypto.randomUUID(),
|
|
1139
|
-
agent: "reviewer",
|
|
1140
|
-
task: "Review the supplied evidence.",
|
|
1141
|
-
context: "fresh",
|
|
1142
|
-
cwd: ctx.cwd,
|
|
1143
|
-
timeoutMs: 120_000,
|
|
1144
|
-
toolBudget: { soft: 10, hard: 16, block: "*" },
|
|
1145
|
-
};
|
|
1146
|
-
|
|
1147
|
-
const unsubscribe = pi.events.on(SUBAGENT_DELEGATION_RESPONSE_EVENT, (payload) => {
|
|
1148
|
-
const response = payload as SubagentDelegationResponse;
|
|
1149
|
-
if (response.requestId !== request.requestId) return;
|
|
1150
|
-
unsubscribe();
|
|
1151
|
-
// Inspect response.status and the metadata present for this run.
|
|
1152
|
-
});
|
|
1153
|
-
pi.events.emit(SUBAGENT_DELEGATION_REQUEST_EVENT, request);
|
|
1154
|
-
```
|
|
1155
|
-
|
|
1156
|
-
The contract uses the established `prompt-template:subagent:*` event transport and the same executor as the `subagent` tool; it does not add another launcher. New integrations must send `version: 1`. Requests are strict and single-agent only. They can set fresh or fork context, model, cwd, timeout, turn and tool-call budgets, skills, output behavior, acceptance, and artifact capture. Unknown or malformed fields return `invalid_request` before execution.
|
|
1157
|
-
|
|
1158
|
-
Responses distinguish completion, failure, timeout, cancellation, interruption,
|
|
1159
|
-
turn or tool-budget exhaustion, explicit acceptance failure, invalid requests,
|
|
1160
|
-
and unavailable active context. Optional metadata is omitted when unavailable.
|
|
1161
|
-
Request IDs must be unique while active; duplicate active IDs are ignored so the
|
|
1162
|
-
original request keeps ownership of its terminal response. Emit
|
|
1163
|
-
`SUBAGENT_DELEGATION_CANCEL_EVENT` with the same version and request ID to cancel
|
|
1164
|
-
queued or active work.
|
|
1165
|
-
|
|
1166
|
-
### Delegation v2
|
|
1167
|
-
|
|
1168
|
-
V2 is the owned-leaf contract for workflow supervisors. Independent requests
|
|
1169
|
-
can overlap through the delegated executor without weakening the ordinary
|
|
1170
|
-
model-facing tool's one-foreground-call-per-turn guard.
|
|
1171
|
-
|
|
1172
|
-
```ts
|
|
1173
|
-
import {
|
|
1174
|
-
SUBAGENT_DELEGATION_REQUEST_EVENT,
|
|
1175
|
-
SUBAGENT_DELEGATION_RESPONSE_EVENT,
|
|
1176
|
-
type SubagentDelegationV2Request,
|
|
1177
|
-
type SubagentDelegationV2Response,
|
|
1178
|
-
} from "pi-subagents/delegation";
|
|
1179
|
-
|
|
1180
|
-
const request: SubagentDelegationV2Request = {
|
|
1181
|
-
version: 2,
|
|
1182
914
|
requestId: crypto.randomUUID(),
|
|
1183
915
|
ownerRunId: workflowRunId,
|
|
1184
916
|
nodeId: "review-accuracy",
|
|
@@ -1199,8 +931,8 @@ const request: SubagentDelegationV2Request = {
|
|
|
1199
931
|
};
|
|
1200
932
|
|
|
1201
933
|
const unsubscribe = pi.events.on(SUBAGENT_DELEGATION_RESPONSE_EVENT, (payload) => {
|
|
1202
|
-
const response = payload as
|
|
1203
|
-
if (response.
|
|
934
|
+
const response = payload as SubagentDelegationResponse;
|
|
935
|
+
if (response.requestId !== request.requestId) return;
|
|
1204
936
|
if (response.ownerRunId !== request.ownerRunId || response.nodeId !== request.nodeId) return;
|
|
1205
937
|
unsubscribe();
|
|
1206
938
|
// Inspect response.status, response.result, response.usage, model, and thinking.
|
|
@@ -1221,22 +953,28 @@ Terminal usage reports input, output, cache-read, cache-write, cost, turns, tool
|
|
|
1221
953
|
calls, and duration alongside the effective model and thinking level when
|
|
1222
954
|
known. Schemas are capped at 64 KiB; tasks and returned text/structured values
|
|
1223
955
|
are capped at 1 MiB, with smaller bounds on identity/configuration strings and
|
|
1224
|
-
a maximum
|
|
956
|
+
a maximum `timeoutMs` of 2,147,483,647. Structured delegation accepts
|
|
1225
957
|
`toolBudget: { hard: 0, block: "*" }` to block the first tool call and run a
|
|
1226
|
-
zero-tool leaf;
|
|
1227
|
-
|
|
1228
|
-
pending-cancellation and settled-attempt identities per extension
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
Delegation requires an active extension context. Emit requests from a supported
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
sandbox
|
|
1239
|
-
|
|
958
|
+
zero-tool leaf; ordinary model-facing/configured budgets keep their existing
|
|
959
|
+
minimum of one. The foreground bridge retains up to 8,192 exact
|
|
960
|
+
pending-cancellation and settled-attempt identities per extension context. If
|
|
961
|
+
either history fills, it fails closed with `unavailable_context` for later
|
|
962
|
+
starts rather than evicting identity facts; lifecycle reset clears the bounded
|
|
963
|
+
history.
|
|
964
|
+
|
|
965
|
+
Delegation requires an active extension context. Emit requests from a supported
|
|
966
|
+
event callback or queued application step, not by recursively invoking the
|
|
967
|
+
`subagent` tool inside another tool's `tool_call` hook. The caller selects a
|
|
968
|
+
configured agent, but agent discovery and effective tools remain package-owned.
|
|
969
|
+
A request cannot grant arbitrary tools, and tool restrictions are not an
|
|
970
|
+
operating-system sandbox. The detached RPC remains async-only; this API is
|
|
971
|
+
foreground-only.
|
|
972
|
+
|
|
973
|
+
Unversioned prompt-template payloads with `requestId`, `agent`, `task`,
|
|
974
|
+
`context`, `model`, and `cwd` are still accepted as a legacy bridge while we
|
|
975
|
+
validate whether any integrations still use them. New integrations should use
|
|
976
|
+
the structured owned-leaf request above. `pi-subagents/delegation` is the
|
|
977
|
+
canonical contract for extension integrations.
|
|
1240
978
|
|
|
1241
979
|
## Capability ceilings
|
|
1242
980
|
|
|
@@ -1264,7 +1002,7 @@ Active registrations intersect their `allowedTools` and `allowedAgents` sets and
|
|
|
1264
1002
|
|
|
1265
1003
|
## Background-work provider API
|
|
1266
1004
|
|
|
1267
|
-
Other Pi extensions can make their current-session jobs visible to `subagent_wait` through the
|
|
1005
|
+
Other Pi extensions can make their current-session jobs visible to `subagent_wait` through the process-local provider contract:
|
|
1268
1006
|
|
|
1269
1007
|
```ts
|
|
1270
1008
|
import { registerBackgroundWorkProvider } from "pi-subagents/background-work";
|
|
@@ -1291,83 +1029,24 @@ These are the parameters the LLM passes when it calls the `subagent` tool. Most
|
|
|
1291
1029
|
|
|
1292
1030
|
### Execution examples
|
|
1293
1031
|
|
|
1294
|
-
```
|
|
1295
|
-
// Single
|
|
1296
|
-
{ agent: "
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
{
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
// Parallel
|
|
1305
|
-
{ tasks: [{ agent: "scout", task: "a" }, { agent: "reviewer", task: "b" }] }
|
|
1306
|
-
{ tasks: [{ agent: "scout", task: "audit auth", count: 3 }] }
|
|
1307
|
-
{ tasks: [{ agent: "scout", task: "audit frontend" }, { agent: "reviewer", task: "audit backend" }], context: "fork" }
|
|
1308
|
-
|
|
1309
|
-
// Chain
|
|
1310
|
-
{ chain: [
|
|
1311
|
-
{ agent: "scout", task: "Gather context for auth refactor" },
|
|
1312
|
-
{ agent: "planner" },
|
|
1313
|
-
{ checkpoint: "implementation", message: "Approve implementation before review?" },
|
|
1314
|
-
{ agent: "worker" },
|
|
1315
|
-
{ agent: "reviewer" }
|
|
1316
|
-
]}
|
|
1317
|
-
|
|
1318
|
-
// Chain in the background, suitable for unblocking the main chat
|
|
1319
|
-
{ chain: [...], async: true }
|
|
1320
|
-
|
|
1321
|
-
// Chain with fan-out/fan-in
|
|
1322
|
-
{ chain: [
|
|
1323
|
-
{ agent: "scout", task: "Gather context", phase: "Context", label: "Map code", as: "context" },
|
|
1324
|
-
{ parallel: [
|
|
1325
|
-
{ agent: "worker", task: "Implement feature A from {outputs.context}", label: "Feature A", as: "featureA" },
|
|
1326
|
-
{ agent: "worker", task: "Implement feature B from {outputs.context}", label: "Feature B", as: "featureB" }
|
|
1327
|
-
], concurrency: 2, failFast: true },
|
|
1328
|
-
{ agent: "reviewer", task: "Review {outputs.featureA} and {outputs.featureB}" }
|
|
1329
|
-
]}
|
|
1330
|
-
|
|
1331
|
-
// Dynamic fanout from structured output
|
|
1332
|
-
{ chain: [
|
|
1333
|
-
{
|
|
1334
|
-
agent: "scout",
|
|
1335
|
-
task: "Return review targets as structured_output: { items: [{ path, reason }] }",
|
|
1336
|
-
as: "targets",
|
|
1337
|
-
outputSchema: { type: "object" }
|
|
1338
|
-
},
|
|
1339
|
-
{
|
|
1340
|
-
expand: { from: { output: "targets", path: "/items" }, item: "target", key: "/path", maxItems: 12 },
|
|
1341
|
-
parallel: { agent: "reviewer", task: "Review {target.path}. Reason: {target.reason}", outputSchema: { type: "object" } },
|
|
1342
|
-
collect: { as: "reviews" },
|
|
1343
|
-
concurrency: 4
|
|
1344
|
-
},
|
|
1345
|
-
{ agent: "worker", task: "Synthesize fixes from {outputs.reviews}" }
|
|
1346
|
-
] }
|
|
1347
|
-
|
|
1348
|
-
// Strict structured output for reliable handoff data
|
|
1349
|
-
{ chain: [
|
|
1350
|
-
{
|
|
1351
|
-
agent: "scout",
|
|
1352
|
-
task: "Return the key files and risks for {task}",
|
|
1353
|
-
as: "scan",
|
|
1354
|
-
outputSchema: {
|
|
1355
|
-
type: "object",
|
|
1356
|
-
required: ["files", "risks"],
|
|
1357
|
-
properties: {
|
|
1358
|
-
files: { type: "array", items: { type: "string" } },
|
|
1359
|
-
risks: { type: "array", items: { type: "string" } }
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
},
|
|
1363
|
-
{ agent: "planner", task: "Plan from this scan: {outputs.scan}" }
|
|
1364
|
-
] }
|
|
1032
|
+
```js
|
|
1033
|
+
// Single child
|
|
1034
|
+
{ agent: "scout", task: "Analyze the auth flow", async: true }
|
|
1035
|
+
|
|
1036
|
+
// Sequential workflow
|
|
1037
|
+
{ workflowScript: `
|
|
1038
|
+
const scan = await runs.run("scan", { agent: "scout", task: "Analyze auth" });
|
|
1039
|
+
return (await runs.run("plan", { agent: "planner", task: "Plan from: " + scan.output })).output;
|
|
1040
|
+
` }
|
|
1365
1041
|
|
|
1366
|
-
//
|
|
1367
|
-
{
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1042
|
+
// Parallel workflow
|
|
1043
|
+
{ workflowScript: `
|
|
1044
|
+
const results = await runs.all([
|
|
1045
|
+
{ key: "backend", agent: "reviewer", task: "Review backend" },
|
|
1046
|
+
{ key: "frontend", agent: "reviewer", task: "Review frontend" }
|
|
1047
|
+
]);
|
|
1048
|
+
return results.map(result => result.output);
|
|
1049
|
+
` }
|
|
1371
1050
|
```
|
|
1372
1051
|
|
|
1373
1052
|
### Management actions
|
|
@@ -1439,26 +1118,26 @@ Agent definitions are not loaded into context by default. Management actions let
|
|
|
1439
1118
|
|-------|------|---------|-------------|
|
|
1440
1119
|
| `agent` | string | - | Agent name or alias for single mode, or target for management actions. Execution records use the canonical agent name. |
|
|
1441
1120
|
| `task` | string | - | Task string for single mode. |
|
|
1442
|
-
| `action` | string | - |
|
|
1121
|
+
| `action` | string | - | Agent, mission (`mission.create/list/show/update/attach-run/close`), Herdr inspector (`inspector.open/status/close`), status/control, schedule, watchdog, or doctor action. |
|
|
1443
1122
|
| `chainName` | string | - | Chain name for management actions. |
|
|
1444
|
-
| `config` | object/string | - | Agent or chain config for create/update. |
|
|
1123
|
+
| `config` | object/string | - | Agent or existing durable chain config for management create/update. |
|
|
1445
1124
|
| `output` | `string \| false` | agent default | Override single-agent output file. |
|
|
1446
1125
|
| `outputMode` | `"inline" \| "file-only"` | `inline` | Return saved output inline or as a concise saved-file reference. `file-only` requires an `output` path. |
|
|
1447
1126
|
| `skill` | `string \| string[] \| false` | agent default | Override skills or disable all. |
|
|
1448
1127
|
| `model` | string | agent default | Override model. |
|
|
1449
1128
|
| `outputSchema` | object | - | Require schema-valid structured output for a direct single-agent run. |
|
|
1450
|
-
| `agentContract` | `{ version: 1 }` | - |
|
|
1451
|
-
| `tasks` | array | - | Top-level parallel tasks. Supports `agent`, `task`, `cwd`, `count`, `output`, `outputMode`, `outputSchema`, `reads`, `progress`, `skill`, `model`, `toolBudget`, `acceptance`, and `agentContract`. |
|
|
1452
|
-
| `concurrency` | number | config or `4` | Top-level parallel concurrency. |
|
|
1453
|
-
| `worktree` | boolean | false | Create isolated git worktrees for parallel tasks. |
|
|
1454
|
-
| `chain` | array | - | Sequential, checkpoint, static parallel, and dynamic fanout chain steps. Steps and chain parallel tasks support `phase`, `label`, `as`, `outputSchema`, `acceptance`, `agentContract`, and v1-only `gateOn` 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. |
|
|
1129
|
+
| `agentContract` | `{ version: 1 }` | - | Enable the compatibility behavior for this run. Omit for the default behavior. |
|
|
1455
1130
|
| `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`, `oracle`, and `advisor` default to `fork`. |
|
|
1456
|
-
| `
|
|
1131
|
+
| `missionId` | string | - | Attach a single-agent or workflow launch to an existing project mission. |
|
|
1132
|
+
| `mission` | object/false | - | Create-and-attach shortcut: `{ title, goal?, labels? }`; pass `false` for an intentionally ephemeral launch with no mission record. Explicit mission persistence failures are strict. |
|
|
1133
|
+
| `handoffPath` | string | - | Aggregate handoff manifest required by `action: "worktree.discard"`. |
|
|
1134
|
+
| `focus` | boolean | true | Focus the newly split pane for `action: "inspector.open"`; not a standalone action. |
|
|
1457
1135
|
| `view` | `fleet \| transcript` | - | Optional `status` view for the active fleet surface or transcript tail inspection. |
|
|
1458
1136
|
| `lines` | number | `80` | Maximum transcript lines for `action: "status", view: "transcript"`; capped at 500. |
|
|
1459
1137
|
| `clarify` | boolean | false | Show TUI preview/edit flow. Explicit `clarify: true` keeps the run foreground for the clarify UI. |
|
|
1460
1138
|
| `agentScope` | `user \| project \| both` | `both` | Agent discovery scope. Project wins on collisions. |
|
|
1461
|
-
| `async` | boolean |
|
|
1139
|
+
| `async` | boolean | default-on | Background execution. Scripted workflows always default to background and accept `async:false` as an explicit foreground escape hatch. `clarify:true` applies only to single-agent execution; workflowScript does not open clarify UI. |
|
|
1140
|
+
| `chatProgress` | `auto \| off \| terminal \| milestones \| live-card` | `auto` | WorkflowScript chat projection. `auto` renders a live in-chat card only for watched foreground workflows in the same Git repository, including managed worktrees; background and other-repo workflows stay compact. Explicit `live-card` requires `async:false` and the same Git repository. |
|
|
1462
1141
|
| `timeoutMs` / `maxRuntimeMs` | number | 30 min foreground; none async | Optional run-level max runtime in milliseconds. Foreground uses 30 minutes only when neither the call nor selected agent provides a timeout. |
|
|
1463
1142
|
| `turnBudget` | object | none | Optional assistant-turn budget `{ maxTurns, graceTurns }`. At `maxTurns` the child is warned to wrap up. After the grace window (default 1), termination occurs at the next assistant boundary; a response that starts tool work records `termination-deferred` until a later boundary. Partial output is returned on abort. |
|
|
1464
1143
|
| `toolBudget` | object | none | Optional child tool-call budget `{ soft?, hard, block? }`. At `soft` the child is nudged to finalize. After `hard`, configured tools are blocked; `block` defaults to `read`, `grep`, `find`, and `ls`, while `"*"` blocks every tool call. Final assistant text is never blocked. |
|
|
@@ -1471,19 +1150,13 @@ Agent definitions are not loaded into context by default. Management actions let
|
|
|
1471
1150
|
| `sessionDir` | string | derived | Override session log directory. |
|
|
1472
1151
|
| `acceptance` | string/object/false | inferred | Configure evidence gates with `"auto"`, `"attested"`, `"checked"`, `"verified"`, or `{ level: "none", reason: "..." }`. Independent review is orthogonal: use `review: { required: true, agent?: "reviewer", focus?: "..." }`. `review-required` means evidence passed but review is pending; `reviewed` is achieved only after a real independent result. Explicit `"reviewed"` remains schema-recognized solely for actionable preflight recovery. For reviewer/read-only calls, omit acceptance. `false` disables gates. With `agentContract: { version: 1 }`, omitted, `"auto"`, and `false` mean no acceptance request for that run; explicit acceptance is reported separately from execution. |
|
|
1473
1152
|
|
|
1474
|
-
`agentContract: { version: 1 }` keeps existing fields and artifacts but adds derived `execution`, `acceptance`, `review`, and `effects` projections. In v1, acceptance failures do not rewrite execution success, and an explicit completion guard reports `effects.fileMutation` instead of failing the run by itself. Chain steps default to advancing on execution under v1; set `gateOn: "acceptance"` on a v1 step or parallel task when rejected acceptance should stop the chain.
|
|
1475
|
-
|
|
1476
|
-
Checkpoint steps use `{ checkpoint: "stable-name", message?: "..." }`. A checkpoint does not launch a child, consume spawn budget, or produce an output reference. Foreground chains return a paused result at the checkpoint so the current parent can explicitly choose the next action. Async chains persist `checkpoint` in status/details and pause before the next step; approve with `subagent({ action: "approve-checkpoint", id: "<run-id>" })` or reject with `subagent({ action: "reject-checkpoint", id: "<run-id>" })`. Approval resumes from that boundary without rerunning completed steps. Rejection is terminal with `state: "rejected"`.
|
|
1477
|
-
|
|
1478
1153
|
As a conservative orchestration policy, do not set `turnBudget`, a hard `toolBudget`, or a tight `usageBudget` on implementation workers, fix workers, reviewers with edit authority, or other mutation-capable children. A default tool budget blocks read/search tools rather than mutation tools, and reported usage has no reservation model, so neither assistant turns, tool-call counts, nor token/cost totals measure whether a delivery slice is buildable or safe to hand off. Hard caps remain appropriate for explicitly read-only scouts, reviewers, and validators.
|
|
1479
1154
|
|
|
1480
1155
|
Bound writer work with a narrow task and an outer `timeoutMs` or `maxRuntimeMs` that leaves enough margin for the slice. An elapsed timeout is not a mutation-safe boundary and may still signal a child during tool work. Before the deadline, use `steer` or an attention notice to request a checkpoint after the current tool returns, including changed files, build/test state, remaining work, and commit or PR state.
|
|
1481
1156
|
|
|
1482
|
-
`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. It forces thinking `off` only when the child’s effective primary or fallback model resolves through the model registry to the Anthropic provider or `anthropic-messages` API; unresolved models are treated conservatively. The result reports every affected child, including on failed runs. Use `context: "fresh"` when an Anthropic child needs thinking. Forking never silently downgrades to `fresh`. In
|
|
1157
|
+
`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. It forces thinking `off` only when the child’s effective primary or fallback model resolves through the model registry to the Anthropic provider or `anthropic-messages` API; unresolved models are treated conservatively. The result reports every affected child, including on failed runs. Use `context: "fresh"` when an Anthropic child needs thinking. Forking never silently downgrades to `fresh`. In workflow runs that omit `context`, each `runs.run` child 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.
|
|
1483
1158
|
|
|
1484
|
-
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
|
|
1485
|
-
|
|
1486
|
-
Sequential and parallel chain tasks accept `agent`, `task`, `phase`, `label`, `as`, `outputSchema`, `cwd`, `output`, `outputMode`, `reads`, `progress`, `skill`, `model`, `toolBudget`, `acceptance`, `agentContract`, and v1-only `gateOn`. 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}`.
|
|
1159
|
+
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 workflowScript, give each child an explicit output path when later script steps need a durable file reference. A child with only read-only tools does not need direct filesystem access for `output`: it returns the complete artifact in its final response and the runtime persists it. Children with mutation-capable tools retain the direct-write instruction.
|
|
1487
1160
|
|
|
1488
1161
|
Status and control actions:
|
|
1489
1162
|
|
|
@@ -1501,7 +1174,7 @@ subagent({ action: "resume", id: "<run-id>", index: 1, message: "follow-up for c
|
|
|
1501
1174
|
subagent({ action: "resume", id: "<nested-run-id>", message: "follow-up for a nested child" })
|
|
1502
1175
|
subagent({ action: "steer", id: "<run-id>", message: "guidance for the running child" })
|
|
1503
1176
|
subagent({ action: "steer", id: "<run-id>", index: 1, message: "guidance for child 2" })
|
|
1504
|
-
subagent({ action: "append-step", id: "<run-id>",
|
|
1177
|
+
subagent({ action: "append-step", id: "<run-id>", step: { agent: "worker", task: "Continue from {previous}" } })
|
|
1505
1178
|
subagent({ action: "approve-checkpoint", id: "<run-id>" })
|
|
1506
1179
|
subagent({ action: "reject-checkpoint", id: "<run-id>" })
|
|
1507
1180
|
subagent({ action: "doctor" })
|
|
@@ -1511,45 +1184,53 @@ subagent({ action: "doctor" })
|
|
|
1511
1184
|
|
|
1512
1185
|
`resume` revives a paused, completed, or failed async/foreground child by starting a new child from its stored session file; stopped runs remain non-resumable, and it does not interrupt a live top-level async child. Use `steer` for acknowledged live async guidance. 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 nested 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. Direct revival takes an exclusive cross-process lease on the canonical session file until the new child finishes. A concurrent attempt fails before Pi is spawned and identifies the owning revived run; dead-owner leases are reclaimed only when staleness can be proved.
|
|
1513
1186
|
|
|
1514
|
-
`stop` ends a current-session top-level async run. It is deliberately stronger than `interrupt`: it is not a resumable pause, stopped runs should be restarted as new runs, foreground and nested targets are rejected, direct id calls execute immediately, and `/subagents-stop` without an id opens a selector with confirmation when a TUI is available. Use `↑`/`↓` or `j`/`k` to move through that selector. In non-TUI contexts the slash command prints exact `subagent({ action: "stop", id })` and `/subagents-stop <id>` commands.
|
|
1187
|
+
`stop` ends a current-session top-level async run. It is deliberately stronger than `interrupt`: it is not a resumable pause, stopped runs should be restarted as new runs, foreground and nested targets are rejected, direct id calls execute immediately, and `/subagents-stop` without an id opens a selector with confirmation when a TUI is available. Use `↑`/`↓` or `j`/`k` to move through that selector. In non-TUI contexts the slash command prints exact `subagent({ action: "stop", id })` and `/subagents-stop <id>` commands. Inactive schedules can appear in the selector, but they are labeled as schedules and route through `schedule.pause`, not `stop`.
|
|
1515
1188
|
|
|
1516
|
-
`steer` waits up to three seconds for a correlated child-Pi input acceptance and returns a request id with `delivered`, `scheduled`, `pending`, `partial`, `recovered`, or `failed` plus per-child states. Delivery means Pi accepted the user message, not model compliance. A pending indexed child returns `scheduled`. Only a top-level single run may interrupt after the acknowledgment deadline and recover after a further 15-second pause/revival bound;
|
|
1189
|
+
`steer` waits up to three seconds for a correlated child-Pi input acceptance and returns a request id with `delivered`, `scheduled`, `pending`, `partial`, `recovered`, or `failed` plus per-child states. Delivery means Pi accepted the user message, not model compliance. A pending indexed child returns `scheduled`. Only a top-level single run may interrupt after the acknowledgment deadline and recover after a further 15-second pause/revival bound; durable multi-child and nested runs never auto-interrupt. Recovery launches a replacement only after the source is confirmed paused, a valid persisted session exists, and deadline, turn, and tool budgets remain. It preserves the original child contract and remaining limits; otherwise the source stays paused with an explicit failure. Late acceptance is recorded but cannot cancel committed recovery. The persisted `steering` ledger retains 20 requests and replaces the old `steerCount`/`lastSteerAt` fields.
|
|
1517
1190
|
|
|
1518
|
-
`append-step` accepts exactly one
|
|
1191
|
+
`append-step` accepts exactly one `step` object for an existing durable chain 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, rejected, paused, foreground, single, and non-chain runs reject appends.
|
|
1519
1192
|
|
|
1520
|
-
##
|
|
1193
|
+
## Durable missions
|
|
1521
1194
|
|
|
1522
|
-
|
|
1195
|
+
Missions are durable wrappers around runs. The noun map is:
|
|
1196
|
+
|
|
1197
|
+
- **Project/codebase** — where work happens.
|
|
1198
|
+
- **Mission** — why delegated work exists and how to recover it later.
|
|
1199
|
+
- **Run** — one actual subagent execution.
|
|
1200
|
+
- **Receipt** — proof or a link for an external outcome, such as a PR, CI check, deployment, or release.
|
|
1201
|
+
|
|
1202
|
+
Ordinary task launches create a mission by default, with detailed JSON records under `<cwd>/.pi-subagents/missions/` linking goals, run ids, lifecycle status, decisions, artifact paths, and delivery receipts. Automatic persistence failures do not block the run and are reported as `details.missionWarning`; explicit `missionId` and `mission` requests remain strict before launch. Human receipts end with `Mission: <id> (<status>)`, while JSON/structured output text stays unchanged and `details.missionId` is authoritative. Pass `mission: false` for an intentionally ephemeral launch that should not leave a durable mission record. Set `missions.enabled: false` to disable automatic mission creation; explicit mission fields and actions still work.
|
|
1523
1203
|
|
|
1524
1204
|
```ts
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
{
|
|
1528
|
-
|
|
1205
|
+
const created = subagent({
|
|
1206
|
+
action: "mission.create",
|
|
1207
|
+
mission: { title: "Ship auth refresh", goal: "Implement and validate token refresh" }
|
|
1208
|
+
})
|
|
1209
|
+
subagent({ agent: "worker", task: "Implement the approved auth refresh plan", missionId: "<mission-id>" })
|
|
1529
1210
|
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
{ parallel: [
|
|
1533
|
-
{ agent: "worker", task: "Implement feature A from {previous}" },
|
|
1534
|
-
{ agent: "worker", task: "Implement feature B from {previous}" }
|
|
1535
|
-
], worktree: true },
|
|
1536
|
-
{ agent: "reviewer", task: "Review all changes from {previous}" }
|
|
1537
|
-
]}
|
|
1211
|
+
// Or create and attach in one launch
|
|
1212
|
+
subagent({ agent: "worker", task: "Implement the approved plan", mission: { title: "Ship auth refresh" } })
|
|
1538
1213
|
```
|
|
1539
1214
|
|
|
1540
|
-
|
|
1215
|
+
Use `mission.list`, `mission.show`, `mission.update`, `mission.attach-run`, and `mission.close` for management. Use `mission.update` to record decisions, artifacts, labels, summaries, and delivery receipts while work runs; receipts are durable links for pull requests, CI, deployments, or releases, each with `kind`, `status`, `title`, `url`, and optional `description`. They record delivery state only; pi-subagents does not merge, poll CI, or deploy. Use `mission.close` with a terminal status and summary when a mission is done. After compaction or restart, resume from `mission.list`/`mission.show` first: `mission.show` refreshes linked async status where available, then use the linked run ids with normal `status`, `steer`, `resume`, or `stop` actions. `mission.list` with `missionScope: "global"` reads the user-local pointer index under the Pi agent directory; project records remain the source of truth, and missing records are reported as stale rather than hiding other projects.
|
|
1541
1216
|
|
|
1542
|
-
-
|
|
1543
|
-
- working tree must be clean
|
|
1544
|
-
- `node_modules/` is symlinked into each worktree when present
|
|
1545
|
-
- task-level `cwd` overrides must be omitted or match the shared cwd
|
|
1546
|
-
- configured `worktreeSetupHook` must return valid JSON before timeout
|
|
1217
|
+
For cross-project work, keep same-project tasks on ordinary subagents. Use an explicit `cwd` for small bounded work in another project. For substantial or long-running work in another project, open a project-owned Herdr pane with `project.open` and give that project Pi session a narrow mission/result contract. The project pane owns its own subagents; do not model it as ordinary child nesting or expect existing headless runs to move into the pane.
|
|
1547
1218
|
|
|
1548
|
-
|
|
1219
|
+
## Worktree isolation
|
|
1549
1220
|
|
|
1550
|
-
|
|
1221
|
+
Scripted workflows can give each writing child a separate managed git worktree by setting `worktree: true` on each `runs.run` / `runs.all` item:
|
|
1551
1222
|
|
|
1552
|
-
|
|
1223
|
+
```javascript
|
|
1224
|
+
const [api, ui] = await runs.all([
|
|
1225
|
+
{ key: "api", agent: "worker", task: "Implement the API", worktree: true },
|
|
1226
|
+
{ key: "ui", agent: "worker", task: "Implement the UI", worktree: true }
|
|
1227
|
+
]);
|
|
1228
|
+
return { api: api.artifactPaths, ui: ui.artifactPaths };
|
|
1229
|
+
```
|
|
1230
|
+
|
|
1231
|
+
Each child uses the existing worktree lifecycle: it branches from clean HEAD, journals ownership before launch, captures a patch and handoff manifest, then removes cleanly captured temporary worktrees and branches. The handoff manifest path remains available in the child's `artifactPaths`; return or emit it when the orchestrator needs to apply or inspect the patches. `runs.ref` stays concise and intentionally omits full paths.
|
|
1232
|
+
|
|
1233
|
+
A top-level `{ workflowScript, worktree: true }` makes isolation the default for every workflow child. An individual child can override that default with `worktree: false`. Keep one writer when parallel writes are not intentionally isolated.
|
|
1553
1234
|
|
|
1554
1235
|
## Configuration
|
|
1555
1236
|
|
|
@@ -1565,13 +1246,21 @@ Controls the parent-facing `subagent` tool description registered at startup. `f
|
|
|
1565
1246
|
|
|
1566
1247
|
`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.
|
|
1567
1248
|
|
|
1249
|
+
### `inlineToolDisplay`
|
|
1250
|
+
|
|
1251
|
+
```json
|
|
1252
|
+
{ "inlineToolDisplay": "summary" }
|
|
1253
|
+
```
|
|
1254
|
+
|
|
1255
|
+
Controls the `subagent` tool result shown inline in chat. The default, `"rich"`, shows live child activity and expands to detailed output. `"summary"` keeps the inline result at one stable row for running, completed, failed, stopped, and paused runs; it does not animate, show elapsed time, preview child output, or change when Pi's expand key is pressed. FleetView remains available for live progress and detailed inspection.
|
|
1256
|
+
|
|
1568
1257
|
### `asyncByDefault`
|
|
1569
1258
|
|
|
1570
1259
|
```json
|
|
1571
|
-
{ "asyncByDefault":
|
|
1260
|
+
{ "asyncByDefault": false }
|
|
1572
1261
|
```
|
|
1573
1262
|
|
|
1574
|
-
|
|
1263
|
+
Ordinary top-level calls use background execution when the request omits `async`. Set `asyncByDefault` to `false` to restore foreground-by-default behavior. Callers can still force foreground with `async: false` unless `forceTopLevelAsync` is enabled; `clarify: true` remains foreground for its UI.
|
|
1575
1264
|
|
|
1576
1265
|
### `fleetView`
|
|
1577
1266
|
|
|
@@ -1595,7 +1284,7 @@ Places the persistent FleetView either `"belowEditor"` or `"aboveEditor"`. The d
|
|
|
1595
1284
|
{ "asyncWidget": true }
|
|
1596
1285
|
```
|
|
1597
1286
|
|
|
1598
|
-
Controls the
|
|
1287
|
+
Controls the under-editor widget for active background runs. It defaults to `true`, including when FleetView is enabled, so active work remains visible after reload. Set it to `false` to hide this widget while keeping FleetView available.
|
|
1599
1288
|
|
|
1600
1289
|
### `waitTool`
|
|
1601
1290
|
|
|
@@ -1605,6 +1294,8 @@ Controls the legacy above-editor widget for background runs. It defaults to `fal
|
|
|
1605
1294
|
|
|
1606
1295
|
Keeps the `subagent_wait` tool registered but makes direct calls return immediately instead of blocking on active subagent or provider work. The default is enabled. You can also set `"waitTool": false`; set `PI_SUBAGENT_WAIT_TOOL_ENABLED=false` (or `0`, `off`, `disabled`) to override config for one process. The effective value is passed explicitly to child runtimes. Headless `agent_end` auto-drain remains a lifecycle safeguard even when direct wait calls are disabled. Invalid config or environment values fail instead of being coerced.
|
|
1607
1296
|
|
|
1297
|
+
Blocking `subagent_wait({ id: "..." })` keeps the current tool call open until that run changes. In a long-lived interactive parent session, `subagent_wait({ id: "...", nonBlocking: true })` instead resolves the prefix once, persists the exact run identity, returns a subscription token immediately, and wakes that session on completion, failure, attention, reconciliation failure, or timeout. Armed subscriptions appear in ordinary `subagent({ action: "status" })` output and are not counted as active child work. This is different from `waitTool.enabled=false`, which returns immediately without registering any future wake. Provider items remain available only to blocking fleet-wide waits; non-blocking subscriptions require one async or remembered detached foreground run id.
|
|
1298
|
+
|
|
1608
1299
|
### `forceTopLevelAsync`
|
|
1609
1300
|
|
|
1610
1301
|
```json
|
|
@@ -1619,7 +1310,7 @@ Forces depth-0 single, parallel, and chain runs into background mode and bypasse
|
|
|
1619
1310
|
{ "globalConcurrencyLimit": 20 }
|
|
1620
1311
|
```
|
|
1621
1312
|
|
|
1622
|
-
Caps simultaneously running
|
|
1313
|
+
Caps simultaneously running children inside existing durable legacy multi-child runs. New orchestration uses `workflowScript` and `runs.all`.
|
|
1623
1314
|
|
|
1624
1315
|
### `maxSubagentSpawnsPerSession`
|
|
1625
1316
|
|
|
@@ -1636,10 +1327,12 @@ A user may explicitly call `subagent({ action: "grant-spawn-budget", additional:
|
|
|
1636
1327
|
### `scheduledRuns`
|
|
1637
1328
|
|
|
1638
1329
|
```json
|
|
1639
|
-
{ "scheduledRuns": { "enabled":
|
|
1330
|
+
{ "scheduledRuns": { "enabled": false, "maxPending": 20 } }
|
|
1640
1331
|
```
|
|
1641
1332
|
|
|
1642
|
-
|
|
1333
|
+
Durable schedules are enabled by default and stored per project under `.pi-subagents/schedules/<id>/`. Create a one-shot schedule with `subagent({ action: "schedule.create", id: "evening-review", name: "Evening review", at: "+30m", agent: "reviewer", task: "Review the current diff." })`. Create a fixed recurring workflow with `subagent({ action: "schedule.create", id: "backlog", every: "6h", catchUp: "latest", workflowScript: "..." })`. Fixed intervals support `m`, `h`, `d`, and `w` units and advance from the planned time without completion drift.
|
|
1334
|
+
|
|
1335
|
+
Manage schedules with `schedule.list`, `schedule.show`, `schedule.history`, `schedule.pause`, `schedule.resume`, `schedule.run`, `schedule.run-due`, and `schedule.delete`. Runs always launch async with fresh context and disable automatic mission creation; mission attachment is deferred from this first slice. Definitions, bounded history, append-only events, and per-run receipts are stored with mode `0600`. `overlap` is currently fixed to `skip`; `catchUp` supports `latest` (default) and `none`. `schedule.run-due` lets an external launcher start due project work without making `pi-subagents` a daemon. Calendar recurrence, cron, queue/replace overlap, and the schedule TUI inspector are intentionally deferred to the next slice. The old `schedule`, `schedule-list`, `schedule-status`, and `schedule-cancel` actions were removed in this hard cutover.
|
|
1643
1336
|
|
|
1644
1337
|
### `parallel`
|
|
1645
1338
|
|
|
@@ -1704,7 +1397,7 @@ Fields:
|
|
|
1704
1397
|
|
|
1705
1398
|
- `mode`: default `always`; use `fork-only` to inject only for forked runs, or `off` to disable the bridge.
|
|
1706
1399
|
- `instructionFile`: optional Markdown template replacing the default bridge instructions. `{orchestratorTarget}` is interpolated. Relative paths resolve from `~/.pi/agent/extensions/subagent/`.
|
|
1707
|
-
- `resultDelivery`: default `
|
|
1400
|
+
- `resultDelivery`: default `false`; set `true` only when an external `subagent:result-intercom` listener is installed. Enabled delivery waits for acknowledgement and reports acknowledgement failures. Supervisor asks/progress remain active.
|
|
1708
1401
|
|
|
1709
1402
|
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.
|
|
1710
1403
|
|
|
@@ -1737,6 +1430,38 @@ stdin is a JSON object with `repoRoot`, `worktreePath`, `agentCwd`, `branch`, `i
|
|
|
1737
1430
|
|
|
1738
1431
|
`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.
|
|
1739
1432
|
|
|
1433
|
+
### `missions`
|
|
1434
|
+
|
|
1435
|
+
```json
|
|
1436
|
+
{
|
|
1437
|
+
"missions": {
|
|
1438
|
+
"enabled": true,
|
|
1439
|
+
"directory": ".pi-subagents/missions",
|
|
1440
|
+
"globalIndex": true,
|
|
1441
|
+
"retainTerminal": 200
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
```
|
|
1445
|
+
|
|
1446
|
+
Automatic missions are enabled by default for ordinary launches with a task. Use per-launch `mission: false` for intentionally ephemeral work, or set `enabled: false` to disable automatic creation globally; explicit mission actions and `missionId`/`mission` launch fields still work. `directory` may be absolute, `~/...`, or project-relative. `retainTerminal` is a positive count (default `200`); pruning removes only the oldest completed, failed, or cancelled records and their pointers, never planned, active, waiting, needs-decision, or corrupt records. The user-global index contains pointers only; missing-record pointers self-heal when globally listed. Set `globalIndex: false` to disable writes or `globalIndexDir` to redirect it.
|
|
1447
|
+
|
|
1448
|
+
### `authorityPolicy`
|
|
1449
|
+
|
|
1450
|
+
```json
|
|
1451
|
+
{
|
|
1452
|
+
"authorityPolicy": {
|
|
1453
|
+
"discardWorktree": "confirm",
|
|
1454
|
+
"destructiveCleanup": "confirm",
|
|
1455
|
+
"spawnBudgetGrant": "confirm",
|
|
1456
|
+
"scheduleCreate": "auto",
|
|
1457
|
+
"stopRun": "auto",
|
|
1458
|
+
"steerRun": "auto"
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
```
|
|
1462
|
+
|
|
1463
|
+
Each fixed action resolves to `"auto"`, `"confirm"`, or `"forbid"`. This is intentionally a small action map, not a generic policy language. Confirm-required control actions fail closed without an interactive UI.
|
|
1464
|
+
|
|
1740
1465
|
### `artifactDir`
|
|
1741
1466
|
|
|
1742
1467
|
```json
|
|
@@ -1747,7 +1472,9 @@ stdin is a JSON object with `repoRoot`, `worktreePath`, `agentCwd`, `branch`, `i
|
|
|
1747
1472
|
|
|
1748
1473
|
Controls where subagent artifact files (inputs, outputs, transcripts, metadata) are stored. Defaults to `"project"`, which writes to `<cwd>/.pi-subagents/artifacts/`. Set to `"session"` to store artifacts under pi's session directory (`~/.pi/agent/sessions/<session>/subagent-artifacts/`), keeping the working directory clean. Set to `"temp"` to use the OS temp directory.
|
|
1749
1474
|
|
|
1750
|
-
|
|
1475
|
+
This preference also controls the default chain scratch directory. `"project"` uses `<cwd>/.pi-subagents/chain-runs/`, while `"session"` and `"temp"` use the user-scoped temp chain directory.
|
|
1476
|
+
|
|
1477
|
+
The `"session"` option uses the same directory that `cleanupAllArtifactDirs` already scans for age-based cleanup, so artifacts are still cleaned up automatically. Temporary chain directories are cleaned up separately after 24 hours.
|
|
1751
1478
|
|
|
1752
1479
|
### `completionBatch`
|
|
1753
1480
|
|
|
@@ -1764,19 +1491,19 @@ The `"session"` option uses the same directory that `cleanupAllArtifactDirs` alr
|
|
|
1764
1491
|
}
|
|
1765
1492
|
```
|
|
1766
1493
|
|
|
1767
|
-
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
|
|
1494
|
+
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 quiet grouped completion instead of separate completions. 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`.
|
|
1768
1495
|
|
|
1769
1496
|
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.
|
|
1770
1497
|
|
|
1771
1498
|
## Files, logs, and observability
|
|
1772
1499
|
|
|
1773
|
-
Each chain run creates a user-scoped temp
|
|
1500
|
+
Each chain run creates a scratch directory under its resolved chain root. With the default `artifactDir: "project"`, that root is `<cwd>/.pi-subagents/chain-runs/`. With `artifactDir: "session"` or `"temp"`, it is user-scoped temp storage:
|
|
1774
1501
|
|
|
1775
1502
|
```text
|
|
1776
1503
|
<tmpdir>/pi-subagents-<scope>/chain-runs/{runId}/
|
|
1777
1504
|
```
|
|
1778
1505
|
|
|
1779
|
-
|
|
1506
|
+
A run directory may contain files such as `context.md`, `plan.md`, `progress.md`, and `parallel-{stepIndex}/.../output.md`. User-scoped temp chain directories older than 24 hours are cleaned up on extension startup; project-local and explicit persistent roots are not age-scanned.
|
|
1780
1507
|
|
|
1781
1508
|
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:
|
|
1782
1509
|
|
|
@@ -1789,7 +1516,7 @@ Metadata records timing, usage, exit code, final model, attempted models, fallba
|
|
|
1789
1516
|
|
|
1790
1517
|
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.
|
|
1791
1518
|
|
|
1792
|
-
Async completions
|
|
1519
|
+
Async completions belong only to the originating session. The result watcher emits `subagent:async-complete`, and the extension consumes that event to record completion state. Successful sibling completions are held briefly and delivered as a quiet grouped completion when they finish within a short window (see `completionBatch`), avoiding unread markers on inactive tabs. Failed and paused completions remain visible and fire immediately.
|
|
1793
1520
|
|
|
1794
1521
|
Async runs write:
|
|
1795
1522
|
|
|
@@ -1914,15 +1641,9 @@ Then run it through the native adapter:
|
|
|
1914
1641
|
/prompt-workflow take-screenshot https://example.com
|
|
1915
1642
|
```
|
|
1916
1643
|
|
|
1917
|
-
The adapter delegates to the named subagent, applies `model`, `skill`, `cwd`,
|
|
1918
|
-
|
|
1919
|
-
For prompt-template chains, use:
|
|
1920
|
-
|
|
1921
|
-
```text
|
|
1922
|
-
/chain-prompts analyze -> fix -- user arguments here
|
|
1923
|
-
```
|
|
1644
|
+
The adapter delegates to the named subagent, applies `model`, `skill`, `cwd`, and fork/fresh context metadata, and supports runtime overrides such as `--subagent reviewer`, `--fork`, `--fresh`, and `--bg`.
|
|
1924
1645
|
|
|
1925
|
-
|
|
1646
|
+
Prompt templates with `chain:` frontmatter are translated into `workflowScript` and launched through `/prompt-workflow`; `/chain-prompts` is no longer registered.
|
|
1926
1647
|
|
|
1927
1648
|
## Runtime files
|
|
1928
1649
|
|