pi-subagents 0.73.1 → 0.75.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 +100 -0
- package/README.md +1 -1
- package/docs/agents.md +30 -16
- package/docs/configuration.md +76 -9
- package/docs/extension-api.md +6 -5
- package/docs/missions.md +28 -14
- package/docs/models.md +8 -4
- package/docs/observability.md +10 -5
- package/docs/tool-reference.md +90 -88
- package/docs/workflows.md +166 -172
- package/package.json +2 -2
- package/prompts/review-loop.md +1 -1
- package/skills/council-mode/SKILL.md +1 -1
- package/skills/pi-subagents/SKILL.md +12 -5
- package/skills/pi-subagents/references/constraints-and-recipes.md +3 -3
- package/skills/pi-subagents/references/execution-controls.md +68 -67
- package/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
- package/skills/pi-subagents/references/multi-lane-orchestration.md +1 -1
- package/skills/pi-subagents/references/prompting-and-roles.md +45 -48
- package/src/agents/agent-management.js +2 -2
- package/src/agents/agent-management.js.map +1 -1
- package/src/agents/agents.d.ts +2 -0
- package/src/agents/agents.d.ts.map +1 -1
- package/src/agents/agents.js +73 -3
- package/src/agents/agents.js.map +1 -1
- package/src/api/preflight.d.ts +6 -2
- package/src/api/preflight.d.ts.map +1 -1
- package/src/api/preflight.js +46 -2
- package/src/api/preflight.js.map +1 -1
- package/src/extension/config.d.ts.map +1 -1
- package/src/extension/config.js +15 -4
- package/src/extension/config.js.map +1 -1
- package/src/extension/control-notices.d.ts +2 -0
- package/src/extension/control-notices.d.ts.map +1 -1
- package/src/extension/control-notices.js +2 -0
- package/src/extension/control-notices.js.map +1 -1
- package/src/extension/doctor.d.ts.map +1 -1
- package/src/extension/doctor.js +1 -0
- package/src/extension/doctor.js.map +1 -1
- package/src/extension/fanout-child.d.ts.map +1 -1
- package/src/extension/fanout-child.js +13 -3
- package/src/extension/fanout-child.js.map +1 -1
- package/src/extension/herdr-pi-bridge.d.ts.map +1 -1
- package/src/extension/herdr-pi-bridge.js +2 -0
- package/src/extension/herdr-pi-bridge.js.map +1 -1
- package/src/extension/index.d.ts +1 -1
- package/src/extension/index.d.ts.map +1 -1
- package/src/extension/index.js +87 -179
- package/src/extension/index.js.map +1 -1
- package/src/extension/public-execution.d.ts +10 -1
- package/src/extension/public-execution.d.ts.map +1 -1
- package/src/extension/public-execution.js +73 -35
- package/src/extension/public-execution.js.map +1 -1
- package/src/extension/reply-workflow-script.d.ts +12 -0
- package/src/extension/reply-workflow-script.d.ts.map +1 -0
- package/src/extension/reply-workflow-script.js +61 -0
- package/src/extension/reply-workflow-script.js.map +1 -0
- package/src/extension/rpc.d.ts +2 -0
- package/src/extension/rpc.d.ts.map +1 -1
- package/src/extension/rpc.js +33 -10
- package/src/extension/rpc.js.map +1 -1
- package/src/extension/schemas.d.ts +4 -117
- package/src/extension/schemas.d.ts.map +1 -1
- package/src/extension/schemas.js +42 -127
- package/src/extension/schemas.js.map +1 -1
- package/src/extension/tool-activation.d.ts +2 -4
- package/src/extension/tool-activation.d.ts.map +1 -1
- package/src/extension/tool-activation.js +54 -104
- package/src/extension/tool-activation.js.map +1 -1
- package/src/extension/tool-description.d.ts +8 -5
- package/src/extension/tool-description.d.ts.map +1 -1
- package/src/extension/tool-description.js +51 -27
- package/src/extension/tool-description.js.map +1 -1
- package/src/extension/upgrade-notice.d.ts +7 -0
- package/src/extension/upgrade-notice.d.ts.map +1 -0
- package/src/extension/upgrade-notice.js +37 -0
- package/src/extension/upgrade-notice.js.map +1 -0
- package/src/integrations/herdr-status.d.ts +3 -0
- package/src/integrations/herdr-status.d.ts.map +1 -1
- package/src/integrations/herdr-status.js +17 -3
- package/src/integrations/herdr-status.js.map +1 -1
- package/src/intercom/native-supervisor-channel.d.ts.map +1 -1
- package/src/intercom/native-supervisor-channel.js +4 -1
- package/src/intercom/native-supervisor-channel.js.map +1 -1
- package/src/missions/goal-driver.d.ts +1 -0
- package/src/missions/goal-driver.d.ts.map +1 -1
- package/src/missions/goal-driver.js +49 -34
- package/src/missions/goal-driver.js.map +1 -1
- package/src/missions/store.d.ts.map +1 -1
- package/src/missions/store.js +11 -1
- package/src/missions/store.js.map +1 -1
- package/src/profiles/profiles.d.ts +1 -1
- package/src/profiles/profiles.d.ts.map +1 -1
- package/src/profiles/profiles.js +4 -0
- package/src/profiles/profiles.js.map +1 -1
- package/src/runs/background/async-execution.d.ts +16 -0
- package/src/runs/background/async-execution.d.ts.map +1 -1
- package/src/runs/background/async-execution.js +95 -8
- package/src/runs/background/async-execution.js.map +1 -1
- package/src/runs/background/async-job-tracker.d.ts +1 -0
- package/src/runs/background/async-job-tracker.d.ts.map +1 -1
- package/src/runs/background/async-job-tracker.js +67 -24
- package/src/runs/background/async-job-tracker.js.map +1 -1
- package/src/runs/background/async-retention.d.ts +1 -1
- package/src/runs/background/async-retention.d.ts.map +1 -1
- package/src/runs/background/async-retention.js +47 -15
- package/src/runs/background/async-retention.js.map +1 -1
- package/src/runs/background/await-async-run.d.ts +23 -0
- package/src/runs/background/await-async-run.d.ts.map +1 -0
- package/src/runs/background/await-async-run.js +82 -0
- package/src/runs/background/await-async-run.js.map +1 -0
- package/src/runs/background/chain-root-attachment.d.ts +1 -0
- package/src/runs/background/chain-root-attachment.d.ts.map +1 -1
- package/src/runs/background/chain-root-attachment.js +3 -3
- package/src/runs/background/chain-root-attachment.js.map +1 -1
- package/src/runs/background/control-channel.d.ts +10 -0
- package/src/runs/background/control-channel.d.ts.map +1 -1
- package/src/runs/background/control-channel.js +51 -0
- package/src/runs/background/control-channel.js.map +1 -1
- package/src/runs/background/notify.d.ts +3 -0
- package/src/runs/background/notify.d.ts.map +1 -1
- package/src/runs/background/notify.js +3 -0
- package/src/runs/background/notify.js.map +1 -1
- package/src/runs/background/run-child-session.d.ts.map +1 -1
- package/src/runs/background/run-child-session.js +24 -7
- package/src/runs/background/run-child-session.js.map +1 -1
- package/src/runs/background/run-status.d.ts.map +1 -1
- package/src/runs/background/run-status.js +6 -0
- package/src/runs/background/run-status.js.map +1 -1
- package/src/runs/background/runner-aliases.d.ts +1 -0
- package/src/runs/background/runner-aliases.d.ts.map +1 -1
- package/src/runs/background/runner-aliases.js +6 -2
- package/src/runs/background/runner-aliases.js.map +1 -1
- package/src/runs/background/runner-child-launch.d.ts +1 -0
- package/src/runs/background/runner-child-launch.d.ts.map +1 -1
- package/src/runs/background/runner-child-launch.js +2 -0
- package/src/runs/background/runner-child-launch.js.map +1 -1
- package/src/runs/background/scheduled-runs.d.ts +2 -1
- package/src/runs/background/scheduled-runs.d.ts.map +1 -1
- package/src/runs/background/scheduled-runs.js +33 -16
- package/src/runs/background/scheduled-runs.js.map +1 -1
- package/src/runs/background/stale-run-reconciler.d.ts +1 -1
- package/src/runs/background/stale-run-reconciler.d.ts.map +1 -1
- package/src/runs/background/stale-run-reconciler.js +15 -2
- package/src/runs/background/stale-run-reconciler.js.map +1 -1
- package/src/runs/background/subagent-runner.d.ts +3 -0
- package/src/runs/background/subagent-runner.d.ts.map +1 -1
- package/src/runs/background/subagent-runner.js +49 -3
- package/src/runs/background/subagent-runner.js.map +1 -1
- package/src/runs/foreground/async-stop-action.d.ts.map +1 -1
- package/src/runs/foreground/async-stop-action.js +15 -1
- package/src/runs/foreground/async-stop-action.js.map +1 -1
- package/src/runs/foreground/command-action.d.ts +13 -0
- package/src/runs/foreground/command-action.d.ts.map +1 -0
- package/src/runs/foreground/command-action.js +38 -0
- package/src/runs/foreground/command-action.js.map +1 -0
- package/src/runs/foreground/execution.d.ts.map +1 -1
- package/src/runs/foreground/execution.js +27 -6
- package/src/runs/foreground/execution.js.map +1 -1
- package/src/runs/foreground/subagent-executor.d.ts +7 -5
- package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
- package/src/runs/foreground/subagent-executor.js +356 -192
- package/src/runs/foreground/subagent-executor.js.map +1 -1
- package/src/runs/shared/child-commands.d.ts +28 -0
- package/src/runs/shared/child-commands.d.ts.map +1 -0
- package/src/runs/shared/child-commands.js +250 -0
- package/src/runs/shared/child-commands.js.map +1 -0
- package/src/runs/shared/child-launch.d.ts +5 -1
- package/src/runs/shared/child-launch.d.ts.map +1 -1
- package/src/runs/shared/child-launch.js +15 -1
- package/src/runs/shared/child-launch.js.map +1 -1
- package/src/runs/shared/child-session.d.ts +13 -0
- package/src/runs/shared/child-session.d.ts.map +1 -1
- package/src/runs/shared/child-session.js +182 -19
- package/src/runs/shared/child-session.js.map +1 -1
- package/src/runs/shared/child-tool-plan.d.ts +4 -0
- package/src/runs/shared/child-tool-plan.d.ts.map +1 -1
- package/src/runs/shared/child-tool-plan.js +12 -5
- package/src/runs/shared/child-tool-plan.js.map +1 -1
- package/src/runs/shared/claude-code-adapter.d.ts +56 -0
- package/src/runs/shared/claude-code-adapter.d.ts.map +1 -1
- package/src/runs/shared/claude-code-adapter.js +138 -2
- package/src/runs/shared/claude-code-adapter.js.map +1 -1
- package/src/runs/shared/dynamic-fanout.js +2 -2
- package/src/runs/shared/dynamic-fanout.js.map +1 -1
- package/src/runs/shared/external-cli-preflight.d.ts +10 -0
- package/src/runs/shared/external-cli-preflight.d.ts.map +1 -1
- package/src/runs/shared/external-cli-preflight.js +50 -6
- package/src/runs/shared/external-cli-preflight.js.map +1 -1
- package/src/runs/shared/external-cli-runner.d.ts.map +1 -1
- package/src/runs/shared/external-cli-runner.js +4 -2
- package/src/runs/shared/external-cli-runner.js.map +1 -1
- package/src/runs/shared/mcp-config-sources.d.ts +1 -0
- package/src/runs/shared/mcp-config-sources.d.ts.map +1 -1
- package/src/runs/shared/mcp-config-sources.js +1 -1
- package/src/runs/shared/mcp-config-sources.js.map +1 -1
- package/src/runs/shared/mcp-direct-tool-allowlist.d.ts +28 -0
- package/src/runs/shared/mcp-direct-tool-allowlist.d.ts.map +1 -1
- package/src/runs/shared/mcp-direct-tool-allowlist.js +79 -2
- package/src/runs/shared/mcp-direct-tool-allowlist.js.map +1 -1
- package/src/runs/shared/model-resolution.d.ts +16 -2
- package/src/runs/shared/model-resolution.d.ts.map +1 -1
- package/src/runs/shared/model-resolution.js +39 -11
- package/src/runs/shared/model-resolution.js.map +1 -1
- package/src/runs/shared/model-scope.d.ts +2 -1
- package/src/runs/shared/model-scope.d.ts.map +1 -1
- package/src/runs/shared/model-scope.js +26 -10
- package/src/runs/shared/model-scope.js.map +1 -1
- package/src/runs/shared/parallel-utils.d.ts +4 -0
- package/src/runs/shared/parallel-utils.d.ts.map +1 -1
- package/src/runs/shared/parallel-utils.js.map +1 -1
- package/src/runs/shared/pi-spawn.d.ts +1 -10
- package/src/runs/shared/pi-spawn.d.ts.map +1 -1
- package/src/runs/shared/pi-spawn.js +7 -86
- package/src/runs/shared/pi-spawn.js.map +1 -1
- package/src/runs/shared/run-history.d.ts +47 -0
- package/src/runs/shared/run-history.d.ts.map +1 -1
- package/src/runs/shared/run-history.js +70 -0
- package/src/runs/shared/run-history.js.map +1 -1
- package/src/runs/shared/subagent-control.d.ts.map +1 -1
- package/src/runs/shared/subagent-control.js +30 -17
- package/src/runs/shared/subagent-control.js.map +1 -1
- package/src/runs/shared/subagent-prompt-runtime.d.ts +1 -0
- package/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
- package/src/runs/shared/subagent-prompt-runtime.js +14 -5
- package/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
- package/src/runs/shared/worktree.d.ts +1 -1
- package/src/runs/shared/worktree.d.ts.map +1 -1
- package/src/runs/shared/worktree.js +1 -1
- package/src/runs/shared/worktree.js.map +1 -1
- package/src/shared/disabled-features.d.ts +92 -0
- package/src/shared/disabled-features.d.ts.map +1 -0
- package/src/shared/disabled-features.js +113 -0
- package/src/shared/disabled-features.js.map +1 -0
- package/src/shared/extension-context.d.ts +9 -0
- package/src/shared/extension-context.d.ts.map +1 -1
- package/src/shared/extension-context.js +7 -0
- package/src/shared/extension-context.js.map +1 -1
- package/src/shared/required-child-extensions.d.ts +16 -1
- package/src/shared/required-child-extensions.d.ts.map +1 -1
- package/src/shared/required-child-extensions.js +37 -5
- package/src/shared/required-child-extensions.js.map +1 -1
- package/src/shared/settings.d.ts +1 -1
- package/src/shared/types.d.ts +26 -1
- package/src/shared/types.d.ts.map +1 -1
- package/src/shared/types.js +1 -1
- package/src/shared/types.js.map +1 -1
- package/src/slash/prompt-template-bridge.js +2 -2
- package/src/slash/prompt-template-bridge.js.map +1 -1
- package/src/slash/slash-commands.d.ts +2 -0
- package/src/slash/slash-commands.d.ts.map +1 -1
- package/src/slash/slash-commands.js +2 -2
- package/src/slash/slash-commands.js.map +1 -1
- package/src/slash/subagent-cost.d.ts.map +1 -1
- package/src/slash/subagent-cost.js +8 -4
- package/src/slash/subagent-cost.js.map +1 -1
- package/src/tui/render.d.ts +1 -1
- package/src/tui/render.d.ts.map +1 -1
- package/src/tui/render.js +59 -21
- package/src/tui/render.js.map +1 -1
- package/src/watchdog/diff-tool.d.ts +3 -1
- package/src/watchdog/diff-tool.d.ts.map +1 -1
- package/src/watchdog/diff-tool.js +20 -11
- package/src/watchdog/diff-tool.js.map +1 -1
- package/src/watchdog/register-child.js +2 -2
- package/src/watchdog/register-child.js.map +1 -1
- package/src/watchdog/register-main.js +2 -2
- package/src/watchdog/register-main.js.map +1 -1
- package/src/watchdog/review.d.ts +1 -1
- package/src/watchdog/review.d.ts.map +1 -1
- package/src/watchdog/review.js +1 -1
- package/src/watchdog/review.js.map +1 -1
- package/src/watchdog/turn-delta.js +1 -1
- package/src/watchdog/turn-delta.js.map +1 -1
- package/src/workflows/chat-progress.js +2 -2
- package/src/workflows/chat-progress.js.map +1 -1
- package/src/workflows/scripted-workflow.d.ts +8 -0
- package/src/workflows/scripted-workflow.d.ts.map +1 -1
- package/src/workflows/scripted-workflow.js +10 -2
- package/src/workflows/scripted-workflow.js.map +1 -1
- package/src/workflows/structured-workflow-scripts.d.ts +10 -0
- package/src/workflows/structured-workflow-scripts.d.ts.map +1 -0
- package/src/workflows/structured-workflow-scripts.js +166 -0
- package/src/workflows/structured-workflow-scripts.js.map +1 -0
- package/src/workflows/workflow-receipt.d.ts.map +1 -1
- package/src/workflows/workflow-receipt.js +10 -4
- package/src/workflows/workflow-receipt.js.map +1 -1
- package/src/workflows/workflow-resources.d.ts +13 -0
- package/src/workflows/workflow-resources.d.ts.map +1 -1
- package/src/workflows/workflow-resources.js +46 -16
- package/src/workflows/workflow-resources.js.map +1 -1
- package/src/workflows/workflow-reuse.d.ts +51 -0
- package/src/workflows/workflow-reuse.d.ts.map +1 -0
- package/src/workflows/workflow-reuse.js +103 -0
- package/src/workflows/workflow-reuse.js.map +1 -0
- package/src/workflows/workflow-revival.d.ts +32 -0
- package/src/workflows/workflow-revival.d.ts.map +1 -0
- package/src/workflows/workflow-revival.js +111 -0
- package/src/workflows/workflow-revival.js.map +1 -0
package/docs/missions.md
CHANGED
|
@@ -30,16 +30,11 @@ const created = subagent({
|
|
|
30
30
|
action: "mission.create",
|
|
31
31
|
mission: { title: "Ship auth refresh", objective: "Implement and validate token refresh" }
|
|
32
32
|
})
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
missionId: "<mission-id>"
|
|
36
|
-
})
|
|
33
|
+
// After a ```js workflow block that runs the approved auth refresh plan:
|
|
34
|
+
subagent({ workflow: true, missionId: "<mission-id>" })
|
|
37
35
|
|
|
38
36
|
// Or create and attach in one launch
|
|
39
|
-
subagent({
|
|
40
|
-
workflowScript: `return runs.run("main", { agent: "worker", task: "Implement the approved plan" })`,
|
|
41
|
-
mission: { title: "Ship auth refresh" }
|
|
42
|
-
})
|
|
37
|
+
subagent({ workflow: true, mission: { title: "Ship auth refresh" } })
|
|
43
38
|
```
|
|
44
39
|
|
|
45
40
|
### Goal missions
|
|
@@ -89,6 +84,10 @@ Durable schedules are enabled by default and stored per project under `.pi/subag
|
|
|
89
84
|
|
|
90
85
|
Create a one-shot schedule:
|
|
91
86
|
|
|
87
|
+
```js workflow
|
|
88
|
+
return runs.run("main", { agent: "reviewer", task: "Review the current diff." });
|
|
89
|
+
```
|
|
90
|
+
|
|
92
91
|
```ts
|
|
93
92
|
subagent({
|
|
94
93
|
action: "schedule.create",
|
|
@@ -96,29 +95,44 @@ subagent({
|
|
|
96
95
|
name: "Evening review",
|
|
97
96
|
at: "+30m",
|
|
98
97
|
baseRef: "refs/heads/release",
|
|
99
|
-
|
|
98
|
+
workflow: true
|
|
100
99
|
})
|
|
101
100
|
```
|
|
102
101
|
|
|
103
|
-
Create a fixed recurring workflow:
|
|
102
|
+
Create a fixed recurring workflow from a script file:
|
|
104
103
|
|
|
105
104
|
```ts
|
|
106
|
-
|
|
105
|
+
// .pi/workflows/backlog.js: return runs.run('main', { agent: 'worker', task: args.task })
|
|
106
|
+
subagent({ action: "schedule.create", id: "backlog", every: "6h", catchUp: "latest", workflow: "./.pi/workflows/backlog.js", args: { task: "Maintain core" } })
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
Fixed intervals support `m`, `h`, `d`, and `w` units and advance from the planned time without completion drift. Schedule arguments are normalized and persisted for exact replay after reload; do not put secrets in them.
|
|
109
|
+
Fixed intervals support `m`, `h`, `d`, and `w` units and advance from the planned time without completion drift. The schedule stores the script text read at creation, so later edits to the file do not change it. Schedule arguments are normalized and persisted for exact replay after reload; do not put secrets in them.
|
|
110
110
|
|
|
111
111
|
Create a quiet recurring workflow whose successful completions stay visible but do not wake the parent session:
|
|
112
112
|
|
|
113
113
|
```ts
|
|
114
|
-
subagent({ action: "schedule.create", id: "nightly-sweep", every: "24h", quiet: true,
|
|
114
|
+
subagent({ action: "schedule.create", id: "nightly-sweep", every: "24h", quiet: true, workflow: true })
|
|
115
115
|
```
|
|
116
116
|
|
|
117
117
|
Manage schedules with `schedule.list`, `schedule.show`, `schedule.history`, `schedule.pause`, `schedule.resume`, `schedule.run`, `schedule.run-due`, and `schedule.delete`.
|
|
118
118
|
|
|
119
|
+
Attach an existing mission to give each scheduled workflow access to the same durable `state.get/set`:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
subagent({ action: "schedule.create", id: "backlog", every: "6h", workflow: "./.pi/workflows/backlog.js", missionId: "<mission-id>" })
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The mission must be readable in the store resolved from the schedule's target `cwd` and current mission configuration. Creation checks it without changing its status. Every fire uses the normal explicit mission launch path, including after session restoration; missing or invalid records fail before workflow execution. Schedules accept only an existing `missionId`, not mission creation or updates. The script's fixed `args` and its mutable mission state remain separate.
|
|
126
|
+
|
|
127
|
+
Attachment uses ordinary mission lifecycle and retention rules. A non-goal mission can become terminal after a run, and the next fire reactivates it. `mission.close` does not pause the schedule; use `schedule.pause` or `schedule.delete` to stop future fires. A schedule does not protect its mission from terminal retention (default 200 records). If it is removed, later fires record `failed_launch` rather than creating a replacement. Open mission decisions and goal notice pause/budget settings do not gate schedule launches. Multiple schedules sharing a mission still have independent overlap controls; attachment does not serialize their workflows.
|
|
128
|
+
|
|
129
|
+
`missions.enabled:false` still permits explicit attachment; `disabledFeatures:["missions"]` rejects it. Each fire resolves the mission store using its target `cwd`, current mission configuration and Pi agent directory; the schedule does not pin the creation-time store. Sessions must resolve the same effective store to reuse the same state. Attachment does not search other worktrees or copy mission records; an explicitly shared `missions.directory` follows the existing storage rules.
|
|
130
|
+
|
|
131
|
+
Mission-bound definitions use schedule schema version 2 so older versions reject them instead of dropping the attachment. Existing unbound definitions keep version 1 and need no migration. A project using mission attachment should use a version that supports it in every scheduler session.
|
|
132
|
+
|
|
119
133
|
Behavior:
|
|
120
134
|
|
|
121
|
-
- Runs always launch async with fresh context
|
|
135
|
+
- Runs always launch async with fresh context. Without `missionId`, they disable mission creation and have no `state` global.
|
|
122
136
|
- An optional top-level `baseRef` selects the safe Git ref used by managed worktrees (default `HEAD`); it is persisted with the schedule and forwarded on every fire. The source checkout must still be clean.
|
|
123
137
|
- Definitions, bounded history, append-only events, and per-run receipts are stored with mode `0600`.
|
|
124
138
|
- `overlap` is currently fixed to `skip`; `catchUp` supports `latest` (default) and `none`.
|
package/docs/models.md
CHANGED
|
@@ -13,6 +13,8 @@ Builtin agents inherit your current Pi default model. This keeps new installs fr
|
|
|
13
13
|
|
|
14
14
|
Precedence, strongest first: per-run override → provider-scoped role override → `agentOverrides.<name>.model` → agent frontmatter `model` → `subagents.defaultModel` → the parent session model. A provider preference does not replace this order; it only resolves bare model ids when the active registry has more than one match. Fully qualified `provider/model` strings still win exactly.
|
|
15
15
|
|
|
16
|
+
On the two Claude Code adapters a model is Claude Code's own alias or id rather than a Pi child model, so a value set for one of them resolves nothing against the registry. `subagents.defaultModel` is ignored there, because it is a default for Pi children. An explicit `agentOverrides.<name>.model` or agent frontmatter `model` is passed on as given, and Claude Code reports it when it does not recognize the value. See [agents](agents.md).
|
|
17
|
+
|
|
16
18
|
Each launch resolves one model. Provider errors, including HTTP 429 responses, are returned from that model rather than selecting another one. Separately, a verified compaction abort after useful progress may continue the retained child session once on the same resolved model; this lifecycle recovery preserves work and is not model fallback.
|
|
17
19
|
|
|
18
20
|
Use `model: "inherit"` in agent frontmatter or `agentOverrides.<name>.model` to select the current parent session model explicitly.
|
|
@@ -122,7 +124,7 @@ If your provider rejects model IDs with thinking suffixes, set `subagents.disabl
|
|
|
122
124
|
|
|
123
125
|
### Thinking ceiling
|
|
124
126
|
|
|
125
|
-
Set `subagents.maxThinking` to enforce a hard maximum for every native Pi
|
|
127
|
+
Set `subagents.maxThinking` to enforce a hard maximum for every child that can ask for a thinking level: native Pi children and the two Claude Code adapters. The supported levels, from least to most thinking, are `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`:
|
|
126
128
|
|
|
127
129
|
```json
|
|
128
130
|
{
|
|
@@ -133,7 +135,7 @@ Set `subagents.maxThinking` to enforce a hard maximum for every native Pi child.
|
|
|
133
135
|
}
|
|
134
136
|
```
|
|
135
137
|
|
|
136
|
-
Requests above the ceiling fail before child startup; the setting covers frontmatter, `agentOverrides`, per-run overrides, parallel/chain children, nested launches, and resumed children. Project settings take precedence over user settings. External runners
|
|
138
|
+
Requests above the ceiling fail before child startup; the setting covers frontmatter, `agentOverrides`, per-run overrides, parallel/chain children, nested launches, and resumed children. Project settings take precedence over user settings. External runners keep their existing behavior, except the two Claude Code adapters, which translate the requested level into `--effort` and enforce the same ceiling. An enforced `subagents.modelScope` also covers them: the model id that will reach the CLI is checked, and a launch that pins no model fails closed.
|
|
137
139
|
|
|
138
140
|
## Extension defaults
|
|
139
141
|
|
|
@@ -206,7 +208,7 @@ To keep subagents inside a budget or compliance profile, enforce a model scope.
|
|
|
206
208
|
}
|
|
207
209
|
```
|
|
208
210
|
|
|
209
|
-
- `allow` is a list of glob patterns matched against the resolved `provider/id` (only `*` is special, case-insensitive). The literal `inherit` means the current parent session model.
|
|
211
|
+
- `allow` is a list of glob patterns matched against the resolved `provider/id` (only `*` is special, case-insensitive). The literal `inherit` means the current parent session model. The literal `scoped` means every model in the parent session's scoped-model set (pi's `/scoped-models`); when that set is empty, it means the same as `inherit`. Because `scoped` is reserved, it cannot match a provider literally named `scoped`.
|
|
210
212
|
- `agents.<name>` adds a second allow-list for that agent. The model must pass both the global list and the matching agent list, so an agent rule cannot weaken the global rule. Agent rules inherit `enforce` and `strict` when those fields are absent.
|
|
211
213
|
- A top-level `enforce: true` with only agent allow-lists restricts only those named agents. Unknown names are allowed so settings can be shared across projects and machines.
|
|
212
214
|
- Models you pass explicitly — the tool-call `model`, `--model`, or a clarify pick — error and abort the run.
|
|
@@ -216,7 +218,7 @@ To keep subagents inside a budget or compliance profile, enforce a model scope.
|
|
|
216
218
|
|
|
217
219
|
Model scope is policy only. It rejects or warns; it does not select a cheaper model. Set `agentOverrides.worker.model` to choose a worker model and use `modelScope.agents.worker` to prevent a per-run override from escaping that restriction.
|
|
218
220
|
|
|
219
|
-
`inherit`
|
|
221
|
+
`inherit` and `scoped` expand in the parent process at each launch. They are never sent to the child as model ids. A nested child therefore inherits its immediate parent's current model, not the original top-level model. `scoped` uses the scoped-model set at launch, so a mid-session `/scoped-models` change applies to the next child; background runs keep the set captured when the run started. Pi reports an empty set when the session is unscoped, either because nothing is configured or because no configured pattern matches an available model, and then lets the parent use every model. In that case `scoped` behaves exactly as `inherit`, which is narrower. If no parent model is available, an enforced `inherit` or `scoped` entry does not match and fails closed.
|
|
220
222
|
|
|
221
223
|
Project `modelScope` settings replace the complete user `modelScope`, as with the existing project-over-user settings precedence. Project settings are trusted and can therefore replace user restrictions.
|
|
222
224
|
|
|
@@ -247,3 +249,5 @@ The workflow:
|
|
|
247
249
|
- `/subagents-refresh-provider-models` writes a serialized provider model catalog with observed registry data, simple role-oriented classification, and live probe results from tiny one-shot `pi -p --model ... --no-tools` checks. The cache refreshes when missing or stale; use `--force` to ignore freshness and probe again immediately.
|
|
248
250
|
- `/subagents-generate-profiles` uses the provider catalog to produce quota and quality profiles.
|
|
249
251
|
- `/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.
|
|
252
|
+
|
|
253
|
+
Hand-authored profile entries can also set `machine` to a non-empty string or `false`. Loading and checking validate the whole saved profile, including machine syntax; malformed values are rejected before loading writes settings or checking probes models. Valid machine strings are trimmed and use the same limits as agent settings. `false` clears a machine pin, while an omitted field preserves an existing string pin when loading. Validation does not query the live machine catalog.
|
package/docs/observability.md
CHANGED
|
@@ -10,6 +10,8 @@ A foreground child is a pi session created inside the parent Pi process, not a s
|
|
|
10
10
|
|
|
11
11
|
A background child is a pi session created inside the detached runner process. The runner mirrors session events into `events.jsonl`, `output-<index>.log`, and the transcript. Interrupt and stop abort the child session; steer requests are delivered with the session's `steer` or `followUp`.
|
|
12
12
|
|
|
13
|
+
Long-open `bash` attention notices identify the exact tool call and include status and child-specific transcript commands. Each distinct long-open call notifies once. Inspect the running command and recent output before intervening: development servers and watch commands may intentionally never return, while builds and tests may legitimately take time. A queued steer does not cancel the shell command. For local native Pi children explicitly granted `subagent_command`, `command.yield` returns control while the selected command remains managed; `command.cancel` stops that command without interrupting the child. Query `command.status` to confirm its terminal state. Unsupported children require the existing run-scoped interrupt/resume path, which may affect siblings. See [command controls](tool-reference.md#command-controls).
|
|
14
|
+
|
|
13
15
|
Live progress shows compact detail for single, chain, and parallel modes: a bounded one-line task, current tool, recent output, token counts, aggregate cost, duration, activity freshness, current-tool duration, and chain graph metadata when available. Workflow `label` metadata wins over raw task text in compact multi-child cards.
|
|
14
16
|
|
|
15
17
|
Press Pi's configured expand key (`Ctrl+O` by default) to expand the full streaming view with complete output per step.
|
|
@@ -53,9 +55,11 @@ or keyboard shortcuts is needed. The summary counts the widget's tracked runs,
|
|
|
53
55
|
including workflow parents and children, rather than unique agents.
|
|
54
56
|
|
|
55
57
|
Folding stays in effect across progress updates and does not change Pi's global
|
|
56
|
-
expand setting, run execution, or completion notifications.
|
|
57
|
-
|
|
58
|
-
widget
|
|
58
|
+
expand setting, run execution, or completion notifications. Set
|
|
59
|
+
`asyncWidgetCollapsed: true` in the extension configuration to start each newly
|
|
60
|
+
mounted widget folded. Task rows, drag and wheel events, and modifier clicks are left
|
|
61
|
+
unhandled. The state resets when the widget is removed or Pi reloads. Regular mode
|
|
62
|
+
keeps the existing keyboard controls.
|
|
59
63
|
|
|
60
64
|
### Reducing status display noise
|
|
61
65
|
|
|
@@ -74,6 +78,7 @@ For compact chat results with FleetView as the only live editor surface, merge t
|
|
|
74
78
|
- `inlineToolDisplay: "summary"` keeps one static result row per call, alongside its call heading. A completed status query is not proof that the queried child has finished.
|
|
75
79
|
- `fleetView: true` retains live progress. Open `/subagents-fleet` for details instead of repeatedly requesting status just to watch progress. Pi's expand key does not expand summary results; keep `"rich"` if you want expandable inline output.
|
|
76
80
|
- `asyncWidget: false` hides only the additional under-editor async widget, leaving FleetView available. This configuration reduces visible surfaces; it does not guarantee ordering relative to other extensions.
|
|
81
|
+
- `asyncWidgetCollapsed: true` starts each newly mounted async widget as a one-line live status summary; click its header to expand it.
|
|
77
82
|
|
|
78
83
|
Thanks to [DraconDev](https://github.com/DraconDev) for reporting the display noise and suggesting summary mode in [#1931](https://github.com/nicobailon/pi-subagents/issues/1931).
|
|
79
84
|
|
|
@@ -212,7 +217,7 @@ subscribe to the `subagent:child-status` event advertised by RPC `ping` as
|
|
|
212
217
|
`version: 1`, `runId`, `childId`, `status` (`"started"`, `"stopping"`, or
|
|
213
218
|
`"stopped"`), `ts`, and optional child metadata such as `asyncDir`, `stepIndex`,
|
|
214
219
|
`agent`, `childRunId`, `workflowKey`, `phase`, and `label`. Async
|
|
215
|
-
|
|
220
|
+
Workflow script roots emit `"started"` once the keyed child has a concrete
|
|
216
221
|
launch identity; `childId` and `workflowKey` are the stable workflow key, while
|
|
217
222
|
`stepIndex` is only a convenience projection for the current status snapshot.
|
|
218
223
|
These events are observer hints only. They can duplicate across the live event
|
|
@@ -311,7 +316,7 @@ Async events:
|
|
|
311
316
|
- `subagent:async-started`
|
|
312
317
|
- `subagent:async-complete`
|
|
313
318
|
|
|
314
|
-
For regular async starts, the `subagent:async-started` payload includes redacted `task` and `goal` prompt fields. Async
|
|
319
|
+
For regular async starts, the `subagent:async-started` payload includes redacted `task` and `goal` prompt fields. Async workflow script roots emit the same event with `mode: "workflow"` after their initial `status.json` is durable; workflow roots can omit `task`, and any included prompt fields are redacted. Their keyed children are then announced dynamically through `subagent:child-status`. Companion UI extensions can combine those hints with the authoritative live lifecycle artifacts under `asyncDir` without scraping terminal output.
|
|
315
320
|
|
|
316
321
|
Intercom delivery events:
|
|
317
322
|
|
package/docs/tool-reference.md
CHANGED
|
@@ -8,13 +8,15 @@ Call `{ action: "guide", topic: "tool-reference" }` for this reference or `topic
|
|
|
8
8
|
|
|
9
9
|
## Execution examples
|
|
10
10
|
|
|
11
|
-
Chaining is code-driven through
|
|
11
|
+
Chaining is code-driven through a workflow script. Write the script as one ```` ```js workflow ```` fenced block in the reply, then call `subagent({ workflow: true, ... })` in the same reply. A `workflow` string containing `/` is a script file, and any other string is a named resource. `workflowScript` and `workflowScriptPath` were removed; use these forms instead.
|
|
12
12
|
|
|
13
|
-
Use `{
|
|
13
|
+
Use `await runs.run(...)` for sequential steps and `await runs.all([{ key, agent, task }, ...])` for ordinary parallel fanout. `runs.all` resolves to an ordered array, not a key map, so use indexes, destructuring, or `.map(...)`, not `results.<key>`. Do not read `.output` from an unawaited `runs.run` launch. Stored `runs.run` promises are only for the advanced rolling fanout pattern under [Workflow steering](#workflow-steering), where every promise is later observed with direct `await`, `Promise.race`, or `Promise.all`. Legacy top-level `chain`, `tasks`, and `parallel` inputs are not supported, except that `disabledFeatures: ["workflow-scripts"]` replaces workflow scripts with top-level `chain` and `tasks` (see [configuration](configuration.md#chain-and-tasks-without-workflow-scripts)). Helper functions must be plain functions or explicit Promise chains. Nested `async function` helpers, async arrows, and async methods are rejected so child-launch tracking stays portable across Node and Bun. For permission-sensitive host calls, use an extension-owned named resource such as `{ workflow: "run-ci", args: { command: "npm test" } }`; raw scripts (`workflow: true` or a script path) have unknown resource provenance and cannot call `runs.host`. A resolved resource may internally use `runs.host(key, { kind: "command", command, timeoutMs, output?, role?, provider? })` within its authority ceiling; there is no per-step `cwd`, and commands and relative output paths use the workflow `cwd`. Set `cwd` on the outer `subagent({...})` request instead, or put a trusted directory change in the command (for example, `cd /path/to/worktree && npm test`).
|
|
14
14
|
|
|
15
|
-
Use `
|
|
15
|
+
Use `{ action: "validate", workflow: true }` (or a script path) to check statically decidable syntax and structure without launching children. It returns `{ ok, errors }` and fails the tool call when `ok` is false. Literal child `baseRef` values are checked against the runtime ref policy. Dynamic keys and values remain subject to runtime checks; static validation does not guess them.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Use `workflow: "./path/to/script.js"` to load the same JavaScript statement body from a file. Relative paths resolve against the request `cwd`, and absolute paths pass through. The host reads the file before validation, scheduling, or sandbox execution. The workflow sandbox still has no filesystem access. Missing, unreadable, and empty files fail as file input errors.
|
|
18
|
+
|
|
19
|
+
Raw reply-block and file-backed scripts accept bounded plain-JSON `args`, including during `validate` and `schedule.create`. Omitted raw args become `{}`; supplied args are deeply frozen in the sandbox. Normalized args persist in run and schedule evidence for diagnosis and exact replay, so never include secrets. Args are data only and do not grant `runs.host` authority.
|
|
18
20
|
|
|
19
21
|
For permission-extension interoperability, use one of the package-owned named resources with bounded `args` instead of caller-supplied workflow text:
|
|
20
22
|
|
|
@@ -23,66 +25,41 @@ For permission-extension interoperability, use one of the package-owned named re
|
|
|
23
25
|
{ workflow: "run-ci", args: { command: "npm test" } }
|
|
24
26
|
```
|
|
25
27
|
|
|
26
|
-
The host resolves the script and authority internally and records bounded provenance in workflow details and receipts. Named resources cannot be combined with `agent
|
|
28
|
+
The host resolves the script and authority internally and records bounded provenance in workflow details and receipts. Named resources cannot be combined with `agent` or `task`; user/project resource registries are not part of this first slice.
|
|
27
29
|
|
|
28
30
|
```js
|
|
29
|
-
{
|
|
30
|
-
{ action: "validate",
|
|
31
|
-
{ action: "schedule.create", every: "6h",
|
|
31
|
+
{ workflow: "./workflows/review.js", args: { target: "src/workflows" }, cwd: "/path/to/project" }
|
|
32
|
+
{ action: "validate", workflow: "./workflows/review.js", args: { target: "src/workflows" } }
|
|
33
|
+
{ action: "schedule.create", every: "6h", workflow: "./workflows/review.js", args: { target: "src/workflows" } }
|
|
32
34
|
```
|
|
33
35
|
|
|
34
|
-
```js
|
|
36
|
+
Each script below is the ```` ```js workflow ```` block of a reply that then calls `subagent({ workflow: true })`:
|
|
37
|
+
|
|
38
|
+
```js workflow
|
|
35
39
|
// One child; return the child promise explicitly
|
|
36
|
-
|
|
40
|
+
return runs.run("main", { agent: "scout", task: "Analyze the auth flow" });
|
|
41
|
+
```
|
|
37
42
|
|
|
43
|
+
```js workflow
|
|
38
44
|
// Sequential workflow
|
|
39
|
-
{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
` }
|
|
45
|
+
const scan = await runs.run("scan", { agent: "scout", task: "Analyze auth" });
|
|
46
|
+
return (await runs.run("implement", { agent: "worker", task: "Implement from: " + scan.output })).output;
|
|
47
|
+
```
|
|
43
48
|
|
|
49
|
+
```js workflow
|
|
44
50
|
// Parallel workflow
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return results.map(result => result.output);
|
|
51
|
-
` }
|
|
51
|
+
const results = await runs.all([
|
|
52
|
+
{ key: "backend", agent: "reviewer", task: "Review backend" },
|
|
53
|
+
{ key: "frontend", agent: "reviewer", task: "Review frontend" }
|
|
54
|
+
]);
|
|
55
|
+
return results.map(result => result.output);
|
|
52
56
|
```
|
|
53
57
|
|
|
54
58
|
### Parallel sequential lanes
|
|
55
59
|
|
|
56
|
-
Use `runs.lanes(lanes)` inside a
|
|
60
|
+
Use `runs.lanes(lanes)` inside a workflow script when several independent lanes each have ordered stages. This helper composes the existing workflow child runner; it does not add a top-level `lanes` parameter or a second persistence/cleanup system.
|
|
57
61
|
|
|
58
|
-
|
|
59
|
-
{ workflowScript: `
|
|
60
|
-
const board = await runs.lanes([
|
|
61
|
-
{ key: "api", stages: [
|
|
62
|
-
{ key: "writer", agent: "worker", task: "Implement the API change" },
|
|
63
|
-
{ key: "challenge", resume: "previous", task: "Challenge the implementation" },
|
|
64
|
-
{ key: "review", agent: "reviewer", task: "Review the API lane" }
|
|
65
|
-
] },
|
|
66
|
-
{ key: "ui", stages: [
|
|
67
|
-
{ key: "writer", agent: "worker", task: "Implement the UI change" },
|
|
68
|
-
{ key: "review", agent: "reviewer", task: "Review the UI lane" }
|
|
69
|
-
] }
|
|
70
|
-
]);
|
|
71
|
-
return board.map((lane) => ({
|
|
72
|
-
key: lane.key,
|
|
73
|
-
state: lane.state,
|
|
74
|
-
failedStage: lane.failedStage,
|
|
75
|
-
stages: lane.stages.map((stage) => ({
|
|
76
|
-
key: stage.key,
|
|
77
|
-
state: stage.state,
|
|
78
|
-
ok: stage.ok,
|
|
79
|
-
runId: stage.runId,
|
|
80
|
-
outputReference: stage.outputReference,
|
|
81
|
-
verdict: stage.verdict
|
|
82
|
-
}))
|
|
83
|
-
}));
|
|
84
|
-
` }
|
|
85
|
-
```
|
|
62
|
+
See the [staged-lane example](workflows.md#parallel-sequential-lanes) (guide topic `workflows`).
|
|
86
63
|
|
|
87
64
|
The first stage of each lane is launched by one existing `runs.all(...)` batch. Later stages run in lane order. Set `resume: "previous"` on a later stage to continue the preceding retained child; the helper requires that child’s returned `runId` and delegates to the existing resume checks. Stage keys are local to the lane, and generated child keys are `<lane>.<stage>`.
|
|
88
65
|
|
|
@@ -98,8 +75,8 @@ The complete plain-JSON inventory is validated before the first launch (maximum
|
|
|
98
75
|
| `topic` | `overview \| workflows \| agents \| missions \| observability \| tool-reference \| configuration \| models \| watchdog \| extension-api \| council` | `overview` | Packaged guide topic for `action: "guide"`. |
|
|
99
76
|
| `config` | object/string | - | Agent config for management create/update. |
|
|
100
77
|
| `context` | `fresh \| fork \| profile` | global or per-agent default, else `fresh` | Explicit `fresh` or `fork` overrides every workflow child. `profile` requires the selected agent's declared `defaultContext` and ignores config `defaultSubagentContext`; missing agent defaults fail. When omitted, [`defaultSubagentContext`](configuration.md#defaultsubagentcontext) wins over each agent's `defaultContext`; implicit fork falls back to fresh without a persisted parent session and leaf. Explicit fork is strict. Packaged `worker` defaults to `fresh`; packaged `oracle` and `advisor` default to `fork`. |
|
|
101
|
-
| `model` | string | agent default | Call `{action:"models"}` first and copy an exact `provider/id`; bare ids resolve only if unique, and agent names are not model ids. A suffix such as `provider/id:high` (`off/minimal/low/medium/high/xhigh/max`) overrides agent thinking. The `thinking` field is only for `watchdog.configure`, ignored on dispatch. |
|
|
102
|
-
| `missionId` | string | - | Attach a workflow to an existing project mission
|
|
78
|
+
| `model` | string | agent default | Call `{action:"models"}` first and copy an exact `provider/id`; bare ids resolve only if unique, and agent names are not model ids. A suffix such as `provider/id:high` (`off/minimal/low/medium/high/xhigh/max`) overrides agent thinking. The `thinking` field is only for `watchdog.configure`, ignored on dispatch. On the `claude-code` and `claude-code-writer` adapters the model is Claude Code's own alias or id, and the same suffix becomes its `--effort`, bounded by `subagents.maxThinking` and by an enforced `subagents.modelScope`. |
|
|
79
|
+
| `missionId` | string | - | Attach a workflow, including each fire of `schedule.create`, to an existing project mission. Scheduled attachment uses ordinary lifecycle and retention rules. |
|
|
103
80
|
| `mission` | object/false | auto-create | Override the default enclosing mission with `{ title \| summary, objective?, goal?, budget?, labels? }`. Set exactly one non-empty `title` or `summary`; `objective` and `labels` are optional. `goal` may only be `true`, requires `budget.tokens`, and enables continuation notices. Pass `false` for an intentionally ephemeral workflow with no mission for it or its children and no `state` global. Explicit mission persistence failures are strict. |
|
|
104
81
|
| `handoffPath` | string | - | Aggregate handoff manifest for `action: "worktree.discard"` or lane evidence actions, or optional explicit metadata for `action: "worktree.cleanup"`. |
|
|
105
82
|
| `repo` | string | runtime cwd | Repository path for `action: "worktree.cleanup"`; plan mode only. The configured worktree base filters candidates by their per-project folder under it but never discovers them. |
|
|
@@ -114,19 +91,19 @@ The complete plain-JSON inventory is validated before the first launch (maximum
|
|
|
114
91
|
| `agentScope` | `user \| project \| both` | `both` | Agent discovery scope. Project wins on collisions. |
|
|
115
92
|
| `capabilities` | boolean | `false` | With `action: "list"`, return compact prompt-free rows and `details.agentCapabilities` machine-readable records for each agent's declared/default routing capabilities. External CLI rows also include their command and passive local availability. |
|
|
116
93
|
| `async` | boolean | default-on | Background execution. Workflows default to background. `async:false` blocks the parent until completion. A local foreground child runs inside the parent Pi process and never loads the parent's ambient extensions, but it does inherit the providers those extensions registered. A pane-native remote foreground child instead uses the remote machine's provider discovery and configuration. Agents that need MCP tools (`mcpDirectTools`, or MCP tools from an ambient adapter such as pi-mcp-adapter) must run as background children, which load them inside the detached runner process. |
|
|
117
|
-
| `chatProgress` | `auto \| off \| live-card` | `auto` |
|
|
94
|
+
| `chatProgress` | `auto \| off \| live-card` | `auto` | Workflow chat projection. `auto` renders a live in-chat card only for watched foreground workflows in the same Git repository, including managed worktrees; it is off otherwise. Explicit `live-card` requires `async:false` and the same Git repository. Async workflows have no inline live card, so omit `chatProgress` or use `auto`/`off`; use `async:false` only when the parent must block. |
|
|
118
95
|
| `isolation` | `none \| worktree` | - | Workflow child isolation. `none` runs in the shared cwd and does not need Git. `worktree` requires a managed Git worktree. Do not combine it with a contradictory `worktree` value. |
|
|
119
|
-
| `baseRef` | string | `HEAD` | `HEAD` or a supported named ref such as `refs/heads/release`, `refs/tags/v1`, or `origin/main`. Full 40/64-character commit IDs and revision expressions such as `HEAD~1` are unsupported. The ref must resolve to a commit at worktree allocation; omitted values default to `HEAD` resolved at that time. Source-checkout cleanliness is still checked. For
|
|
96
|
+
| `baseRef` | string | `HEAD` | `HEAD` or a supported named ref such as `refs/heads/release`, `refs/tags/v1`, or `origin/main`. Full 40/64-character commit IDs and revision expressions such as `HEAD~1` are unsupported. The ref must resolve to a commit at worktree allocation; omitted values default to `HEAD` resolved at that time. Source-checkout cleanliness is still checked. For a workflow script, set it on the outer request as a default or on an individual `runs.run`/`runs.all` child to override it. |
|
|
120
97
|
| `timeoutMs` / `maxRuntimeMs` | number | config `timeoutMs`, else 30 min foreground / single-agent async | Optional run-level max runtime in milliseconds. Both aliases may be supplied only when their values agree. When omitted, the global [`timeoutMs`](configuration.md#timeoutms) config provides the default; absent that, foreground and plain single-agent async runs fall back to 30 minutes, while composite async runs (chains, parallel tasks, workflows) stay unbounded at the top level. Expiration of this run-level deadline is terminal. |
|
|
121
98
|
| `toolTimeoutMs` | number | fast-tool default | Optional positive hard per-tool-call deadline in milliseconds. Precedence: call value → agent frontmatter → config → `PI_SUBAGENT_TOOL_TIMEOUT_MS`. The timer starts on `tool_execution_start`, clears on the matching `tool_execution_end`, and terminates the run with `timedOut: true` if the tool remains open. When omitted, known-fast built-in tools get a five-minute default; long-running tools get attention notices but no hard default. It never extends the run deadline; `contact_supervisor`, `intercom`, and `bg_wait` are exempt. |
|
|
122
99
|
| `checkpointBeforeDeadlineMs` | number | none | Async single-agent runs only. The runner requests that the child "checkpoint and stop" this many milliseconds before the run deadline (finish the current tool call, report changed files, build/test state, remaining work, commit/PR state; start no new work). This best-effort steer uses the normal steering lifecycle at the next tool boundary, so the receipt is visible in status and events; the ordinary deadline kill still applies. Precedence: call value → config `checkpointBeforeDeadlineMs`. Disarmed when the deadline leaves under one second before the checkpoint. |
|
|
123
100
|
| `toolBudget` | object | none | Optional child tool-call budget `{ soft?, hard, block? }`: `hard` is a positive integer and `soft`, if set, is a positive integer no greater than `hard`. At `soft` the child is nudged to finalize. After `hard`, configured tools are blocked; `block` defaults to `read`, `grep`, `find`, and `ls`, and accepts either a nonempty array of tool names or `"*"` for every tool call. Final assistant text is never blocked. |
|
|
124
101
|
| `usageBudget` | object | none | Optional root-only reported-usage budget `{ tokens?: { soft?, hard }, costUsd?: { soft?, hard } }`. Include at least one metric; each `hard` must be positive and each optional `soft` positive and no greater than its `hard`. Soft limits are status-only. Hard limits prevent later child launches after reported usage is reconciled; already-running children are not stopped and no reservations are made. |
|
|
125
102
|
| `extensionBindings` | object | none | Child-only plain JSON keyed by namespaces like `package.name/1` (positive version): at most 16 namespaces, nesting depth 16, 256 total object properties, and 16 KiB of canonical UTF-8 JSON. Native Pi launches only; external runners and retained resumes reject it. |
|
|
126
|
-
| `preflight` | object | none | Advisory lane hints for `
|
|
103
|
+
| `preflight` | object | none | Advisory lane hints for raw scripts (`workflow: true` or a script path) only; not accepted with named workflows or direct children. See [bounded workflows](workflows.md#opt-in-bounded-workflows). |
|
|
127
104
|
| `cwd` | string | runtime cwd | Override working directory. With `machine`, the directory on that machine. |
|
|
128
105
|
| `machine` | string | - | Herdr saved machine (label or profile id) for external-cli agents; see [agents.md](agents.md#running-external-cli-agents-on-a-herdr-saved-machine). |
|
|
129
|
-
| `maxOutput` | object | none | Final output truncation limits `{ bytes?, lines? }`. For child runs it is only applied when set; there is no default cap on the inline path, so use `outputMode: "file-only"` for large outputs. For
|
|
106
|
+
| `maxOutput` | object | none | Final output truncation limits `{ bytes?, lines? }`. For child runs it is only applied when set; there is no default cap on the inline path, so use `outputMode: "file-only"` for large outputs. For workflow script results, the Return, Emitted, and Console sections are always capped, at 200 KB / 5000 lines unless `maxOutput` sets other limits. |
|
|
130
107
|
| `artifacts` | boolean | true | Write debug artifacts. |
|
|
131
108
|
| `includeProgress` | boolean | false | Include full progress in result. |
|
|
132
109
|
| `share` | boolean | false | Upload session export to GitHub Gist. |
|
|
@@ -156,26 +133,24 @@ The workflow trace records the attempt and receipt. Always await, return, or inc
|
|
|
156
133
|
|
|
157
134
|
For advanced rolling fanout, keep the launched `runs.run` promises in ordinary JavaScript data only when every promise is later observed with direct `await`, `Promise.race`, or `Promise.all`. `Promise.race` gives the next completed child, `runs.steer` can challenge a still-running keyed sibling, and `Promise.all` collects the rest. No separate `runs.start`, `runs.next`, or `runs.collect` API is exposed.
|
|
158
135
|
|
|
159
|
-
```js
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
return { first: first.key, rest: rest.map((child) => child.key), receipt };
|
|
171
|
-
` }
|
|
136
|
+
```js workflow
|
|
137
|
+
let pending = [
|
|
138
|
+
{ key: "writer", promise: runs.run("writer", { agent: "worker", task: "Draft the fix" }).then((result) => ({ key: "writer", result })) },
|
|
139
|
+
{ key: "reviewer", promise: runs.run("reviewer", { agent: "reviewer", task: "Review likely risks" }).then((result) => ({ key: "reviewer", result })) }
|
|
140
|
+
];
|
|
141
|
+
const first = await Promise.race(pending.map((child) => child.promise));
|
|
142
|
+
pending = pending.filter((child) => child.key !== first.key);
|
|
143
|
+
const target = pending[0];
|
|
144
|
+
const receipt = await runs.steer(target.key, "Use this early review:\n" + first.result.output, { mode: "auto" });
|
|
145
|
+
const rest = await Promise.all(pending.map((child) => child.promise));
|
|
146
|
+
return { first: first.key, rest: rest.map((child) => child.key), receipt };
|
|
172
147
|
```
|
|
173
148
|
|
|
174
149
|
### Output mode details
|
|
175
150
|
|
|
176
151
|
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.
|
|
177
152
|
|
|
178
|
-
In
|
|
153
|
+
In a workflow script, 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.
|
|
179
154
|
|
|
180
155
|
The `output` field is the API binding; a filename mentioned in task text (for example, `Write your findings to exactly this path: report.md`) is only instruction and does not override runtime routing. When a later workflow step or parent needs a durable file, set `output` on `runs.run`/`runs.all` and return the child’s `outputReference`, `outputPathMapping`, or `artifactPaths`; arbitrary literal strings returned by workflow JavaScript are not rewritten. Omitted child output may use a managed aggregate-derived sibling path.
|
|
181
156
|
|
|
@@ -185,20 +160,18 @@ Workflows get `await state.get(key)` and `await state.set(key, value)` through t
|
|
|
185
160
|
|
|
186
161
|
Completed workflow children from the current parent session stay addressable as retained children. `{ action: "children.list" }` lists up to the last 10 with their run ids and explicit `resumable` or `not resumable` state. This workflow-only roster is not an exhaustive list of direct native children. Resume only rows reported `resumable`. When the exact run id of an intended direct child is known, inspect it with `{ action: "status", id: "<run-id>" }`; if status identifies the candidate, attempt `{ action: "resume", id: "<run-id>", message: "..." }`. Resume performs the authoritative eligibility check and may reject the attempt. Start a same-role fallback challenge, labeled as fallback, only when no known candidate exists or resume rejects eligibility. A later workflow continues a resumable child by passing `resume` instead of `agent`:
|
|
187
162
|
|
|
188
|
-
```js
|
|
189
|
-
{
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return writer;
|
|
196
|
-
` }
|
|
163
|
+
```js workflow
|
|
164
|
+
let writer = await runs.run("implement", { agent: "worker", task: "Implement the accepted contract" });
|
|
165
|
+
for (const pass of [1, 2]) {
|
|
166
|
+
if (!writer.runId) throw new Error("writer did not return a retained run id");
|
|
167
|
+
writer = await runs.run("followup-" + pass, { resume: writer.runId, task: "Revisit pass " + pass + ": " + writer.output });
|
|
168
|
+
}
|
|
169
|
+
return writer;
|
|
197
170
|
```
|
|
198
171
|
|
|
199
172
|
Each workflow key identifies one result lane. Use a new stable workflow key for every distinct retained resume pass; same-key calls are reused only when launch parameters are identical, and incompatible parameters are rejected.
|
|
200
173
|
|
|
201
|
-
Inside
|
|
174
|
+
Inside a workflow script, `await runs.run(key, { resume, task })` waits for the revived child to finish and returns its completed output and new `runId`. Each resume can return a new retained run id, so loops must continue from the latest returned `runId`. Top-level `{ action: "resume" }` remains detached and returns a background-run receipt. When it revives a failed async workflow child (or a failed revival of one), the revived run becomes that key's latest run: workflow `status` adds `Revived → <run>: <state>` under the key, and keyed `resume: { workflowRunId, key, latest: true }` continues from it with lineage `[original, revived, ...]`. If the workflow was still running, the receipt it writes when it ends adds the revived runs to the key's lineage, and its completion notice keeps the child's failed result with the same `Revived →` line. The workflow's return value and state are not changed, notices already delivered are not rewritten, and a key accepts at most 16 chained revivals. Reviving a completed, paused, or stopped child does not change its key.
|
|
202
175
|
|
|
203
176
|
For a simple implementation challenge outside a workflow script, send the challenge through `subagent({ action: "resume", id: "<retained-writer-run>", message: "Reconsider the implementation and make any better current-scope change." })` when `children.list` reports that retained writer as `resumable`, or attempt it after exact-id status inspection identifies a known direct-child candidate. Status is advisory; resume authoritatively checks eligibility and may reject missing recovery requirements. If there is no known candidate or resume rejects eligibility, start a same-role fallback challenge and record why it is a fallback. Use workflow `runs.run({ resume })` only when the script must await the revived writer output before the next step. Do not use `steer` as the sole challenge action for a completed retained child; `steer` with `mode: "follow_up"` only queues text for the next `resume`.
|
|
204
177
|
|
|
@@ -273,7 +246,7 @@ Rules:
|
|
|
273
246
|
|
|
274
247
|
### Schedule controls
|
|
275
248
|
|
|
276
|
-
Use `schedule.create` with `
|
|
249
|
+
Use `schedule.create` with `workflow: true` or a script path, not a direct child. `at` accepts a delay like `+10m` or an ISO timestamp with timezone; `every` accepts fixed intervals. `sessionOnly:true` binds restoration/execution to the creating session file; omitted/false is project-wide. Recurring `quiet:true` keeps successful automatic fires visible without a parent turn; failed, stopped or paused runs still wake the parent. One-shot `at` and manual `schedule.run` stay noisy unless that launch passes `quiet:true`. An optional `missionId` attaches an existing mission on every fire and exposes its workflow state, using ordinary mission lifecycle and retention rules; `mission.close` does not pause the schedule. See [missions and schedules](missions.md#schedules) for examples and list/show/history/pause/resume/run/run-due/delete. Calendar selectors (`on`, `timezone`) are deferred. `baseRef` resolves only at worktree allocation and still requires a clean source checkout.
|
|
277
250
|
|
|
278
251
|
## Lane merge evidence and cleanup eligibility
|
|
279
252
|
|
|
@@ -347,6 +320,31 @@ subagent({ action: "doctor" })
|
|
|
347
320
|
- Inside child-safe fanout mode, bare `status` requires an id when no local foreground run is active, so children cannot enumerate unrelated top-level async runs.
|
|
348
321
|
- Bare `interrupt` still targets only the visible top-level run; interrupting a nested run requires its explicit nested id.
|
|
349
322
|
|
|
323
|
+
### Command controls
|
|
324
|
+
|
|
325
|
+
Command controls target direct local native Pi children that explicitly select both `bash` and `subagent_command`, in foreground or async runs. They require the owning parent session, a run `id`, an explicit `index` for multi-child runs, and the exact `toolCallId` for mutations. Nested, external, and custom shell backends do not expose this controller. Custom bash extensions keep their own registered `subagent_command` tool. If a custom bash backend does not provide that tool, an explicitly required `subagent_command` remains available and reports an unsupported-backend error. Native supervisor command controls are unavailable for custom backends.
|
|
326
|
+
|
|
327
|
+
```ts
|
|
328
|
+
subagent({ action: "command.status", id: "<run-id>", index: 0 })
|
|
329
|
+
subagent({ action: "command.yield", id: "<run-id>", index: 0, toolCallId: "<call-id>" })
|
|
330
|
+
subagent({ action: "command.cancel", id: "<run-id>", index: 0, toolCallId: "<call-id>" })
|
|
331
|
+
subagent({ action: "command.status", id: "<run-id>", index: 0, toolCallId: "<call-id>" })
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
`command.yield` releases the selected blocking tool call without restarting the process. `command.cancel` aborts only that command through Pi's native bash cancellation; the child receives a tool error and can continue. `cancel_requested` acknowledges the request, while `cancelled` confirms the backend settled. A stale id never targets a later command. Run-scoped `interrupt` remains separate.
|
|
335
|
+
|
|
336
|
+
Enable command controls by including both `bash` and `subagent_command` in the agent or call's `tools` allowlist. Tool ceilings and `excludeTools` still apply. Without this explicit selection, bash keeps its original tool schema and backend; no command controller, inbox watcher, or command-state writes are added. Inside an enabled child:
|
|
337
|
+
|
|
338
|
+
```ts
|
|
339
|
+
bash({ command: "npm run dev", yieldTimeMs: 1000 })
|
|
340
|
+
subagent_command({ action: "status", toolCallId: "<returned-call-id>", waitMs: 1000 })
|
|
341
|
+
subagent_command({ action: "cancel", toolCallId: "<returned-call-id>", waitMs: 1000 })
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
`yieldTimeMs` and `waitMs` range from 0 to 30,000 milliseconds. Omitting `yieldTimeMs` preserves completion-waiting behavior. Yielded handles are not successful exits. Status includes running/yielded/cancel-requested states and completed/failed/cancelled terminal states, a bounded output tail, and Pi's full-output file path when available. Recent terminal history retains 20 commands; active commands remain tracked.
|
|
345
|
+
|
|
346
|
+
Commands remain owned by the child session. Normal completion with unfinished commands cancels them and fails the run. Interrupt, stop, timeout, and disposal clean up owned commands. Controls do not transfer processes out of the child or create detached services. Native bash `timeout` remains command-scoped; `toolTimeoutMs` covers an open tool call and does not become a yielded process deadline.
|
|
347
|
+
|
|
350
348
|
### resume
|
|
351
349
|
|
|
352
350
|
`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.
|
|
@@ -406,8 +404,8 @@ Prefer an inline JSON object. JSON-encoded object strings are tolerated only dur
|
|
|
406
404
|
|
|
407
405
|
When one host-run command is the entire verification contract, use the `gate` shorthand instead of a full `acceptance` object:
|
|
408
406
|
|
|
409
|
-
```js
|
|
410
|
-
|
|
407
|
+
```js workflow
|
|
408
|
+
return runs.run("impl", { agent: "worker", task: "Implement the fix", gate: "npm test" });
|
|
411
409
|
```
|
|
412
410
|
|
|
413
411
|
`gate` normalizes to verified acceptance with that single command, so the runtime executes it on the host and records the result as evidence. Verification results are memoized per tracked workspace state and effective environment, so an unchanged tree does not rerun the same command. Use explicit `acceptance.verify` when you need multiple commands, timeouts, or custom criteria. `gate` rejects `acceptance` except `false` (treated as omitted), and rejects retained `resume` items. With `worktree: true`, the gate runs inside the child's managed worktree.
|
|
@@ -416,12 +414,12 @@ When one host-run command is the entire verification contract, use the `gate` sh
|
|
|
416
414
|
|
|
417
415
|
A gate given as `{ command, output: "json" }` runs like a string gate, and then parses the command's stdout:
|
|
418
416
|
|
|
419
|
-
```js
|
|
420
|
-
|
|
417
|
+
```js workflow
|
|
418
|
+
return runs.run("review", {
|
|
421
419
|
agent: "reviewer", task: "Review the change", output: "reports/review.md", outputMode: "file-only",
|
|
422
420
|
gate: { command: "classify --report reports/review.md", output: "json",
|
|
423
421
|
schema: { type: "object", properties: { verdict: { enum: ["ok", "blocked"] } }, required: ["verdict"] } }
|
|
424
|
-
})
|
|
422
|
+
});
|
|
425
423
|
```
|
|
426
424
|
|
|
427
425
|
- The command runs after the child's output file is saved, in the child's cwd or managed worktree, so it can read what the child wrote.
|
|
@@ -516,8 +514,12 @@ Intentionally unsupported: native Pi child options such as model override, struc
|
|
|
516
514
|
|
|
517
515
|
Pass `share: true` to export a full session to HTML, upload it to a secret GitHub Gist through your `gh` credentials, and return a `https://shittycodingagent.ai/session/?<gistId>` URL.
|
|
518
516
|
|
|
519
|
-
```
|
|
520
|
-
|
|
517
|
+
```js workflow
|
|
518
|
+
return runs.run("main", { agent: "scout", task: "..." });
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
```js
|
|
522
|
+
subagent({ workflow: true, share: true });
|
|
521
523
|
```
|
|
522
524
|
|
|
523
525
|
This is disabled by default. Session data may contain source code, paths, environment variables, credentials, or other sensitive output. You need `gh` installed and authenticated.
|