pi-subagents 0.73.0 → 0.74.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 +65 -0
- package/README.md +1 -1
- package/docs/agents.md +18 -12
- package/docs/configuration.md +66 -9
- package/docs/extension-api.md +5 -4
- package/docs/missions.md +13 -13
- package/docs/models.md +2 -2
- package/docs/observability.md +2 -2
- package/docs/tool-reference.md +63 -86
- package/docs/workflows.md +165 -171
- 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/advertised-agent-prompt.d.ts +6 -4
- package/src/agents/advertised-agent-prompt.d.ts.map +1 -1
- package/src/agents/advertised-agent-prompt.js +16 -30
- package/src/agents/advertised-agent-prompt.js.map +1 -1
- package/src/agents/agent-management.js +2 -2
- package/src/agents/agent-management.js.map +1 -1
- package/src/agents/agents.d.ts +1 -0
- package/src/agents/agents.d.ts.map +1 -1
- package/src/agents/agents.js +8 -0
- package/src/agents/agents.js.map +1 -1
- package/src/api/preflight.d.ts +5 -1
- package/src/api/preflight.d.ts.map +1 -1
- package/src/api/preflight.js +2 -1
- package/src/api/preflight.js.map +1 -1
- package/src/extension/config.d.ts.map +1 -1
- package/src/extension/config.js +12 -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 +71 -169
- 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 +69 -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 +3 -117
- package/src/extension/schemas.d.ts.map +1 -1
- package/src/extension/schemas.js +38 -125
- 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/runs/background/async-execution.d.ts +3 -0
- package/src/runs/background/async-execution.d.ts.map +1 -1
- package/src/runs/background/async-execution.js +6 -2
- package/src/runs/background/async-execution.js.map +1 -1
- package/src/runs/background/async-job-tracker.d.ts.map +1 -1
- package/src/runs/background/async-job-tracker.js +65 -22
- 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 +80 -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 +4 -0
- package/src/runs/background/control-channel.d.ts.map +1 -1
- package/src/runs/background/control-channel.js +16 -1
- 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 +4 -1
- 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-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.js +5 -5
- package/src/runs/background/scheduled-runs.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 +13 -1
- 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 +19 -3
- package/src/runs/foreground/async-stop-action.js.map +1 -1
- package/src/runs/foreground/execution.d.ts.map +1 -1
- package/src/runs/foreground/execution.js +8 -1
- package/src/runs/foreground/execution.js.map +1 -1
- package/src/runs/foreground/subagent-executor.d.ts +6 -5
- package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
- package/src/runs/foreground/subagent-executor.js +293 -182
- package/src/runs/foreground/subagent-executor.js.map +1 -1
- 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 +9 -0
- package/src/runs/shared/child-session.d.ts.map +1 -1
- package/src/runs/shared/child-session.js +90 -4
- 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 +11 -4
- package/src/runs/shared/child-tool-plan.js.map +1 -1
- package/src/runs/shared/dynamic-fanout.js +1 -1
- package/src/runs/shared/dynamic-fanout.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 +78 -2
- package/src/runs/shared/mcp-direct-tool-allowlist.js.map +1 -1
- package/src/runs/shared/model-resolution.d.ts +10 -0
- package/src/runs/shared/model-resolution.d.ts.map +1 -1
- package/src/runs/shared/model-resolution.js +30 -9
- 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 +2 -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/subagent-prompt-runtime.d.ts.map +1 -1
- package/src/runs/shared/subagent-prompt-runtime.js +2 -0
- 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/settings.d.ts +1 -1
- package/src/shared/types.d.ts +20 -0
- package/src/shared/types.d.ts.map +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/tui/render.d.ts.map +1 -1
- package/src/tui/render.js +55 -17
- 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 +8 -2
- package/src/workflows/workflow-receipt.js.map +1 -1
- package/src/workflows/workflow-resources.d.ts +9 -0
- package/src/workflows/workflow-resources.d.ts.map +1 -1
- package/src/workflows/workflow-resources.js +39 -12
- 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
|
@@ -9,7 +9,7 @@ Agent files can live in:
|
|
|
9
9
|
- `.pi/agents/**/*.md` — canonical project scope
|
|
10
10
|
- legacy `.agents/**/*.md` — still read for compatibility, but `.pi/agents/` wins on conflicts
|
|
11
11
|
|
|
12
|
-
Saved chain files may still be discovered for management and existing durable run state, but they are not a public execution surface. Author new orchestration
|
|
12
|
+
Saved chain files may still be discovered for management and existing durable run state, but they are not a public execution surface. Author new orchestration as a workflow script.
|
|
13
13
|
|
|
14
14
|
Precedence is by parsed runtime name:
|
|
15
15
|
1. project scope
|
|
@@ -45,16 +45,16 @@ subagent({
|
|
|
45
45
|
|
|
46
46
|
Use direct single-agent execution for one bounded task when no stable key,
|
|
47
47
|
branching, retained-child lookup, or aggregate workflow result is needed. Use a
|
|
48
|
-
|
|
48
|
+
workflow script when the parent needs JavaScript control flow or data-dependent
|
|
49
49
|
branching, or when the run is part of a larger coordinated wave or a later step
|
|
50
50
|
must resume it by key.
|
|
51
51
|
|
|
52
52
|
### Forked context
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
})
|
|
54
|
+
Write this block in the reply, then call `subagent({ workflow: true })` (see [Scripted workflows](#scripted-workflows)):
|
|
55
|
+
|
|
56
|
+
```js workflow
|
|
57
|
+
return runs.run("oracle-check", { agent: "oracle", task: "Review my current direction and challenge assumptions.", context: "fork" });
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
`context: "fork"` creates a branched child session from the current persisted
|
|
@@ -68,7 +68,7 @@ its resolved launch context as `[fresh]` or `[fork]`. Aggregate headers show
|
|
|
68
68
|
|
|
69
69
|
### Scripted workflows
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
A workflow script is the public composition surface when the parent needs
|
|
72
72
|
JavaScript control flow or data-dependent branching. Use
|
|
73
73
|
`runs.run(key, { agent, task, ... })` for keyed children, `runs.all([...])` for
|
|
74
74
|
parallel children, and ordinary JavaScript for sequence, filtering, retries,
|
|
@@ -80,17 +80,25 @@ workflow whenever the parent is starting a coordinated wave, such as multiple
|
|
|
80
80
|
reviews, review plus gate monitor, worker then monitor setup, cross-repo prep
|
|
81
81
|
lanes, or a fanout that the parent will consume together.
|
|
82
82
|
|
|
83
|
+
Write the script as one ```` ```js workflow ```` fenced block in the reply, then
|
|
84
|
+
call `subagent({ workflow: true, ... })` in the same reply. The block is plain
|
|
85
|
+
text, so it needs no JSON string escaping; a line containing only ```` ``` ````
|
|
86
|
+
(three or more backticks) ends it. A reply carries one block and one
|
|
87
|
+
`workflow: true` call. Use `workflow: "./path/to/script.js"` for a script file.
|
|
88
|
+
Later examples that show only a ```` ```js workflow ```` block run with
|
|
89
|
+
`subagent({ workflow: true })`.
|
|
90
|
+
|
|
91
|
+
```js workflow
|
|
92
|
+
const scan = await runs.run("scan", { label: "Map target behavior", agent: "scout", task: "Map the target" });
|
|
93
|
+
const reviews = await runs.all([
|
|
94
|
+
{ key: "correctness", label: "Review target correctness", agent: "reviewer", task: "Review correctness: " + scan.output },
|
|
95
|
+
{ key: "tests", label: "Review target test coverage", agent: "reviewer", task: "Review tests: " + scan.output }
|
|
96
|
+
]);
|
|
97
|
+
return reviews.map(result => result.output);
|
|
98
|
+
```
|
|
99
|
+
|
|
83
100
|
```js
|
|
84
|
-
subagent({
|
|
85
|
-
workflowScript: `
|
|
86
|
-
const scan = await runs.run("scan", { label: "Map target behavior", agent: "scout", task: "Map the target" });
|
|
87
|
-
const reviews = await runs.all([
|
|
88
|
-
{ key: "correctness", label: "Review target correctness", agent: "reviewer", task: "Review correctness: " + scan.output },
|
|
89
|
-
{ key: "tests", label: "Review target test coverage", agent: "reviewer", task: "Review tests: " + scan.output }
|
|
90
|
-
]);
|
|
91
|
-
return reviews.map(result => result.output);
|
|
92
|
-
`
|
|
93
|
-
})
|
|
101
|
+
subagent({ workflow: true, async: true })
|
|
94
102
|
```
|
|
95
103
|
|
|
96
104
|
Scripts run in a timed worker with only `runs.run`, `runs.all`, `runs.status`, `runs.ref/refs`, `emit`, captured `console`, and standard JavaScript. Pass explicit task text to `runs.run`. Mission-attached workflows also get `await state.get(key)` and `await state.set(key, value)` for durable JSON state shared across workflows on the same mission; `mission: false` workflows have no `state` global. Stable keys are required. Child launches follow ordinary single-agent execution controls. Give each child a distinct decision and output path when reports must outlive the workflow, then consume the aggregate workflow result before opening individual reports. Do not ask children to write `reports/...` or other repo-root scratch paths in task text.
|
|
@@ -103,7 +111,7 @@ For a typed post-run check, pass the object form `gate: { command, output: "json
|
|
|
103
111
|
|
|
104
112
|
If omitted, acceptance is inferred from role, mode, and risk. Use `level: "checked"` for ordinary writer evidence and `level: "verified"` when the runtime should run explicit validation commands. Independent review is orthogonal: use `review: { required: true, agent: "reviewer" }`; reviewer/read-only calls omit `acceptance`. `review-required` means evidence passed but review is pending; `reviewed` means an independent review found no blockers. Never request `level: "reviewed"`; it is recognized only so preflight can return an actionable correction. Disable gates with `{ level: "none", reason: "..." }`; bare `"none"` is rejected and `false` is only a deprecated shorthand. Child-reported command success is evidence, not runtime verification.
|
|
105
113
|
|
|
106
|
-
Completed workflow children from this parent session stay addressable as retained children. `subagent({ action: "children.list" })` lists up to the last 10 with run ids and reports each row as `resumable` or `not resumable` with a reason. 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 `subagent({ action: "status", id: "<run-id>" })`; if status identifies the candidate, attempt `subagent({ action: "resume", id: "<run-id>", message: "..." })`. Resume performs the authoritative eligibility check and may reject the attempt. For a retained-child challenge, use `resume` instead of `steer` when the child is complete. Launch 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 with `runs.run(key, { resume: "<run-id>", task: "follow-up" })`. Inside
|
|
114
|
+
Completed workflow children from this parent session stay addressable as retained children. `subagent({ action: "children.list" })` lists up to the last 10 with run ids and reports each row as `resumable` or `not resumable` with a reason. 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 `subagent({ action: "status", id: "<run-id>" })`; if status identifies the candidate, attempt `subagent({ action: "resume", id: "<run-id>", message: "..." })`. Resume performs the authoritative eligibility check and may reject the attempt. For a retained-child challenge, use `resume` instead of `steer` when the child is complete. Launch 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 with `runs.run(key, { resume: "<run-id>", task: "follow-up" })`. Inside a workflow script, awaiting that call waits for the revived child to finish and returns its completed output and new `runId`; top-level `{ action: "resume" }` remains detached. Pass explicit follow-up task text. Assign each returned child result back to the loop variable because every resume can return a new retained `runId`; always resume the latest returned id. `resume` and `agent` are mutually exclusive, the revived child keeps its stored agent/model/tool contract, and `gate` is rejected on retained resume items.
|
|
107
115
|
|
|
108
116
|
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.
|
|
109
117
|
|
|
@@ -122,7 +130,7 @@ Keyed resume reads that one exact receipt and revalidates the retained run at la
|
|
|
122
130
|
### Parallel sequential lanes
|
|
123
131
|
|
|
124
132
|
For a broad plan with a known set of narrow, visible stages per lane, use
|
|
125
|
-
`runs.lanes(...)` inside a
|
|
133
|
+
`runs.lanes(...)` inside a workflow script; it is a nested helper, not a
|
|
126
134
|
top-level `subagent` mode. Give each lane and stage a stable key; give stage
|
|
127
135
|
items a short verb + behavior `label`, preserving explicit user labels. The first
|
|
128
136
|
stage from every lane is launched together, then later stages sequence per lane.
|
|
@@ -184,25 +192,26 @@ fleet. If `PI_SUBAGENT_WAIT_TOOL_ENABLED` disables blocking, direct waits return
|
|
|
184
192
|
immediately, but headless `agent_end` auto-drain still surfaces provider,
|
|
185
193
|
reconciliation, or timeout failures.
|
|
186
194
|
|
|
195
|
+
```js workflow
|
|
196
|
+
return runs.run("main", { agent: "worker", task: "Run the full test suite" });
|
|
197
|
+
```
|
|
198
|
+
|
|
187
199
|
```typescript
|
|
188
|
-
subagent({
|
|
189
|
-
workflowScript: `return runs.run("main", { agent: "worker", task: "Run the full test suite" })`,
|
|
190
|
-
async: true
|
|
191
|
-
})
|
|
200
|
+
subagent({ workflow: true, async: true })
|
|
192
201
|
```
|
|
193
202
|
|
|
194
|
-
File-only output mode works for
|
|
203
|
+
File-only output mode works for workflow script child launches. Use relative child output paths for scratch reports so the runtime stores them under the run artifact directory and age-based cleanup can remove them. Use absolute paths only for user-approved durable destinations, such as session memory, a docs folder outside the repo, or a known handoff path. For cross-codebase waves, include the repo slug or lane key in each output path so reports from different repositories cannot collide.
|
|
195
204
|
|
|
196
205
|
The `output` field is the API binding; a filename mentioned in task text 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.
|
|
197
206
|
|
|
198
207
|
For review fanout where the parent continues a local audit:
|
|
199
208
|
|
|
209
|
+
```js workflow
|
|
210
|
+
return runs.run("correctness", { agent: "reviewer", task: "Review the current diff for correctness issues. Do not edit files." });
|
|
211
|
+
```
|
|
212
|
+
|
|
200
213
|
```typescript
|
|
201
|
-
const run = subagent({
|
|
202
|
-
workflowScript: `return runs.run("correctness", { agent: "reviewer", task: "Review the current diff for correctness issues. Do not edit files." })`,
|
|
203
|
-
async: true,
|
|
204
|
-
context: "fresh"
|
|
205
|
-
})
|
|
214
|
+
const run = subagent({ workflow: true, async: true, context: "fresh" })
|
|
206
215
|
// Continue local inspection, then later call status with the returned id.
|
|
207
216
|
```
|
|
208
217
|
|
|
@@ -265,11 +274,11 @@ A cooperating terminal runtime can register read-only external records through `
|
|
|
265
274
|
Schedules are durable project records under `.pi/subagents/schedules/`. They are enabled by default; set `{ "scheduledRuns": { "enabled": false } }` in `~/.pi/agent/extensions/subagent/config.json` to disable them. Only schedule explicit work the user asked for. To keep schedules outside the project repository, set `{ "scheduledRuns": { "storeRoot": "~/.pi/subagent-schedules" } }` in the same config: `storeRoot` accepts an absolute path or a `~/`-prefixed path, and records land under `<storeRoot>/<sha256(path.resolve(cwd)) first 20 hex>/<scheduleId>/`.
|
|
266
275
|
|
|
267
276
|
```typescript
|
|
268
|
-
// One-shot reviewer
|
|
269
|
-
subagent({ action: "schedule.create", id: "evening-review", name: "Evening review", at: "+30m",
|
|
277
|
+
// One-shot reviewer, after a ```js workflow block with the script
|
|
278
|
+
subagent({ action: "schedule.create", id: "evening-review", name: "Evening review", at: "+30m", workflow: true })
|
|
270
279
|
|
|
271
|
-
// Fixed recurring workflow
|
|
272
|
-
subagent({ action: "schedule.create", id: "backlog", every: "6h", catchUp: "latest",
|
|
280
|
+
// Fixed recurring workflow from a script file
|
|
281
|
+
subagent({ action: "schedule.create", id: "backlog", every: "6h", catchUp: "latest", workflow: "./.pi/workflows/backlog.js" })
|
|
273
282
|
|
|
274
283
|
subagent({ action: "schedule.list" })
|
|
275
284
|
subagent({ action: "schedule.show", id: "backlog" })
|
|
@@ -281,7 +290,7 @@ subagent({ action: "schedule.run-due" })
|
|
|
281
290
|
subagent({ action: "schedule.delete", id: "backlog" })
|
|
282
291
|
```
|
|
283
292
|
|
|
284
|
-
`schedule.create` accepts exactly one target, `
|
|
293
|
+
`schedule.create` accepts exactly one target, a workflow script (`workflow: true` or a script path; the script text is stored at creation), and exactly one trigger (`at`, or a fixed `every` interval using `m`, `h`, `d`, or `w`). Runs always launch async with fresh context and no automatic mission; mission attachment is deferred from this first slice. `overlap` is currently `skip`; `catchUp` supports `latest` and `none`. `schedule.run-due` is the headless external-launcher seam. Calendar recurrence, cron, and the schedule inspector are deferred from this first safe slice. Definitions, bounded history, append-only events, and per-run receipts remain project-scoped across Pi sessions.
|
|
285
294
|
|
|
286
295
|
Humans can use `/subagents-doctor` for the same read-only report. It checks runtime paths, discovery counts, async support, current session context, and intercom bridge state.
|
|
287
296
|
|
|
@@ -308,17 +317,15 @@ A soft interrupt cancels the current child turn and leaves the run paused. It do
|
|
|
308
317
|
|
|
309
318
|
Per-run control thresholds can be overridden when a task legitimately runs without observable output for longer than usual:
|
|
310
319
|
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
})`
|
|
321
|
-
})
|
|
320
|
+
```js workflow
|
|
321
|
+
return runs.run("slow-tests", {
|
|
322
|
+
agent: "worker",
|
|
323
|
+
task: "Run the slow migration test suite",
|
|
324
|
+
control: {
|
|
325
|
+
needsAttentionAfterMs: 300000,
|
|
326
|
+
notifyOn: ["needs_attention"]
|
|
327
|
+
}
|
|
328
|
+
});
|
|
322
329
|
```
|
|
323
330
|
|
|
324
331
|
If the run already has an active intercom bridge target, needs-attention notifications can also prepare a compact intercom ping for the orchestrator. When a child route is available, the ping tells the orchestrator which agent needs attention and includes the exact `intercom({ action: "send", to: "..." })` target for a nudge. Do not invent a target or ask the child to self-report when no bridge exists.
|
|
@@ -400,7 +407,7 @@ Use `mission.update` while work runs to record decisions, artifacts, labels, sum
|
|
|
400
407
|
|
|
401
408
|
### Mission use policy
|
|
402
409
|
|
|
403
|
-
- **Keep the default.** Every ordinary
|
|
410
|
+
- **Keep the default.** Every ordinary workflow script launch with a task creates one enclosing mission automatically. All workflow children share it and never get their own. Do not add `mission: {...}` boilerplate. Pass it only to set the title, objective, labels, or to enable `goal` with `budget`.
|
|
404
411
|
- **Use `mission: false` for noise.** Use it for trivial one-shot lookups, scouts, disposable probes, and quick validation where a recovery record is noise. It removes the mission and the `state` global for the whole workflow, so do not use it for monitors or multi-workflow loops that coordinate through `state`. Scheduled runs already launch without automatic missions.
|
|
405
412
|
- **Use `missionId` for follow-up work.** Attach later work to an existing objective with `missionId`; attachment re-marks the mission active. `missionId` and `mission` are mutually exclusive. Explicit attachment fails before launch if the mission is missing, while automatic missions degrade to `details.missionWarning` without blocking the run.
|
|
406
413
|
- **Keep `state` small.** Mission `state` is JSON coordination across workflows on the same mission. Keys use the same format as run keys, values must be JSON, and the whole state file is capped at 256 KiB. Each `set` merges one key under a file lock. Put large content in artifact files and store paths in state. In goal missions, write `state.set("nextReadyAction", "...")` so the next idle-turn notice names the exact ready step.
|
|
@@ -413,15 +420,15 @@ After compaction, restart, or confusing history, recover from durable state firs
|
|
|
413
420
|
Routing rule:
|
|
414
421
|
- Same project: ordinary mission-backed subagents.
|
|
415
422
|
- Different project, small/bounded task: ordinary async subagent with explicit `cwd`, an authority boundary, and durable output.
|
|
416
|
-
- Several projects with independent work: one async
|
|
423
|
+
- Several projects with independent work: one async workflow script whose child keys include repo slugs and whose child calls set explicit `cwd`; keep publication and merge decisions serial per repo.
|
|
417
424
|
- Different project, substantial or long-running work: open a project-owned Herdr pane rooted there when a separate visible project session is useful, then give that project Pi session a narrow mission/result contract. Do not model it as ordinary child nesting, and do not expect existing headless runs to move into the pane.
|
|
418
425
|
|
|
419
426
|
Project panes run a separate Pi session from the target directory. Subagents launched inside that pane use that project's config, agents, skills, files, git state, and mission records. The pane binding lives under `<projectRoot>/.pi/subagents/project-panes/herdr.json`. When Pi runs inside Herdr, the owning pane reports compact active-work status and title suffixes, and the parent inline status counts opened project panes. Use Herdr itself or `project.status` / `project.close` for pane-level follow-up. For ordinary headless delegation to another repo, prefer explicit `cwd` first; reserve project panes for visible or persistent project ownership.
|
|
420
427
|
|
|
421
428
|
```typescript
|
|
422
429
|
subagent({ action: "mission.create", mission: { title: "Ship auth refresh", objective: "Implement and validate refresh handling" } })
|
|
423
|
-
subagent({
|
|
424
|
-
subagent({
|
|
430
|
+
subagent({ workflow: true, missionId: "<mission-id>" }) // after a ```js workflow block
|
|
431
|
+
subagent({ workflow: true, mission: false }) // after a ```js workflow block
|
|
425
432
|
subagent({ action: "mission.list", missionScope: "global" })
|
|
426
433
|
subagent({ action: "mission.resolve-decision", missionId: "<mission-id>", id: "<decision-id>", summary: "Settled: ship the v2 API; no schema freeze needed." })
|
|
427
434
|
subagent({ action: "project.open", cwd: "/path/to/other-repo", message: "Own this mission for the project and report back with receipts." })
|
|
@@ -435,16 +442,12 @@ subagent({ action: "mission.close", missionId: "<mission-id>", missionStatus: "c
|
|
|
435
442
|
When multiple agents might write concurrently, use worktrees instead of letting
|
|
436
443
|
them share one filesystem view.
|
|
437
444
|
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
]);
|
|
445
|
-
return results.map(({ key, artifactPaths }) => ({ key, artifactPaths }));
|
|
446
|
-
`
|
|
447
|
-
})
|
|
445
|
+
```js workflow
|
|
446
|
+
const results = await runs.all([
|
|
447
|
+
{ key: "feature-a", agent: "worker", task: "Implement feature A", worktree: true },
|
|
448
|
+
{ key: "feature-b", agent: "worker", task: "Implement feature B", worktree: true }
|
|
449
|
+
]);
|
|
450
|
+
return results.map(({ key, artifactPaths }) => ({ key, artifactPaths }));
|
|
448
451
|
```
|
|
449
452
|
|
|
450
453
|
`worktree: true` on a `runs.run` / `runs.all` item gives that child its own git
|
|
@@ -487,16 +490,14 @@ The intended oracle loop is:
|
|
|
487
490
|
4. the main agent decides what direction to approve
|
|
488
491
|
5. only then should `worker` implement
|
|
489
492
|
|
|
490
|
-
```
|
|
493
|
+
```js workflow
|
|
491
494
|
// Advisory review in a branched thread. Oracle defaults to forked context.
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
})
|
|
495
|
+
return runs.run("oracle-check", { agent: "oracle", task: "Review my current direction, challenge assumptions, and propose the best next move." });
|
|
496
|
+
```
|
|
495
497
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
})
|
|
498
|
+
```js workflow
|
|
499
|
+
// Implementation only after explicit approval, in a later reply. Worker defaults to fresh context.
|
|
500
|
+
return runs.run("implementation", { agent: "worker", task: "Implement the approved approach: ..." });
|
|
500
501
|
```
|
|
501
502
|
|
|
502
503
|
`oracle` is not a fresh-context reviewer in the Cognition article sense. It is
|
|
@@ -85,7 +85,7 @@ subagent({ action: "reset", agent: "reviewer" })
|
|
|
85
85
|
Use management actions when the system needs to create or edit subagents on
|
|
86
86
|
demand without dropping into raw file editing.
|
|
87
87
|
|
|
88
|
-
Management actions create or update user/project agent files. `config.name` is the local frontmatter name; optional `config.package` registers and looks up the runtime name as `{package}.{name}`. Use the dotted runtime name for `get`, `update`, `delete`, slash commands, and scripted workflow steps. For small agent changes such as a model swap, prefer `subagents.agentOverrides` in settings. Durable `.chain.md` definitions are legacy records, not a current authoring target; use `
|
|
88
|
+
Management actions create or update user/project agent files. `config.name` is the local frontmatter name; optional `config.package` registers and looks up the runtime name as `{package}.{name}`. Use the dotted runtime name for `get`, `update`, `delete`, slash commands, and scripted workflow steps. For small agent changes such as a model swap, prefer `subagents.agentOverrides` in settings. Durable `.chain.md` definitions are legacy records, not a current authoring target; use a workflow script file (`workflow: "./path.js"`) or `/prompt-workflow` for repeatable orchestration.
|
|
89
89
|
|
|
90
90
|
## Creating and Editing Agents by File
|
|
91
91
|
|
|
@@ -158,4 +158,4 @@ Additional user prompt templates can delegate into `pi-subagents` through the na
|
|
|
158
158
|
|
|
159
159
|
Other Pi extensions can call `pi-subagents` through the in-process event bus. The RPC channels are `subagents:rpc:v1:ready`, `subagents:rpc:v1:request`, and per-request replies at `subagents:rpc:v1:reply:<requestId>`. Envelopes use `{ version: 1, requestId, method, params }`, and replies use `{ version: 1, requestId, success, data | error }`. `ping` advertises the exact process-local async completion event as `events.asyncComplete` for RPC-spawn consumers.
|
|
160
160
|
|
|
161
|
-
Methods: `ping`, `status`, `manage`, `spawn`, `steer`, `interrupt`, `resume`, `stop`, and `cost`. `ping` capability metadata advertises optional projections: `capabilities.fleetStatus: { version: 1 }` adds bounded current-session `data.fleet` records (opaque reconciliation `key`, resolved `agent`, optional `role`, `model`, `effort`, caller-facing `goal`, `startedAt`, split `{ input, output, total }` tokens, plus `totalActive`/`omitted` overflow counts) to successful `status` replies; `capabilities.launchResolvedExtensions` advertises parent-resolved opaque launch-extension identifiers in status details; `capabilities.runtimeAcknowledgedExtensions` advertises the best-effort child-runtime acknowledgement projection fed by cooperating extensions emitting `subagent:acknowledge-extension`; `capabilities.cost: { version: 1 }` advertises parent-plus-child accounting as data. Foreground `details.results[]` rows carry a stable numeric `index`; correlate children by `(runId, index)` rather than row position. Consumers should read status/result artifacts and RPC projections instead of scraping terminal output and must ignore unknown fields. `spawn` accepts either `{ agent, task? }`,
|
|
161
|
+
Methods: `ping`, `status`, `manage`, `spawn`, `steer`, `interrupt`, `resume`, `stop`, and `cost`. `ping` capability metadata advertises optional projections: `capabilities.fleetStatus: { version: 1 }` adds bounded current-session `data.fleet` records (opaque reconciliation `key`, resolved `agent`, optional `role`, `model`, `effort`, caller-facing `goal`, `startedAt`, split `{ input, output, total }` tokens, plus `totalActive`/`omitted` overflow counts) to successful `status` replies; `capabilities.launchResolvedExtensions` advertises parent-resolved opaque launch-extension identifiers in status details; `capabilities.runtimeAcknowledgedExtensions` advertises the best-effort child-runtime acknowledgement projection fed by cooperating extensions emitting `subagent:acknowledge-extension`; `capabilities.cost: { version: 1 }` advertises parent-plus-child accounting as data. Foreground `details.results[]` rows carry a stable numeric `index`; correlate children by `(runId, index)` rather than row position. Consumers should read status/result artifacts and RPC projections instead of scraping terminal output and must ignore unknown fields. `spawn` accepts either `{ agent, task? }`, inline script text as `script`, or `workflow` with a script path (containing `/`) or a named workflow resource; `workflow: true` is rejected because RPC has no assistant reply to read. It is async-only and rejects management actions, `async: false`, or `clarify: true`. It reuses the normal executor, so discovery, validation, session attribution, configured spawn caps, child-safety depth, artifacts, and async status are shared with the `subagent` tool. `manage` accepts only the schedule actions advertised by `ping.capabilities.managementActions`. `status`, acknowledged async `steer`, and `interrupt` map to the normal control actions. RPC steer disables pause-and-revive recovery and advertises `capabilities.nonRecoveringSteer`, preserving the caller's authority over the exact spawned child. `resume` requires a target plus non-empty message and delegates to the package-owned revival path; it may set a caller-owned `file-only` output path but cannot override the persisted child model, tools, budgets, session ownership, or exclusive session lease. For retained-child workflows, resume only roster rows reported `resumable`; because that workflow-only roster is not exhaustive, inspect the exact status of a known direct-run candidate and attempt the authoritative resume when status identifies it. Start a labeled same-role fallback only when there is no known candidate or resume rejects eligibility. `stop` targets running async runs through the existing timeout control channel. `pi.events` is process-local, so separate Pi processes and child subagents need lifecycle artifact files or `pi-intercom` instead.
|
|
@@ -34,7 +34,7 @@ Partition fanout by repository, source seam, decision, or review angle. Each run
|
|
|
34
34
|
|
|
35
35
|
Every child packet must stand alone: include the goal, exact repository/cwd/ref, authority and edit boundary, relevant context/evidence, success criteria, validation, expected output, and stop/escalation rules. Do not rely on parent history, an issue number, or a broad glob alone. An orchestration audit by a top-reasoning critic model is read-only and returns at most three cited omissions; use high thinking only as an explicit parent/user escalation, never as an autonomous root or a parallel placeholder.
|
|
36
36
|
|
|
37
|
-
Use one async `
|
|
37
|
+
Use one async workflow script (`subagent({ workflow: true, async: true })` after a ```` ```js workflow ```` block) for a coordinated wave. Use `runs.all` for independent lanes and `runs.run` for dependent lane stages. Give cross-repository runs explicit `cwd` values and lane-qualified outputs. Use `outputMode: "file-only"` when a report must survive the run or feed a later stage. Keep scratch outputs relative so they live under subagent artifacts; use absolute paths only for durable memory, approved docs paths, or final handoff files.
|
|
38
38
|
|
|
39
39
|
## Keep independent work moving
|
|
40
40
|
|
|
@@ -25,10 +25,10 @@ they do not authorize a launch.
|
|
|
25
25
|
|
|
26
26
|
## Tool vs Slash Commands
|
|
27
27
|
|
|
28
|
-
Agents use the `subagent(...)` tool for execution, management, status, and control. Direct `{ agent, task }` execution is enough for one bounded child task; use `
|
|
28
|
+
Agents use the `subagent(...)` tool for execution, management, status, and control. Direct `{ agent, task }` execution is enough for one bounded child task; use a workflow script (one ```` ```js workflow ```` block in the reply plus `subagent({ workflow: true })`) when the parent needs JavaScript control flow or data-dependent branching, keyed, parallel, sequential, retry, retained-resume, aggregate, or explicit staged-lane behavior (`runs.lanes`). Humans often use the slash-command layer instead:
|
|
29
29
|
|
|
30
30
|
- `/run` — launch a single agent
|
|
31
|
-
- `
|
|
31
|
+
- `subagent({ workflow: ... })` — the workflow-script surface for sequence, parallelism, branching, retries, and aggregation; with `disabledFeatures: ["workflow-scripts"]`, top-level `chain` and `tasks` replace it (see [configuration](../../../docs/configuration.md#chain-and-tasks-without-workflow-scripts))
|
|
32
32
|
- `/subagents` — interactive admin for inspecting agents and editing model, thinking, or system prompt
|
|
33
33
|
- `/subagents-stop [run-id]` — stop a current-session top-level async run; opens a selector when no id is given
|
|
34
34
|
- `/subagents-detach [run-id]` — detach an active foreground single-subagent run without terminating its child
|
|
@@ -39,7 +39,7 @@ Agents use the `subagent(...)` tool for execution, management, status, and contr
|
|
|
39
39
|
- `/subagents-doctor` — diagnose setup, discovery, async paths, and intercom bridge state
|
|
40
40
|
- `/subagents-models [agent]` — show the live runtime-loaded builtin model mapping
|
|
41
41
|
- `/subagents-profiles`, `/subagents-load-profile`, `/subagents-refresh-provider-models`, `/subagents-generate-profiles`, `/subagents-check-profile` — manage model profiles and provider catalogs
|
|
42
|
-
- `/prompt-workflow` — run a prompt template
|
|
42
|
+
- `/prompt-workflow` — run a prompt template as a native workflow script
|
|
43
43
|
|
|
44
44
|
Prefer the tool when you are writing agent logic. Prefer the slash commands when
|
|
45
45
|
you are guiding a human through an interactive flow.
|
|
@@ -83,22 +83,21 @@ Default guardrails:
|
|
|
83
83
|
|
|
84
84
|
Example shape:
|
|
85
85
|
|
|
86
|
+
```js workflow
|
|
87
|
+
const results = await runs.all([
|
|
88
|
+
{ key: "deslop", agent: "reviewer", task: "Apply the available 'deslop' skill to review the current diff for concrete cleanup findings only. Do not modify files.", skill: "deslop" },
|
|
89
|
+
{ key: "accessibility", agent: "reviewer", task: "Apply the available 'accessibility' skill to review the UI changes for concrete issues only. Do not modify files.", skill: "accessibility" }
|
|
90
|
+
]);
|
|
91
|
+
return results.map(result => result.output);
|
|
92
|
+
```
|
|
93
|
+
|
|
86
94
|
```typescript
|
|
87
|
-
subagent({
|
|
88
|
-
workflowScript: `
|
|
89
|
-
const results = await runs.all([
|
|
90
|
-
{ key: "deslop", agent: "reviewer", task: "Apply the available 'deslop' skill to review the current diff for concrete cleanup findings only. Do not modify files.", skill: "deslop" },
|
|
91
|
-
{ key: "accessibility", agent: "reviewer", task: "Apply the available 'accessibility' skill to review the UI changes for concrete issues only. Do not modify files.", skill: "accessibility" }
|
|
92
|
-
]);
|
|
93
|
-
return results.map(result => result.output);
|
|
94
|
-
`,
|
|
95
|
-
context: "fresh"
|
|
96
|
-
})
|
|
95
|
+
subagent({ workflow: true, context: "fresh" })
|
|
97
96
|
```
|
|
98
97
|
|
|
99
98
|
### Review-loop technique
|
|
100
99
|
|
|
101
|
-
Use this when the user wants implementation or current diff review to continue until reviewers stop finding fixes worth doing now. Keep the loop in the parent session: one async `worker` implements or fixes, fresh-context `reviewer` agents inspect the actual repo and diff, the parent synthesizes accepted fixes, and one async forked `worker` applies them. The parent can express the sequence up front as an async/background
|
|
100
|
+
Use this when the user wants implementation or current diff review to continue until reviewers stop finding fixes worth doing now. Keep the loop in the parent session: one async `worker` implements or fixes, fresh-context `reviewer` agents inspect the actual repo and diff, the parent synthesizes accepted fixes, and one async forked `worker` applies them. The parent can express the sequence up front as an async/background workflow script when the workflow is known, or continue with explicit follow-up workflow script runs after each async completion. For an initial workflow, pass `async: true` so the main chat is unblocked. Treat an async implementation worker handoff as an intermediate state, not final completion, unless the user explicitly asked for worker-only work, review-only output, or to stop after implementation. Stop when reviewers find no P0 blockers or P1 fixes worth doing now, remaining P2 feedback is optional or deferred, an unapproved product/scope/architecture decision appears, or the max review-round cap is reached. Default to 3 review rounds unless the user sets a different cap. Do not loop for optional polish, and do not let children launch subagents or decide the loop outcome.
|
|
102
101
|
|
|
103
102
|
As a conservative orchestration policy, do not pass a hard `toolBudget` to an implementation worker, fix worker, reviewer with edit authority, or other mutation-capable child. The default tool budget blocks read/search tools rather than mutation tools, but count limits still do not measure delivery safety. Use a narrow task plus an outer elapsed deadline with enough margin, then request a checkpoint after the current tool returns. The checkpoint should report changed files, build/test state, remaining work, and commit or PR state. An elapsed timeout is not a mutation-safe boundary and must not be used as the checkpoint trigger.
|
|
104
103
|
|
|
@@ -118,10 +117,10 @@ Use this after implementation when the user or applicable instructions request d
|
|
|
118
117
|
|
|
119
118
|
### Staged fix orchestration technique
|
|
120
119
|
|
|
121
|
-
Use this when a broad diff has known reviewer findings across several items and the user wants the parent to “orchestrate subagents like a boss.” Keep mutation ownership explicit in the
|
|
120
|
+
Use this when a broad diff has known reviewer findings across several items and the user wants the parent to “orchestrate subagents like a boss.” Keep mutation ownership explicit in the workflow script:
|
|
122
121
|
|
|
123
122
|
When staged seams are available, a low-tier writer should not receive the
|
|
124
|
-
end-to-end issue. Use `runs.lanes` inside
|
|
123
|
+
end-to-end issue. Use `runs.lanes` inside the workflow script to keep stages narrow:
|
|
125
124
|
a scout/red test, helper-only change, one render seam, validation, minimality
|
|
126
125
|
challenge, or fresh review. Give the writer only its assigned implementation
|
|
127
126
|
stage; keep sequencing and synthesis with the parent.
|
|
@@ -137,39 +136,37 @@ When one child returns a structured target list, use ordinary JavaScript to vali
|
|
|
137
136
|
|
|
138
137
|
Single-seam example shape (the lane board records that these are review angles on one tightly coupled deployment-lifecycle diff, not independent implementation contracts):
|
|
139
138
|
|
|
139
|
+
```js workflow
|
|
140
|
+
// Stage 1: parallel read-only review angles on one recorded single seam
|
|
141
|
+
const plans = await runs.all([
|
|
142
|
+
{ key: "correctness-plan", agent: "reviewer", phase: "Planning", label: "Review lifecycle correctness", task: "Plan correctness fixes for the same deployment-lifecycle diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/correctness.md", outputMode: "file-only" },
|
|
143
|
+
{ key: "regression-plan", agent: "reviewer", phase: "Planning", label: "Review lifecycle regressions", task: "Plan regression coverage for the same deployment-lifecycle diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/regressions.md", outputMode: "file-only" },
|
|
144
|
+
{ key: "minimality-plan", agent: "reviewer", phase: "Planning", label: "Review lifecycle minimality", task: "Plan minimality fixes for the same deployment-lifecycle diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/minimality.md", outputMode: "file-only" }
|
|
145
|
+
]);
|
|
146
|
+
|
|
147
|
+
// Stage 2: one writer for this lane-board-recorded single seam.
|
|
148
|
+
// Under outputMode "file-only" the awaited .output is the saved-output
|
|
149
|
+
// reference, so pass those managed artifact references to the writer.
|
|
150
|
+
const worker = await runs.run("apply-fixes", {
|
|
151
|
+
agent: "worker",
|
|
152
|
+
phase: "Implementation",
|
|
153
|
+
label: "Apply accepted fixes",
|
|
154
|
+
task: "Apply only the accepted fixes to the one deployment-lifecycle seam. The lane board records that splitting this existing diff would create overlapping ownership. You are the sole writer for this seam. Run focused validation and report changed files, commands, failures, and remaining issues.\n\nCorrectness plan: " + plans[0].output + "\n\nRegression plan: " + plans[1].output + "\n\nMinimality plan: " + plans[2].output,
|
|
155
|
+
output: "worker/fixes.md",
|
|
156
|
+
outputMode: "file-only"
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Stage 3: parallel read-only validation fanout
|
|
160
|
+
const validations = await runs.all([
|
|
161
|
+
{ key: "validate-behavior", agent: "reviewer", phase: "Validation", label: "Validate lifecycle behavior", task: "Validate behavior in the post-worker deployment-lifecycle diff. Start from the worker result: " + worker.output + ". Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "validation/behavior.md", outputMode: "file-only" },
|
|
162
|
+
{ key: "validate-minimality", agent: "reviewer", phase: "Validation", label: "Validate lifecycle minimality", task: "Validate minimality in the same post-worker deployment-lifecycle diff. Start from the worker result: " + worker.output + ". Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "validation/minimality.md", outputMode: "file-only" }
|
|
163
|
+
]);
|
|
164
|
+
|
|
165
|
+
return { worker: worker.output, validations: validations.map(v => v.output) };
|
|
166
|
+
```
|
|
167
|
+
|
|
140
168
|
```typescript
|
|
141
|
-
subagent({
|
|
142
|
-
async: true,
|
|
143
|
-
context: "fresh",
|
|
144
|
-
workflowScript: `
|
|
145
|
-
// Stage 1: parallel read-only review angles on one recorded single seam
|
|
146
|
-
const plans = await runs.all([
|
|
147
|
-
{ key: "correctness-plan", agent: "reviewer", phase: "Planning", label: "Review lifecycle correctness", task: "Plan correctness fixes for the same deployment-lifecycle diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/correctness.md", outputMode: "file-only" },
|
|
148
|
-
{ key: "regression-plan", agent: "reviewer", phase: "Planning", label: "Review lifecycle regressions", task: "Plan regression coverage for the same deployment-lifecycle diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/regressions.md", outputMode: "file-only" },
|
|
149
|
-
{ key: "minimality-plan", agent: "reviewer", phase: "Planning", label: "Review lifecycle minimality", task: "Plan minimality fixes for the same deployment-lifecycle diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/minimality.md", outputMode: "file-only" }
|
|
150
|
-
]);
|
|
151
|
-
|
|
152
|
-
// Stage 2: one writer for this lane-board-recorded single seam.
|
|
153
|
-
// Under outputMode "file-only" the awaited .output is the saved-output
|
|
154
|
-
// reference, so pass those managed artifact references to the writer.
|
|
155
|
-
const worker = await runs.run("apply-fixes", {
|
|
156
|
-
agent: "worker",
|
|
157
|
-
phase: "Implementation",
|
|
158
|
-
label: "Apply accepted fixes",
|
|
159
|
-
task: "Apply only the accepted fixes to the one deployment-lifecycle seam. The lane board records that splitting this existing diff would create overlapping ownership. You are the sole writer for this seam. Run focused validation and report changed files, commands, failures, and remaining issues.\\n\\nCorrectness plan: " + plans[0].output + "\\n\\nRegression plan: " + plans[1].output + "\\n\\nMinimality plan: " + plans[2].output,
|
|
160
|
-
output: "worker/fixes.md",
|
|
161
|
-
outputMode: "file-only"
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
// Stage 3: parallel read-only validation fanout
|
|
165
|
-
const validations = await runs.all([
|
|
166
|
-
{ key: "validate-behavior", agent: "reviewer", phase: "Validation", label: "Validate lifecycle behavior", task: "Validate behavior in the post-worker deployment-lifecycle diff. Start from the worker result: " + worker.output + ". Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "validation/behavior.md", outputMode: "file-only" },
|
|
167
|
-
{ key: "validate-minimality", agent: "reviewer", phase: "Validation", label: "Validate lifecycle minimality", task: "Validate minimality in the same post-worker deployment-lifecycle diff. Start from the worker result: " + worker.output + ". Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "validation/minimality.md", outputMode: "file-only" }
|
|
168
|
-
]);
|
|
169
|
-
|
|
170
|
-
return { worker: worker.output, validations: validations.map(v => v.output) };
|
|
171
|
-
`
|
|
172
|
-
})
|
|
169
|
+
subagent({ workflow: true, async: true, context: "fresh" })
|
|
173
170
|
```
|
|
174
171
|
|
|
175
172
|
## Builtin Agents
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { ResolvedSubagentCapabilityCeiling } from "../runs/shared/capability-ceiling.ts";
|
|
2
2
|
import type { AgentConfig } from "./agents.ts";
|
|
3
|
+
/**
|
|
4
|
+
* The catalog body without its `<advertised_subagents>` wrapper, for Pi's structured
|
|
5
|
+
* prompt sections, which add the tag from the section key. The byte budget applies to
|
|
6
|
+
* the wrapped form, so both deliveries carry the same entries.
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildAdvertisedAgentCatalog(agents: readonly AgentConfig[], capabilityCeiling?: ResolvedSubagentCapabilityCeiling): string | undefined;
|
|
3
9
|
export declare function buildAdvertisedAgentPrompt(agents: readonly AgentConfig[], capabilityCeiling?: ResolvedSubagentCapabilityCeiling): string | undefined;
|
|
4
|
-
export declare function appendAdvertisedAgentPrompt(systemPrompt: string, advertisedPrompt: string | undefined): string;
|
|
5
|
-
export declare function appendAdvertisedAgentPrompt(systemPrompt: string[], advertisedPrompt: string | undefined): string[];
|
|
6
|
-
export declare function appendAdvertisedAgentPrompt(systemPrompt: undefined, advertisedPrompt: string | undefined): string | undefined;
|
|
7
|
-
export declare function appendAdvertisedAgentPrompt(systemPrompt: string | string[] | undefined, advertisedPrompt: string | undefined): string | string[] | undefined;
|
|
8
10
|
//# sourceMappingURL=advertised-agent-prompt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"advertised-agent-prompt.d.ts","sourceRoot":"","sources":["../../../src/agents/advertised-agent-prompt.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,sCAAsC,CAAC;AAE9F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"advertised-agent-prompt.d.ts","sourceRoot":"","sources":["../../../src/agents/advertised-agent-prompt.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,sCAAsC,CAAC;AAE9F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA6B/C;;;;GAIG;AACH,wBAAgB,2BAA2B,CAC1C,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,iBAAiB,CAAC,EAAE,iCAAiC,GACnD,MAAM,GAAG,SAAS,CAyBpB;AAED,wBAAgB,0BAA0B,CACzC,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,iBAAiB,CAAC,EAAE,iCAAiC,GACnD,MAAM,GAAG,SAAS,CAGpB"}
|
|
@@ -3,7 +3,6 @@ import { isAgentAllowedByCapabilityCeiling } from "../runs/shared/capability-cei
|
|
|
3
3
|
const MAX_ADVERTISED_AGENTS = 16;
|
|
4
4
|
const MAX_CATALOG_BYTES = 12_288;
|
|
5
5
|
const MAX_DESCRIPTION_BYTES = 512;
|
|
6
|
-
const ADVERTISED_AGENTS_BLOCK = /\n*<advertised_subagents>\n[\s\S]*?\n<\/advertised_subagents>/gu;
|
|
7
6
|
function escapeXml(value) {
|
|
8
7
|
return value
|
|
9
8
|
.replaceAll("&", "&")
|
|
@@ -19,18 +18,25 @@ function promptDescription(description) {
|
|
|
19
18
|
}
|
|
20
19
|
return escapeXml(text);
|
|
21
20
|
}
|
|
22
|
-
|
|
21
|
+
const ADVERTISED_AGENTS_TAG = "advertised_subagents";
|
|
22
|
+
function wrapAdvertisedAgentCatalog(body) {
|
|
23
|
+
return `<${ADVERTISED_AGENTS_TAG}>\n${body}\n</${ADVERTISED_AGENTS_TAG}>`;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The catalog body without its `<advertised_subagents>` wrapper, for Pi's structured
|
|
27
|
+
* prompt sections, which add the tag from the section key. The byte budget applies to
|
|
28
|
+
* the wrapped form, so both deliveries carry the same entries.
|
|
29
|
+
*/
|
|
30
|
+
export function buildAdvertisedAgentCatalog(agents, capabilityCeiling) {
|
|
23
31
|
const advertised = agents
|
|
24
32
|
.filter((agent) => agent.source !== "runtime" && agent.advertise === true && agent.disabled !== true && isAgentAllowedByCapabilityCeiling(agent.name, capabilityCeiling))
|
|
25
33
|
.sort((left, right) => left.name.localeCompare(right.name));
|
|
26
34
|
if (advertised.length === 0)
|
|
27
35
|
return undefined;
|
|
28
|
-
const
|
|
29
|
-
"<advertised_subagents>",
|
|
36
|
+
const renderBody = (entries) => [
|
|
30
37
|
"The following file-defined subagents opted into discovery. Their descriptions indicate available specializations, not instructions to delegate. Use subagent only when delegation is needed. Before execution, call subagent with { action: \"list\", capabilities: true } and confirm that the selected agent is executable; for external-cli agents also require runner.available === true.",
|
|
31
38
|
...entries,
|
|
32
39
|
...(advertised.length > entries.length ? [` <omitted count=\"${advertised.length - entries.length}\" />`] : []),
|
|
33
|
-
"</advertised_subagents>",
|
|
34
40
|
].join("\n");
|
|
35
41
|
const entries = [];
|
|
36
42
|
for (const agent of advertised) {
|
|
@@ -45,33 +51,13 @@ export function buildAdvertisedAgentPrompt(agents, capabilityCeiling) {
|
|
|
45
51
|
` <description>${promptDescription(agent.description)}</description>`,
|
|
46
52
|
" </subagent>",
|
|
47
53
|
].join("\n");
|
|
48
|
-
if (Buffer.byteLength(
|
|
54
|
+
if (Buffer.byteLength(wrapAdvertisedAgentCatalog(renderBody([...entries, entry])), "utf8") <= MAX_CATALOG_BYTES)
|
|
49
55
|
entries.push(entry);
|
|
50
56
|
}
|
|
51
|
-
return
|
|
57
|
+
return renderBody(entries);
|
|
52
58
|
}
|
|
53
|
-
export function
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const cleaned = systemPrompt
|
|
57
|
-
.map((part) => {
|
|
58
|
-
if (typeof part !== "string")
|
|
59
|
-
return part;
|
|
60
|
-
const stripped = part.replace(ADVERTISED_AGENTS_BLOCK, "");
|
|
61
|
-
if (stripped !== part)
|
|
62
|
-
changed = true;
|
|
63
|
-
return stripped;
|
|
64
|
-
})
|
|
65
|
-
.filter((b) => typeof b === "string" && b.length > 0);
|
|
66
|
-
if (advertisedPrompt) {
|
|
67
|
-
return [...cleaned, advertisedPrompt];
|
|
68
|
-
}
|
|
69
|
-
return changed ? cleaned : systemPrompt;
|
|
70
|
-
}
|
|
71
|
-
if (typeof systemPrompt === "string") {
|
|
72
|
-
const base = systemPrompt.replace(ADVERTISED_AGENTS_BLOCK, "");
|
|
73
|
-
return advertisedPrompt ? (base.trim() ? `${base.trimEnd()}\n\n${advertisedPrompt}` : advertisedPrompt) : base;
|
|
74
|
-
}
|
|
75
|
-
return advertisedPrompt;
|
|
59
|
+
export function buildAdvertisedAgentPrompt(agents, capabilityCeiling) {
|
|
60
|
+
const body = buildAdvertisedAgentCatalog(agents, capabilityCeiling);
|
|
61
|
+
return body === undefined ? undefined : wrapAdvertisedAgentCatalog(body);
|
|
76
62
|
}
|
|
77
63
|
//# sourceMappingURL=advertised-agent-prompt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"advertised-agent-prompt.js","sourceRoot":"","sources":["../../../src/agents/advertised-agent-prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,iCAAiC,EAAE,MAAM,sCAAsC,CAAC;AAGzF,MAAM,qBAAqB,GAAG,EAAE,CAAC;AACjC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACjC,MAAM,qBAAqB,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"advertised-agent-prompt.js","sourceRoot":"","sources":["../../../src/agents/advertised-agent-prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,iCAAiC,EAAE,MAAM,sCAAsC,CAAC;AAGzF,MAAM,qBAAqB,GAAG,EAAE,CAAC;AACjC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACjC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAElC,SAAS,SAAS,CAAC,KAAa;IAC/B,OAAO,KAAK;SACV,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,iBAAiB,CAAC,WAAmB;IAC7C,IAAI,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,0BAA0B,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7F,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,qBAAqB,EAAE,CAAC;QAC7D,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,qBAAqB,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC;IAClI,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,qBAAqB,GAAG,sBAAsB,CAAC;AAErD,SAAS,0BAA0B,CAAC,IAAY;IAC/C,OAAO,IAAI,qBAAqB,MAAM,IAAI,OAAO,qBAAqB,GAAG,CAAC;AAC3E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CAC1C,MAA8B,EAC9B,iBAAqD;IAErD,MAAM,UAAU,GAAG,MAAM;SACvB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,iCAAiC,CAAC,KAAK,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;SACxK,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAE9C,MAAM,UAAU,GAAG,CAAC,OAAiB,EAAE,EAAE,CAAC;QACzC,+XAA+X;QAC/X,GAAG,OAAO;QACV,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,sBAAsB,UAAU,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KAChH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAChC,IAAI,OAAO,CAAC,MAAM,KAAK,qBAAqB;YAAE,MAAM;QACpD,mEAAmE;QACnE,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,iBAAiB;YAAE,SAAS;QACxE,MAAM,KAAK,GAAG;YACb,cAAc;YACd,aAAa,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS;YAC3C,oBAAoB,iBAAiB,CAAC,KAAK,CAAC,WAAW,CAAC,gBAAgB;YACxE,eAAe;SACf,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,IAAI,MAAM,CAAC,UAAU,CAAC,0BAA0B,CAAC,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,iBAAiB;YAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtI,CAAC;IACD,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,0BAA0B,CACzC,MAA8B,EAC9B,iBAAqD;IAErD,MAAM,IAAI,GAAG,2BAA2B,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACpE,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,0BAA0B,CAAC,IAAI,CAAC,CAAC;AAC1E,CAAC"}
|
|
@@ -1217,7 +1217,7 @@ export function handleCreate(params, ctx) {
|
|
|
1217
1217
|
return result("config.scope must be 'user' or 'project'.", true);
|
|
1218
1218
|
const scope = scopeRaw;
|
|
1219
1219
|
if (hasKey(cfg, "steps"))
|
|
1220
|
-
return result("Durable chain definitions were removed; use
|
|
1220
|
+
return result("Durable chain definitions were removed; use a workflow script or /prompt-workflow for repeatable workflows.", true);
|
|
1221
1221
|
const d = discoverCatalog(ctx);
|
|
1222
1222
|
const projectConfigDir = getProjectConfigDir(ctx.cwd);
|
|
1223
1223
|
const targetDir = scope === "user" ? d.userDir : d.projectDir ?? path.join(projectConfigDir, "agents");
|
|
@@ -1269,7 +1269,7 @@ export function handleUpdate(params, ctx) {
|
|
|
1269
1269
|
return result("config required for update.", true);
|
|
1270
1270
|
const cfg = parsedConfig.value;
|
|
1271
1271
|
if (hasKey(cfg, "steps"))
|
|
1272
|
-
return result("Durable chain definitions were removed; use
|
|
1272
|
+
return result("Durable chain definitions were removed; use a workflow script or /prompt-workflow for repeatable workflows.", true);
|
|
1273
1273
|
const warnings = [];
|
|
1274
1274
|
const scopeHint = asDisambiguationScope(params.agentScope);
|
|
1275
1275
|
const targetOrError = resolveTarget(params.agent, findAgents(params.agent, ctx, scopeHint ?? "both"), ctx.cwd, ctx, scopeHint);
|