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.
Files changed (299) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/README.md +1 -1
  3. package/docs/agents.md +30 -16
  4. package/docs/configuration.md +76 -9
  5. package/docs/extension-api.md +6 -5
  6. package/docs/missions.md +28 -14
  7. package/docs/models.md +8 -4
  8. package/docs/observability.md +10 -5
  9. package/docs/tool-reference.md +90 -88
  10. package/docs/workflows.md +166 -172
  11. package/package.json +2 -2
  12. package/prompts/review-loop.md +1 -1
  13. package/skills/council-mode/SKILL.md +1 -1
  14. package/skills/pi-subagents/SKILL.md +12 -5
  15. package/skills/pi-subagents/references/constraints-and-recipes.md +3 -3
  16. package/skills/pi-subagents/references/execution-controls.md +68 -67
  17. package/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
  18. package/skills/pi-subagents/references/multi-lane-orchestration.md +1 -1
  19. package/skills/pi-subagents/references/prompting-and-roles.md +45 -48
  20. package/src/agents/agent-management.js +2 -2
  21. package/src/agents/agent-management.js.map +1 -1
  22. package/src/agents/agents.d.ts +2 -0
  23. package/src/agents/agents.d.ts.map +1 -1
  24. package/src/agents/agents.js +73 -3
  25. package/src/agents/agents.js.map +1 -1
  26. package/src/api/preflight.d.ts +6 -2
  27. package/src/api/preflight.d.ts.map +1 -1
  28. package/src/api/preflight.js +46 -2
  29. package/src/api/preflight.js.map +1 -1
  30. package/src/extension/config.d.ts.map +1 -1
  31. package/src/extension/config.js +15 -4
  32. package/src/extension/config.js.map +1 -1
  33. package/src/extension/control-notices.d.ts +2 -0
  34. package/src/extension/control-notices.d.ts.map +1 -1
  35. package/src/extension/control-notices.js +2 -0
  36. package/src/extension/control-notices.js.map +1 -1
  37. package/src/extension/doctor.d.ts.map +1 -1
  38. package/src/extension/doctor.js +1 -0
  39. package/src/extension/doctor.js.map +1 -1
  40. package/src/extension/fanout-child.d.ts.map +1 -1
  41. package/src/extension/fanout-child.js +13 -3
  42. package/src/extension/fanout-child.js.map +1 -1
  43. package/src/extension/herdr-pi-bridge.d.ts.map +1 -1
  44. package/src/extension/herdr-pi-bridge.js +2 -0
  45. package/src/extension/herdr-pi-bridge.js.map +1 -1
  46. package/src/extension/index.d.ts +1 -1
  47. package/src/extension/index.d.ts.map +1 -1
  48. package/src/extension/index.js +87 -179
  49. package/src/extension/index.js.map +1 -1
  50. package/src/extension/public-execution.d.ts +10 -1
  51. package/src/extension/public-execution.d.ts.map +1 -1
  52. package/src/extension/public-execution.js +73 -35
  53. package/src/extension/public-execution.js.map +1 -1
  54. package/src/extension/reply-workflow-script.d.ts +12 -0
  55. package/src/extension/reply-workflow-script.d.ts.map +1 -0
  56. package/src/extension/reply-workflow-script.js +61 -0
  57. package/src/extension/reply-workflow-script.js.map +1 -0
  58. package/src/extension/rpc.d.ts +2 -0
  59. package/src/extension/rpc.d.ts.map +1 -1
  60. package/src/extension/rpc.js +33 -10
  61. package/src/extension/rpc.js.map +1 -1
  62. package/src/extension/schemas.d.ts +4 -117
  63. package/src/extension/schemas.d.ts.map +1 -1
  64. package/src/extension/schemas.js +42 -127
  65. package/src/extension/schemas.js.map +1 -1
  66. package/src/extension/tool-activation.d.ts +2 -4
  67. package/src/extension/tool-activation.d.ts.map +1 -1
  68. package/src/extension/tool-activation.js +54 -104
  69. package/src/extension/tool-activation.js.map +1 -1
  70. package/src/extension/tool-description.d.ts +8 -5
  71. package/src/extension/tool-description.d.ts.map +1 -1
  72. package/src/extension/tool-description.js +51 -27
  73. package/src/extension/tool-description.js.map +1 -1
  74. package/src/extension/upgrade-notice.d.ts +7 -0
  75. package/src/extension/upgrade-notice.d.ts.map +1 -0
  76. package/src/extension/upgrade-notice.js +37 -0
  77. package/src/extension/upgrade-notice.js.map +1 -0
  78. package/src/integrations/herdr-status.d.ts +3 -0
  79. package/src/integrations/herdr-status.d.ts.map +1 -1
  80. package/src/integrations/herdr-status.js +17 -3
  81. package/src/integrations/herdr-status.js.map +1 -1
  82. package/src/intercom/native-supervisor-channel.d.ts.map +1 -1
  83. package/src/intercom/native-supervisor-channel.js +4 -1
  84. package/src/intercom/native-supervisor-channel.js.map +1 -1
  85. package/src/missions/goal-driver.d.ts +1 -0
  86. package/src/missions/goal-driver.d.ts.map +1 -1
  87. package/src/missions/goal-driver.js +49 -34
  88. package/src/missions/goal-driver.js.map +1 -1
  89. package/src/missions/store.d.ts.map +1 -1
  90. package/src/missions/store.js +11 -1
  91. package/src/missions/store.js.map +1 -1
  92. package/src/profiles/profiles.d.ts +1 -1
  93. package/src/profiles/profiles.d.ts.map +1 -1
  94. package/src/profiles/profiles.js +4 -0
  95. package/src/profiles/profiles.js.map +1 -1
  96. package/src/runs/background/async-execution.d.ts +16 -0
  97. package/src/runs/background/async-execution.d.ts.map +1 -1
  98. package/src/runs/background/async-execution.js +95 -8
  99. package/src/runs/background/async-execution.js.map +1 -1
  100. package/src/runs/background/async-job-tracker.d.ts +1 -0
  101. package/src/runs/background/async-job-tracker.d.ts.map +1 -1
  102. package/src/runs/background/async-job-tracker.js +67 -24
  103. package/src/runs/background/async-job-tracker.js.map +1 -1
  104. package/src/runs/background/async-retention.d.ts +1 -1
  105. package/src/runs/background/async-retention.d.ts.map +1 -1
  106. package/src/runs/background/async-retention.js +47 -15
  107. package/src/runs/background/async-retention.js.map +1 -1
  108. package/src/runs/background/await-async-run.d.ts +23 -0
  109. package/src/runs/background/await-async-run.d.ts.map +1 -0
  110. package/src/runs/background/await-async-run.js +82 -0
  111. package/src/runs/background/await-async-run.js.map +1 -0
  112. package/src/runs/background/chain-root-attachment.d.ts +1 -0
  113. package/src/runs/background/chain-root-attachment.d.ts.map +1 -1
  114. package/src/runs/background/chain-root-attachment.js +3 -3
  115. package/src/runs/background/chain-root-attachment.js.map +1 -1
  116. package/src/runs/background/control-channel.d.ts +10 -0
  117. package/src/runs/background/control-channel.d.ts.map +1 -1
  118. package/src/runs/background/control-channel.js +51 -0
  119. package/src/runs/background/control-channel.js.map +1 -1
  120. package/src/runs/background/notify.d.ts +3 -0
  121. package/src/runs/background/notify.d.ts.map +1 -1
  122. package/src/runs/background/notify.js +3 -0
  123. package/src/runs/background/notify.js.map +1 -1
  124. package/src/runs/background/run-child-session.d.ts.map +1 -1
  125. package/src/runs/background/run-child-session.js +24 -7
  126. package/src/runs/background/run-child-session.js.map +1 -1
  127. package/src/runs/background/run-status.d.ts.map +1 -1
  128. package/src/runs/background/run-status.js +6 -0
  129. package/src/runs/background/run-status.js.map +1 -1
  130. package/src/runs/background/runner-aliases.d.ts +1 -0
  131. package/src/runs/background/runner-aliases.d.ts.map +1 -1
  132. package/src/runs/background/runner-aliases.js +6 -2
  133. package/src/runs/background/runner-aliases.js.map +1 -1
  134. package/src/runs/background/runner-child-launch.d.ts +1 -0
  135. package/src/runs/background/runner-child-launch.d.ts.map +1 -1
  136. package/src/runs/background/runner-child-launch.js +2 -0
  137. package/src/runs/background/runner-child-launch.js.map +1 -1
  138. package/src/runs/background/scheduled-runs.d.ts +2 -1
  139. package/src/runs/background/scheduled-runs.d.ts.map +1 -1
  140. package/src/runs/background/scheduled-runs.js +33 -16
  141. package/src/runs/background/scheduled-runs.js.map +1 -1
  142. package/src/runs/background/stale-run-reconciler.d.ts +1 -1
  143. package/src/runs/background/stale-run-reconciler.d.ts.map +1 -1
  144. package/src/runs/background/stale-run-reconciler.js +15 -2
  145. package/src/runs/background/stale-run-reconciler.js.map +1 -1
  146. package/src/runs/background/subagent-runner.d.ts +3 -0
  147. package/src/runs/background/subagent-runner.d.ts.map +1 -1
  148. package/src/runs/background/subagent-runner.js +49 -3
  149. package/src/runs/background/subagent-runner.js.map +1 -1
  150. package/src/runs/foreground/async-stop-action.d.ts.map +1 -1
  151. package/src/runs/foreground/async-stop-action.js +15 -1
  152. package/src/runs/foreground/async-stop-action.js.map +1 -1
  153. package/src/runs/foreground/command-action.d.ts +13 -0
  154. package/src/runs/foreground/command-action.d.ts.map +1 -0
  155. package/src/runs/foreground/command-action.js +38 -0
  156. package/src/runs/foreground/command-action.js.map +1 -0
  157. package/src/runs/foreground/execution.d.ts.map +1 -1
  158. package/src/runs/foreground/execution.js +27 -6
  159. package/src/runs/foreground/execution.js.map +1 -1
  160. package/src/runs/foreground/subagent-executor.d.ts +7 -5
  161. package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  162. package/src/runs/foreground/subagent-executor.js +356 -192
  163. package/src/runs/foreground/subagent-executor.js.map +1 -1
  164. package/src/runs/shared/child-commands.d.ts +28 -0
  165. package/src/runs/shared/child-commands.d.ts.map +1 -0
  166. package/src/runs/shared/child-commands.js +250 -0
  167. package/src/runs/shared/child-commands.js.map +1 -0
  168. package/src/runs/shared/child-launch.d.ts +5 -1
  169. package/src/runs/shared/child-launch.d.ts.map +1 -1
  170. package/src/runs/shared/child-launch.js +15 -1
  171. package/src/runs/shared/child-launch.js.map +1 -1
  172. package/src/runs/shared/child-session.d.ts +13 -0
  173. package/src/runs/shared/child-session.d.ts.map +1 -1
  174. package/src/runs/shared/child-session.js +182 -19
  175. package/src/runs/shared/child-session.js.map +1 -1
  176. package/src/runs/shared/child-tool-plan.d.ts +4 -0
  177. package/src/runs/shared/child-tool-plan.d.ts.map +1 -1
  178. package/src/runs/shared/child-tool-plan.js +12 -5
  179. package/src/runs/shared/child-tool-plan.js.map +1 -1
  180. package/src/runs/shared/claude-code-adapter.d.ts +56 -0
  181. package/src/runs/shared/claude-code-adapter.d.ts.map +1 -1
  182. package/src/runs/shared/claude-code-adapter.js +138 -2
  183. package/src/runs/shared/claude-code-adapter.js.map +1 -1
  184. package/src/runs/shared/dynamic-fanout.js +2 -2
  185. package/src/runs/shared/dynamic-fanout.js.map +1 -1
  186. package/src/runs/shared/external-cli-preflight.d.ts +10 -0
  187. package/src/runs/shared/external-cli-preflight.d.ts.map +1 -1
  188. package/src/runs/shared/external-cli-preflight.js +50 -6
  189. package/src/runs/shared/external-cli-preflight.js.map +1 -1
  190. package/src/runs/shared/external-cli-runner.d.ts.map +1 -1
  191. package/src/runs/shared/external-cli-runner.js +4 -2
  192. package/src/runs/shared/external-cli-runner.js.map +1 -1
  193. package/src/runs/shared/mcp-config-sources.d.ts +1 -0
  194. package/src/runs/shared/mcp-config-sources.d.ts.map +1 -1
  195. package/src/runs/shared/mcp-config-sources.js +1 -1
  196. package/src/runs/shared/mcp-config-sources.js.map +1 -1
  197. package/src/runs/shared/mcp-direct-tool-allowlist.d.ts +28 -0
  198. package/src/runs/shared/mcp-direct-tool-allowlist.d.ts.map +1 -1
  199. package/src/runs/shared/mcp-direct-tool-allowlist.js +79 -2
  200. package/src/runs/shared/mcp-direct-tool-allowlist.js.map +1 -1
  201. package/src/runs/shared/model-resolution.d.ts +16 -2
  202. package/src/runs/shared/model-resolution.d.ts.map +1 -1
  203. package/src/runs/shared/model-resolution.js +39 -11
  204. package/src/runs/shared/model-resolution.js.map +1 -1
  205. package/src/runs/shared/model-scope.d.ts +2 -1
  206. package/src/runs/shared/model-scope.d.ts.map +1 -1
  207. package/src/runs/shared/model-scope.js +26 -10
  208. package/src/runs/shared/model-scope.js.map +1 -1
  209. package/src/runs/shared/parallel-utils.d.ts +4 -0
  210. package/src/runs/shared/parallel-utils.d.ts.map +1 -1
  211. package/src/runs/shared/parallel-utils.js.map +1 -1
  212. package/src/runs/shared/pi-spawn.d.ts +1 -10
  213. package/src/runs/shared/pi-spawn.d.ts.map +1 -1
  214. package/src/runs/shared/pi-spawn.js +7 -86
  215. package/src/runs/shared/pi-spawn.js.map +1 -1
  216. package/src/runs/shared/run-history.d.ts +47 -0
  217. package/src/runs/shared/run-history.d.ts.map +1 -1
  218. package/src/runs/shared/run-history.js +70 -0
  219. package/src/runs/shared/run-history.js.map +1 -1
  220. package/src/runs/shared/subagent-control.d.ts.map +1 -1
  221. package/src/runs/shared/subagent-control.js +30 -17
  222. package/src/runs/shared/subagent-control.js.map +1 -1
  223. package/src/runs/shared/subagent-prompt-runtime.d.ts +1 -0
  224. package/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  225. package/src/runs/shared/subagent-prompt-runtime.js +14 -5
  226. package/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  227. package/src/runs/shared/worktree.d.ts +1 -1
  228. package/src/runs/shared/worktree.d.ts.map +1 -1
  229. package/src/runs/shared/worktree.js +1 -1
  230. package/src/runs/shared/worktree.js.map +1 -1
  231. package/src/shared/disabled-features.d.ts +92 -0
  232. package/src/shared/disabled-features.d.ts.map +1 -0
  233. package/src/shared/disabled-features.js +113 -0
  234. package/src/shared/disabled-features.js.map +1 -0
  235. package/src/shared/extension-context.d.ts +9 -0
  236. package/src/shared/extension-context.d.ts.map +1 -1
  237. package/src/shared/extension-context.js +7 -0
  238. package/src/shared/extension-context.js.map +1 -1
  239. package/src/shared/required-child-extensions.d.ts +16 -1
  240. package/src/shared/required-child-extensions.d.ts.map +1 -1
  241. package/src/shared/required-child-extensions.js +37 -5
  242. package/src/shared/required-child-extensions.js.map +1 -1
  243. package/src/shared/settings.d.ts +1 -1
  244. package/src/shared/types.d.ts +26 -1
  245. package/src/shared/types.d.ts.map +1 -1
  246. package/src/shared/types.js +1 -1
  247. package/src/shared/types.js.map +1 -1
  248. package/src/slash/prompt-template-bridge.js +2 -2
  249. package/src/slash/prompt-template-bridge.js.map +1 -1
  250. package/src/slash/slash-commands.d.ts +2 -0
  251. package/src/slash/slash-commands.d.ts.map +1 -1
  252. package/src/slash/slash-commands.js +2 -2
  253. package/src/slash/slash-commands.js.map +1 -1
  254. package/src/slash/subagent-cost.d.ts.map +1 -1
  255. package/src/slash/subagent-cost.js +8 -4
  256. package/src/slash/subagent-cost.js.map +1 -1
  257. package/src/tui/render.d.ts +1 -1
  258. package/src/tui/render.d.ts.map +1 -1
  259. package/src/tui/render.js +59 -21
  260. package/src/tui/render.js.map +1 -1
  261. package/src/watchdog/diff-tool.d.ts +3 -1
  262. package/src/watchdog/diff-tool.d.ts.map +1 -1
  263. package/src/watchdog/diff-tool.js +20 -11
  264. package/src/watchdog/diff-tool.js.map +1 -1
  265. package/src/watchdog/register-child.js +2 -2
  266. package/src/watchdog/register-child.js.map +1 -1
  267. package/src/watchdog/register-main.js +2 -2
  268. package/src/watchdog/register-main.js.map +1 -1
  269. package/src/watchdog/review.d.ts +1 -1
  270. package/src/watchdog/review.d.ts.map +1 -1
  271. package/src/watchdog/review.js +1 -1
  272. package/src/watchdog/review.js.map +1 -1
  273. package/src/watchdog/turn-delta.js +1 -1
  274. package/src/watchdog/turn-delta.js.map +1 -1
  275. package/src/workflows/chat-progress.js +2 -2
  276. package/src/workflows/chat-progress.js.map +1 -1
  277. package/src/workflows/scripted-workflow.d.ts +8 -0
  278. package/src/workflows/scripted-workflow.d.ts.map +1 -1
  279. package/src/workflows/scripted-workflow.js +10 -2
  280. package/src/workflows/scripted-workflow.js.map +1 -1
  281. package/src/workflows/structured-workflow-scripts.d.ts +10 -0
  282. package/src/workflows/structured-workflow-scripts.d.ts.map +1 -0
  283. package/src/workflows/structured-workflow-scripts.js +166 -0
  284. package/src/workflows/structured-workflow-scripts.js.map +1 -0
  285. package/src/workflows/workflow-receipt.d.ts.map +1 -1
  286. package/src/workflows/workflow-receipt.js +10 -4
  287. package/src/workflows/workflow-receipt.js.map +1 -1
  288. package/src/workflows/workflow-resources.d.ts +13 -0
  289. package/src/workflows/workflow-resources.d.ts.map +1 -1
  290. package/src/workflows/workflow-resources.js +46 -16
  291. package/src/workflows/workflow-resources.js.map +1 -1
  292. package/src/workflows/workflow-reuse.d.ts +51 -0
  293. package/src/workflows/workflow-reuse.d.ts.map +1 -0
  294. package/src/workflows/workflow-reuse.js +103 -0
  295. package/src/workflows/workflow-reuse.js.map +1 -0
  296. package/src/workflows/workflow-revival.d.ts +32 -0
  297. package/src/workflows/workflow-revival.d.ts.map +1 -0
  298. package/src/workflows/workflow-revival.js +111 -0
  299. package/src/workflows/workflow-revival.js.map +1 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,106 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.75.0] - 2026-10-02
6
+
7
+ ### Highlights
8
+
9
+ - Background subagents work on Pi 1.0.0 again. In 0.74.0 they failed to start with "does not provide @earendil-works/pi-agent-core/node".
10
+ - The built-in `claude-code` and `claude-code-writer` agents can pick a Claude model and effort level per launch, for example `model: "claude-opus-5.5:high"`.
11
+ - On Windows, `claude-code`, `codex-exec`, and `cursor-agent` can now launch CLIs installed with npm.
12
+ - Children on a virtual model from an extension, such as a model router set as `subagents.defaultModel`, now launch and pass model verification.
13
+ - An invalid config value no longer silently turns off `authorityPolicy`, `permissions`, or `toolBudget`. Loading the config fails instead.
14
+
15
+ ### Added
16
+
17
+ - The built-in `claude-code` and `claude-code-writer` agents accept a model and thinking level per launch or in agent frontmatter, and pass them to Claude Code as `--model` and `--effort`. Before, the model could only be set in your global Claude Code settings. `model: "claude-opus-5.5:high"` sets both; `model: ":high"` sets only the effort. An unknown model or level fails the launch and names it. `subagents.maxThinking` and an enforced `subagents.modelScope` apply to these launches; with an enforced scope, a launch that sets no model fails, because Claude Code's default model cannot be checked. Other external runners still reject both fields. See [agents](docs/agents.md). Thanks to [@lexxbyte](https://github.com/lexxbyte) for [#2602](https://github.com/nicobailon/pi-subagents/issues/2602).
18
+ - The parent can now manage a long `bash` command inside a native Pi child that is granted both `bash` and `subagent_command`: `command.status` shows it, `command.yield` lets the child continue while the command keeps running, and `command.cancel` stops only that command. The child can do the same itself with `bash`'s `yieldTimeMs` and the `subagent_command` tool. Commands use Pi's own shell and are stopped when the child exits, and a child that finishes with a command still running fails. Thanks to [@jiuai233](https://github.com/jiuai233) for [#2598](https://github.com/nicobailon/pi-subagents/pull/2598).
19
+ - Hosts that require child extensions with `registerRequiredChildExtensions` can pass `requireForAllRunners: true`. Only local Pi children can load those extensions, so with this flag a launch on an external CLI, an external job, or another machine is refused before it starts instead of running without them. The requirement stays with the run, including nested, resumed, and workflow children, even after the host removes its registration. Without the flag, external runners are skipped as before. See [agents](docs/agents.md). Thanks to [@doc-krieger](https://github.com/doc-krieger) for [#2639](https://github.com/nicobailon/pi-subagents/issues/2639).
20
+ - `schedule.create` accepts an existing `missionId`, so a scheduled workflow keeps the same mission state across runs and session restarts. Schedules with a mission are saved in a new format that older pi-subagents versions reject instead of silently dropping the mission; other schedules keep the old format. Thanks to [@quifox](https://github.com/quifox) for [#2616](https://github.com/nicobailon/pi-subagents/pull/2616).
21
+ - `asyncWidgetCollapsed: true` starts the async widget under the editor folded to one line. Clicking its header still unfolds it, and the default is unchanged. Thanks to [@unrelentingfox](https://github.com/unrelentingfox) for [#2621](https://github.com/nicobailon/pi-subagents/pull/2621).
22
+
23
+ ### Changed
24
+
25
+ - CI now runs the clean-install test against both Pi `0.86.1` and `1.0.0`, as separate jobs with separate logs. Thanks to [@EightDoor](https://github.com/EightDoor) for [#2648](https://github.com/nicobailon/pi-subagents/pull/2648).
26
+
27
+ ### Fixed
28
+
29
+ - Background subagents failed to start on Pi 1.0.0 with "does not provide @earendil-works/pi-agent-core/node", because Pi 1.0.0 no longer ships that module. They now start without it, and still fail if Pi includes the module but the file is missing. Thanks to [@albertgwo](https://github.com/albertgwo) for [#2634](https://github.com/nicobailon/pi-subagents/pull/2634).
30
+ - An invalid value for any config key no longer silently drops `authorityPolicy`, `permissions`, or `toolBudget`. If the config file sets any of them, loading now fails instead of continuing with an empty config that would allow what those settings forbid. (#2622)
31
+ - A required child extension (`registerRequiredChildExtensions`) that throws during `session_start` now stops the launch. Before, Pi only reported the error, so the child still started and could send model requests without the policy the extension was meant to set up. Ordinary extensions are unchanged: their startup errors are reported and the child still starts. Thanks to [@doc-krieger](https://github.com/doc-krieger) for reporting [#2639](https://github.com/nicobailon/pi-subagents/issues/2639).
32
+ - On Windows, external-CLI agents such as `claude-code`, `codex-exec`, and `cursor-agent` failed with `EINVAL` when the CLI was installed with npm, because npm installs it as a `.cmd` file that Node cannot start without a shell. The runner now runs the CLI's script with Node directly, still without a shell, and refuses any other `.cmd` or `.bat` file. Thanks to [@lexxbyte](https://github.com/lexxbyte) for tracing the cause in [#2631](https://github.com/nicobailon/pi-subagents/issues/2631).
33
+ - A child could not launch on a virtual model that an extension registers with `pi.registerVirtualModel()`, such as a router set as `subagents.defaultModel`. The child looked up its model before the extension's virtual models were registered, so the name matched a model on another provider and the launch failed on that provider's missing API key. Virtual models are now registered first, and a required extension whose registration fails stops the launch. Thanks to [@mauroziux](https://github.com/mauroziux) for [#2636](https://github.com/nicobailon/pi-subagents/pull/2636) (#2635).
34
+ - A child on a virtual model failed with `model_verification_failed` even when it ran correctly, because the check compared the launch model with the real model the router picked. For virtual models, the check now compares the child's selected model with the launch model. Other children are checked as before. Thanks to [@mauroziux](https://github.com/mauroziux) for reporting [#2637](https://github.com/nicobailon/pi-subagents/issues/2637) (#2635).
35
+ - A background chain whose `expand` step runs an external-CLI agent such as `claude-code` failed with "Dynamic chain step N parallel does not support field 'runner'". Each item now runs through that agent's runner, and its output is collected like any parallel child. Thanks to [@lexxbyte](https://github.com/lexxbyte) for reporting [#2629](https://github.com/nicobailon/pi-subagents/issues/2629).
36
+ - Saving builtin agent overrides no longer risks a half-written settings file: if the save is interrupted, the previous settings stay readable. Thanks to [@quifox](https://github.com/quifox) for [#2627](https://github.com/nicobailon/pi-subagents/pull/2627).
37
+ - Codex children now keep tool-call IDs in the `call_id|item_id` form when both parts are at most 64 characters and use only letters, digits, `_`, or `-`. Other IDs are shortened as before. Thanks to [@jtabke](https://github.com/jtabke) for [#2628](https://github.com/nicobailon/pi-subagents/pull/2628) (#2623).
38
+ - With Pi's built-in MCP, `mcp:` entries whose server or tool name contains `-`, such as `mcp:srv/get-item`, failed with "selects MCP tools that Pi's built-in MCP does not offer". pi-subagents now converts `-` to `_` the same way Pi names the tool, so you keep writing names as the server reports them. Thanks to [@sheurich](https://github.com/sheurich) for [#2607](https://github.com/nicobailon/pi-subagents/issues/2607).
39
+ - Some MCP clients, such as pi-claude-bridge, send `workflow: true` as the string `"true"`, which failed with an error asking for `workflow: true`. The string now works the same as the boolean (#2600).
40
+ - `action: "validate"` now checks workflow `args` against the same limits as a launch: 16 fields per object, 64 items per array, depth 8, and 16 KiB total. A script that validates no longer fails at launch because of its `args`. ([#2608](https://github.com/nicobailon/pi-subagents/issues/2608))
41
+ - The parent is now told about every tool call that stays open past the attention threshold, not only the first one in each child. Thanks to [@jiuai233](https://github.com/jiuai233) for [#2598](https://github.com/nicobailon/pi-subagents/pull/2598).
42
+ - Async runs now reach `run-history.jsonl`. Before, only foreground runs were recorded, so per-agent lookups missed every background launch. Single-step runs record the same row as a foreground run, multi-step runs record one row per child step, and a paused run records as `interrupted`, with a later resume recording again. Thanks to [@limin411](https://github.com/limin411) for [#2620](https://github.com/nicobailon/pi-subagents/pull/2620).
43
+ - `/subagent-cost` and the RPC `cost` method now count every round of a resumed foreground workflow child. Before, every round after the first was dropped as a duplicate, so totals came out low with no warning. Results recorded before this fix still undercount. Thanks to [@chagwood](https://github.com/chagwood) for [#2601](https://github.com/nicobailon/pi-subagents/issues/2601).
44
+ - `/subagent-cost` and the RPC `cost` method no longer log a missing-receipt error on every call for foreground workflows. An async workflow that has no receipt yet, such as one still running, is now listed as `Async child usage unavailable` instead of being left out of the total without notice. (#2614)
45
+ - The global mission list now takes title, status, update time, and latest run from each mission's own record, so a mission no longer looks out of date because its index entry is stale. Thanks to [@quifox](https://github.com/quifox) for [#2618](https://github.com/nicobailon/pi-subagents/pull/2618).
46
+ - Headless sessions now deliver goal-mission notices even when finishing background work fails. The failure is still reported to the caller. Thanks to [@quifox](https://github.com/quifox) for [#2605](https://github.com/nicobailon/pi-subagents/pull/2605).
47
+ - One mission with a damaged run status or state no longer stops continuation notices for healthy goal missions. The damaged mission is reported separately. Thanks to [@quifox](https://github.com/quifox) for [#2604](https://github.com/nicobailon/pi-subagents/pull/2604).
48
+ - On Linux, a runner process that exited but was not yet cleaned up by the system no longer leaves its run marked as running, or a workflow waiting for a result that will never arrive. Thanks to [@quifox](https://github.com/quifox) for [#2606](https://github.com/nicobailon/pi-subagents/pull/2606).
49
+ - Saved subagent profiles with an invalid `machine` value are now rejected when loaded or checked, before any settings are written. `machine: false` still clears a pin. Thanks to [@quifox](https://github.com/quifox) for [#2619](https://github.com/nicobailon/pi-subagents/pull/2619).
50
+
51
+ ## [0.74.0] - 2026-09-30
52
+
53
+ ### Highlights
54
+
55
+ - Workflow scripts are now written as a normal ```` ```js workflow ```` code block in the reply and run with `workflow: true`, with no JSON escaping. This replaces `workflowScript` and `workflowScriptPath`.
56
+ - On models that cannot add a tool mid-conversation, `subagent` is now available from the start, so turning it on no longer reprocesses the whole conversation at full price.
57
+ - The new `disabledFeatures` setting hides parts of the `subagent` tool you do not use, and with `workflow-scripts` turned off you can run children with simple `chain` and `tasks` lists.
58
+ - `/reload` and session resumes no longer kill running background workflows, and relaunching one reuses the children that already finished.
59
+ - Subagent children now respect an untrusted project the same way the main session does.
60
+
61
+ ### Added
62
+
63
+ - `disabledFeatures` in `config.json` removes feature groups you do not use from the `subagent` tool, such as agent management, watchdog, panes, missions, lane management, and per-call options like `toolBudget` or `machine`. Their parameters disappear from the tool, the tool description stops mentioning them, and calls that still use them fail with an error that names the setting. `scheduledRuns.enabled: false` now removes the schedule parameters the same way, and a malformed `scheduledRuns` value is now a config error. Nothing changes unless you opt in. With everything disabled, the tool declaration shrinks from 18,239 to 10,263 characters. See [configuration](docs/configuration.md#disabledfeatures). Thanks to [@tmustier](https://github.com/tmustier) for [#2542](https://github.com/nicobailon/pi-subagents/pull/2542).
64
+ - `disabledFeatures` also accepts `workflow-scripts`. It removes the `workflow`, `args`, `preflight`, `globalConcurrencyLimit`, and `maxSubagentSpawnsPerRun` parameters and the `validate` action, and the tool description no longer explains how to write scripts. In their place, the tool takes `tasks: [{ agent, task }]` to run children in parallel and `chain: [{ agent, task?, as? } | { parallel: [{ agent, task }] }]` to run steps in order. Chain tasks can use `{task}` (the top-level `task`), `{previous}`, and `{outputs.name}`. If a child fails, the run fails but still returns the results of the children that finished. Scripts that still arrive from RPC, `/prompt-workflow`, saved schedules, or delegated launches fail with an error that names the setting; `/run` still works. This mode saves about 2,000 more characters of tool declaration. Without it, the tool is unchanged. In both modes, extensions can no longer register workflow resources named `chain` or `tasks`. See [configuration](docs/configuration.md#chain-and-tasks-without-workflow-scripts).
65
+ - On Pi 0.99 and later without pi-mcp-adapter, `mcp:server` and `mcp:server/tool` entries in an agent's `tools` now select tools from Pi's built-in MCP, and the child gets exactly those tools. Servers from `mcp.json` work in foreground and background children; servers that extensions add with `pi.registerMcpServer()` work in background children. With pi-mcp-adapter installed, nothing changes. Thanks to [@fmoda3](https://github.com/fmoda3) for [#2555](https://github.com/nicobailon/pi-subagents/issues/2555).
66
+ - `subagents.modelScope` allow lists accept a `scoped` token, which stands for the parent session's scoped models (Pi's `/scoped-models`). Subagent model limits then follow Pi's model scoping without a second copy of the list. In an unscoped session, `scoped` means the same as `inherit`. Error messages list at most 8 patterns before summarizing the rest. Thanks to [@coreyryanhanson](https://github.com/coreyryanhanson) for [#2538](https://github.com/nicobailon/pi-subagents/pull/2538).
67
+ - `subagents.agentOverrides.<name>.advertise` lists an agent in the parent's agent catalog from settings, so you no longer have to copy a builtin agent file just to advertise it. Agents registered at runtime still cannot be advertised. Thanks to [@strive-run](https://github.com/strive-run) for [#2534](https://github.com/nicobailon/pi-subagents/pull/2534).
68
+ - Native Pi subagents can use Pi's built-in `codemode` tool when their tool selection allows it. It is loaded only in the child, so the main session can keep codemode off. Older Pi versions without codemode still report it as unavailable when an agent asks for it. Thanks to [@albertgwo](https://github.com/albertgwo) for [#2574](https://github.com/nicobailon/pi-subagents/pull/2574).
69
+ - After you upgrade pi-subagents, your first interactive session shows a short notice with the highlights of each new version and a link to the changelog. It is shown once and never enters the conversation, so it does not affect the model's context or prompt cache. Fresh installs and child sessions show nothing.
70
+
71
+ ### Changed
72
+
73
+ - **Breaking:** Workflow scripts had to be passed to the `subagent` tool as a JSON string, so every quote and newline was escaped. The tool now takes one `workflow` field with three forms: `workflow: true` runs the single ```` ```js workflow ```` code block written in the same reply; a string containing `/` (such as `"./ci/sweep.js"`) loads a script file relative to `cwd`; any other string runs a named workflow. The `workflowScript` and `workflowScriptPath` parameters were removed, and calls that still pass them fail with an error that shows the new forms. RPC `spawn` takes inline script text as `script` and a path or workflow name as `workflow`. Saved schedules and run records keep working.
74
+ - On models that cannot take a new tool mid-conversation, calling `subagents_enable` made the provider reprocess the whole conversation at the uncached price. New sessions on those models now start with `subagent` already available. Models that can add tools mid-conversation still start with `subagents_enable`. Resumed sessions keep the tools they had, and switching models mid-session does not change them. The new `toolActivation` setting in `config.json` chooses `"auto"` (the default), `"dynamic"` (always start with `subagents_enable`, the old behavior), or `"eager"` (always start with `subagent`, like `--exclude-tools subagents_enable`). See [configuration](docs/configuration.md#toolactivation). Thanks to [@tinoy1336](https://github.com/tinoy1336) for [#2589](https://github.com/nicobailon/pi-subagents/issues/2589).
75
+ - After `subagents_enable`, the model was sometimes told to wait for the next prompt even when `subagent` was already usable. It is now told to check its tool list: use `subagent` if it is there, otherwise wait for the next prompt instead of retrying.
76
+ - CI now runs the tool-activation smoke test as a required check. Thanks to [@quifox](https://github.com/quifox) for [#2528](https://github.com/nicobailon/pi-subagents/pull/2528).
77
+
78
+ ### Fixed
79
+
80
+ - Subagent children now follow the parent session's project trust. Before, a child in an untrusted project still loaded that project's settings, system prompt files, skills and, for background children, its extensions. Fixes [#2569](https://github.com/nicobailon/pi-subagents/issues/2569).
81
+ - `/reload`, a session resume, or a pi-web project switch stopped running background workflows and their children, and relaunching the script ran every child again, including ones that had already finished. Background children now keep running, the workflow's notice says to relaunch it, and relaunching the same script with the same args reuses finished children and waits for running ones. Failed children run again. The stop is recorded as `workflow.stopCause: "runtime-replaced"`. Fixes [#2546](https://github.com/nicobailon/pi-subagents/issues/2546).
82
+ - Stopping a background workflow by a short id, its tool-call id, its run directory, or from the Fleet view did nothing, so the workflow and its children kept running. These stops now work, and the workflow ends as stopped. Fixes [#2571](https://github.com/nicobailon/pi-subagents/issues/2571).
83
+ - Reviving a failed background workflow child with `subagent({ action: "resume", id })` did not show up in the workflow: its status, receipt and keyed `latest: true` resume still pointed at the failed run. Workflow `status` now shows `Revived → <run>: <state>` under the failed key, keyed resume continues from the revived run, and a workflow that finishes afterwards records the revival in its receipt and completion notice. The workflow's return value is unchanged. Thanks to [@l3gz](https://github.com/l3gz) for reporting [#2579](https://github.com/nicobailon/pi-subagents/issues/2579).
84
+ - When a workflow script failed and stopped a sibling that was still running, the sibling got a "Workflow child failed" notice whose error began with a "Run fan-out: N/M used, K remaining" line. The notice now says the child was stopped and gives only the reason. Fixes [#2562](https://github.com/nicobailon/pi-subagents/issues/2562) and [#2567](https://github.com/nicobailon/pi-subagents/issues/2567).
85
+ - After pi-subagents was updated on disk while Pi was running, for example by `git pull` in a local checkout or a package update, the first `subagent` call could fail with an error such as `(0 , _publicExecution.isWorkflowScriptPath) is not a function`, because it mixed new and old code. pi-subagents now loads all of its code shortly after a session starts, without slowing startup. After an update, run `/reload` or restart Pi to use the new version.
86
+ - With Pi 0.99's `codemode` turned on, codemode scripts could call `subagent`, `subagents_enable`, `subagent_supervisor`, `contact_supervisor` and `structured_output`, none of which work from a script: a `subagent` run there had no progress card and was cancelled unless awaited, `contact_supervisor` blocked the script, and `structured_output` had no effect. Codemode also added the whole `subagent` schema to its own description, about 2,200 extra tokens per request. The model can still call these tools directly, but scripts can no longer call them. Older Pi versions are unaffected.
87
+ - With the `subagent` tool registered, every request to llama.cpp (`llama-server --jinja`) failed with a 400 error because one parameter's pattern was not anchored at both ends, which llama.cpp requires. The pattern is now anchored and accepts the same values. Thanks to [@tychart](https://github.com/tychart) for reporting [#2581](https://github.com/nicobailon/pi-subagents/issues/2581).
88
+ - With pi-mcp-adapter 3.x on Pi 0.99 or later, `mcp:` entries in an agent's `tools` looked up Pi's built-in MCP instead of the adapter, so choosing an adapter server failed the launch. The adapter now takes priority whenever it is loaded. Fixes [#2575](https://github.com/nicobailon/pi-subagents/issues/2575).
89
+ - After upgrading pi-mcp-adapter to 3.1.0, `mcp:` tool selections for stdio servers stopped resolving, because the adapter started including `inheritEnv` and `literalEnv` in its config hash. pi-subagents now computes the same hash. Thanks to [@qsgy-edge](https://github.com/qsgy-edge) for [#2539](https://github.com/nicobailon/pi-subagents/pull/2539).
90
+ - When the async widget did not have room for its full view, its compact card showed one line per run and filled the rest with blank rows, hiding a workflow's lanes. The card now shows the lanes in that space and is only as tall as its content. Thanks to [@l3gz](https://github.com/l3gz) for reporting [#2578](https://github.com/nicobailon/pi-subagents/issues/2578).
91
+ - The async widget and the Fleet view counted running agents differently: with a 4-lane workflow and one other run, the widget said `2 agents running` and the Fleet view said `5 active agents`. The widget now counts each running workflow lane and each agent of a parallel run, like the Fleet view. Thanks to [@l3gz](https://github.com/l3gz) for reporting [#2578](https://github.com/nicobailon/pi-subagents/issues/2578).
92
+ - Herdr's subagent count no longer counts a workflow's coordinator as a child, and it updates as soon as a foreground workflow child starts or finishes instead of up to 45 seconds later. Thanks to [@xadips](https://github.com/xadips) for [#2556](https://github.com/nicobailon/pi-subagents/pull/2556).
93
+ - Dynamic tool activation now works when Pi runs inside another app, such as pi-web. Those hosts no longer print "Could not locate the running Pi installation" and no longer fall back to keeping `subagent` always loaded. Thanks to [@q107580018](https://github.com/q107580018) for [#2526](https://github.com/nicobailon/pi-subagents/issues/2526).
94
+ - Answering a background subagent's supervisor request no longer triggers a stale "needs attention" notice afterwards. The notice now waits 60 seconds and is sent only if the request is still unanswered and the run is still active. Status views still show the request right away.
95
+ - `inheritSkills: false` now also removes skills that extensions add to a child session (for example through `subagents.defaultExtensions`), so they no longer appear next to the agent's own skills. Thanks to [@zeezooz](https://github.com/zeezooz) for [#2540](https://github.com/nicobailon/pi-subagents/issues/2540).
96
+ - A child that was aborted by compaction now recovers when Pi reports the compaction late. Thanks to [@jiuai233](https://github.com/jiuai233) for [#2537](https://github.com/nicobailon/pi-subagents/pull/2537).
97
+ - Old background runs that belong to a finished or deleted mission are now cleaned up like other old runs instead of being kept forever. Fixes [#2535](https://github.com/nicobailon/pi-subagents/issues/2535). Thanks to [@LCorleone](https://github.com/LCorleone) for [#2536](https://github.com/nicobailon/pi-subagents/pull/2536).
98
+ - On Windows, the Pi interface froze for about 0.45 seconds once per process while background run cleanup waited on a PowerShell query. The query no longer blocks the interface. Thanks to [@localhedge](https://github.com/localhedge) for reporting [#2559](https://github.com/nicobailon/pi-subagents/issues/2559).
99
+ - On Windows, an idle session no longer checks for supervisor requests every 250 ms for its whole lifetime. Checking stops when no subagent work is pending and starts again when new work begins, as it already did on macOS. Thanks to [@localhedge](https://github.com/localhedge) for reporting [#2558](https://github.com/nicobailon/pi-subagents/issues/2558).
100
+ - Starting, reloading, resuming, or forking a session no longer pauses Pi while the watchdog records the current Git commit (about 50 ms per session start on Windows, even with the watchdog off). The check now runs in the background. Thanks to [@localhedge](https://github.com/localhedge) for reporting [#2560](https://github.com/nicobailon/pi-subagents/issues/2560).
101
+ - Worktree diffs now work with older Git versions that lack the `--default-prefix` option. Thanks to [@quifox](https://github.com/quifox) for [#2527](https://github.com/nicobailon/pi-subagents/pull/2527).
102
+ - Updated `undici` from 8.10.0 to 8.10.2, outside the range of [GHSA-3wwx-pv8p-q78v](https://github.com/advisories/GHSA-3wwx-pv8p-q78v), so projects that install pi-subagents no longer fail `npm audit` because of it. pi-subagents does not use the affected WebSocket client. Thanks to [@advaitpaliwal](https://github.com/advaitpaliwal) for [#2548](https://github.com/nicobailon/pi-subagents/pull/2548).
103
+ - A package-discovery test no longer fails when the system temp directory is inside a Pi project. Thanks to [@abdwhb-png](https://github.com/abdwhb-png) for [#2553](https://github.com/nicobailon/pi-subagents/pull/2553).
104
+
5
105
  ## [0.73.1] - 2026-09-27
6
106
 
7
107
  ### Highlights
package/README.md CHANGED
@@ -44,7 +44,7 @@ Pi is the parent session. A subagent is a focused child Pi session with its own
44
44
 
45
45
  When you ask for a subagent, Pi starts the child, gives it the task, and brings the result back. Foreground children run as sessions inside the parent Pi process and stream in the conversation. Background children run as sessions inside a detached runner process that keeps working and can be checked later.
46
46
 
47
- Installing the extension does not start an automatic reviewer in the background. Fresh parent sessions initially expose the small `subagents_enable` loader instead of the full `subagent` schema. When your request or applicable instructions authorize delegation, Pi can call the loader itself; the unchanged `subagent` tool is available on the next model request. Complexity alone does not authorize delegation. `bg_wait` and supervisor replies remain available without activation.
47
+ Installing the extension does not start an automatic reviewer in the background. When the session's model can take a new tool mid-conversation, fresh parent sessions initially expose the small `subagents_enable` loader instead of the full `subagent` schema. When your request or applicable instructions authorize delegation, Pi can call the loader itself; the unchanged `subagent` tool is available on the next model request. With other models, fresh sessions start with `subagent` active, because adding a tool later would make the provider miss its prompt cache. The [`toolActivation`](docs/configuration.md#toolactivation) setting changes this. Complexity alone does not authorize delegation. `bg_wait` and supervisor replies remain available without activation.
48
48
 
49
49
  If you want every implementation reviewed, say so in your prompt or project instructions:
50
50
 
package/docs/agents.md CHANGED
@@ -110,12 +110,20 @@ The built-in `claude-code` and `claude-code-writer` profiles are the supported C
110
110
 
111
111
  Both adapters own `claude -p` argv with stream JSON, strict empty MCP configuration, user-only setting sources, no session persistence, disabled slash commands, and disabled Chrome integration. The writer mode does not include Bash or any permission bypass. Neither mode uses `--bare`, which does not read normal OAuth/keychain authentication. Neither mode requires `--safe-mode`, which is absent from the installed 2.1.150 help. User profiles cannot add argv. Selecting the code-owned `claude-code-writer` adapter identity is the only way to opt into its write tools; the read-only adapter cannot be widened with user argv.
112
112
 
113
+ A `model`, and a thinking level carried on it as a `:level` suffix, are the one thing these two adapters do accept from a launch; the same two fields work in agent frontmatter. They become Claude Code's own `--model` and `--effort` rather than a Pi child model, so one launch can pin `claude-opus-5.5` with `high` effort without changing the operator's global Claude Code settings. The model must be an alias or a model id, and both values are checked before launch, so an unusable value fails the launch by name and no other token can be added.
114
+
115
+ The level travels as the same `:level` suffix Pi children use, on the `model` field: `model: "claude-opus-5.5:high"` pins the model and the effort, and `model: ":high"` asks for the effort alone. A suffix wins over the frontmatter `thinking` value. `off` passes no `--effort` and `minimal` maps to `low`, and a launch that requests no level leaves the flag out, so Claude Code's own default effort applies and this repository cannot bound it. `off` therefore means "pass no flag", not "no thinking".
116
+
117
+ `subagents.maxThinking` applies here the way it does to a native Pi child: a request above the ceiling fails before the child starts, compared on the requested level rather than on the effort it maps to. An enforced `subagents.modelScope` applies too, checked against the id that will reach the CLI; a launch that pins no model at all fails closed, because the CLI's own default cannot be checked. Every other external runner still refuses both fields.
118
+
113
119
  Run it asynchronously:
114
120
 
115
121
  ```text
116
122
  Use claude-code to analyze this handoff without editing files.
117
123
 
118
124
  Use claude-code-writer to make the requested file changes.
125
+
126
+ Use claude-code-writer with model claude-sonnet-5:high to make the requested file changes.
119
127
  ```
120
128
 
121
129
  The adapter validates `claude --version` and `claude --help` only when a run launches. Discovery, list, status, and native Pi launches do not execute Claude Code or probe authentication. A capabilities listing performs only a passive PATH/PATHEXT/X_OK lookup and exposes the command as `runner.available`; that does not prove authentication or launch compatibility. JSONL, stderr, and stdout are untrusted. A run succeeds only after bounded valid JSONL contains exactly one successful terminal `result` with non-empty final text. Missing or revoked local authentication, limit stops, malformed JSON, duplicate terminal results, and EOF before a terminal result fail closed.
@@ -220,7 +228,7 @@ You can override selected agent fields without copying the whole agent. Override
220
228
  }
221
229
  ```
222
230
 
223
- Supported override fields: `description`, `machine`, `output`, `outputMode`, `defaultReads`, `model`, `defaultProvider`, `thinking`, `systemPromptMode`, `inheritProjectContext`, `inheritGlobalContext`, `inheritSkills`, `defaultContext`, `acceptanceRole`, `disabled`, `skills`, `tools`, and `systemPrompt`.
231
+ Supported override fields: `description`, `advertise`, `machine`, `output`, `outputMode`, `defaultReads`, `model`, `defaultProvider`, `thinking`, `systemPromptMode`, `inheritProjectContext`, `inheritGlobalContext`, `inheritSkills`, `defaultContext`, `acceptanceRole`, `disabled`, `skills`, `tools`, and `systemPrompt`.
224
232
 
225
233
  - `description` replaces the discovered description for builtin and custom agents, which lets list output show deployment-specific routing or model metadata.
226
234
  - Use `output: false`, `defaultReads: false`, `defaultContext: false`, `acceptanceRole: false`, or `machine: false` to clear an inherited value.
@@ -265,7 +273,7 @@ pi-subagents never clones, pulls, or checks out on the machine. Generic `externa
265
273
 
266
274
  ## Parent prompt discovery
267
275
 
268
- Set `advertise: true` in a specialist's agent file frontmatter for parent-prompt discovery. When the `subagent` tool is active, pi-subagents adds an agent-owned catalog of names and descriptions to the parent system prompt. Disabled agents and agents excluded by the current capability ceiling are omitted. Advertisement is not supported through settings overrides or runtime registration.
276
+ Set `advertise: true` in a specialist's agent file frontmatter for parent-prompt discovery, or in `subagents.agentOverrides.<name>.advertise` when the definition must stay untouched. When the `subagent` tool is active, pi-subagents adds an agent-owned catalog of names and descriptions to the parent system prompt. Disabled agents and agents excluded by the current capability ceiling are omitted. Advertisement is not supported through runtime registration.
269
277
 
270
278
  Advertisement is opt-in discovery, not automatic routing. The catalog is sorted by name and limited to 16 agents and 12,288 total rendered UTF-8 bytes, including XML escaping, instructions, and omission counts. Descriptions are capped at 512 UTF-8 bytes before escaping. Entries that cannot fit are omitted; canonical agent names are never truncated. The parent still calls `subagent({ action: "list", capabilities: true })` before execution to confirm that the selected agent is executable (including `runner.available === true` for external CLI agents).
271
279
 
@@ -345,18 +353,18 @@ Field notes:
345
353
  | `package` | Optional package identifier. A file with `name: scout` and `package: code-analysis` registers as `code-analysis.scout`; serialization keeps `name` and `package` separate. |
346
354
  | `advertise` | Set `true` to include this agent's name and description in the parent system prompt when the `subagent` tool is active. Defaults to `false`. |
347
355
  | `aliases` | Optional comma-separated or block-list names that resolve to this agent for selection and explicit `agent` and task inputs. Runtime status, persistence, and config still use the canonical `name`. Exact canonical names take precedence over aliases, and alias collisions between distinct canonical agents fail as ambiguous. |
348
- | `tools` | Strict child tool allowlist. Named extension tools must also have their provider loaded. `mcp:` entries select direct MCP tools when `pi-mcp-adapter` is installed. |
356
+ | `tools` | Strict child tool allowlist. Named extension tools must also have their provider loaded. `mcp:` entries select direct MCP tools from `pi-mcp-adapter` when it is installed, and from Pi's built-in MCP otherwise. |
349
357
  | `excludeTools` | Optional child tool deny-list applied after normal tool resolution. With an explicit `tools` allowlist, matching names are removed; when `tools` is omitted, the names are excluded from the child session's default tool set. Unknown names are ignored by Pi without making the agent definition invalid. |
350
358
  | `allowNestedSubagents` | Set `true` to authorize the child-safe nested `subagent` runtime without making omitted `tools` an allowlist. Inherited depth and capability ceilings remain authoritative. |
351
359
  | `allowedAgents` | Restricts which canonical, case-sensitive agent names this agent may launch. Omitted adds no restriction; an empty list denies every descendant launch. This only narrows an existing nesting grant: `tools: subagent` or `allowNestedSubagents: true` is still required. Inherited/runtime allowlists are intersected and cannot be widened. |
352
360
  | `extensions` | Omitted means a background child loads the parent's ambient extensions; empty means no ambient extensions; list values load exactly those extensions. Foreground children never load ambient extensions, so for them only listed values apply. |
353
361
  | `subagentOnlyExtensions` | Extension paths loaded only in this agent's child sessions. Tools registered there are unavailable to the main agent unless also installed through normal Pi extension configuration. |
354
- | `model` | Default model. Bare ids prefer the current provider when possible, then unique registry matches. |
355
- | `thinking` | Appended as a `:level` suffix at runtime unless a suffix is already present. |
362
+ | `model` | Default model. Bare ids prefer the current provider when possible, then unique registry matches. On the two Claude Code adapters this is Claude Code's own alias or id, and a trailing `:level` picks the effort. |
363
+ | `thinking` | Appended as a `:level` suffix at runtime unless a suffix is already present. On the two Claude Code adapters it becomes `--effort`, and a suffix on `model` wins over it. |
356
364
  | `systemPromptMode` | `replace` by default; `append` keeps Pi's base prompt. |
357
365
  | `inheritProjectContext` | Keeps or strips inherited repository instruction blocks. |
358
366
  | `inheritGlobalContext` | Keeps or strips the operator's global context file from the Pi config agent directory (e.g. `~/.pi/agent/AGENTS.md`). It has an effect only when `inheritProjectContext` is `true`; otherwise all context files are already disabled. Defaults to `false`. |
359
- | `inheritSkills` | Keeps or strips Pi's discovered skills catalog. |
367
+ | `inheritSkills` | Keeps or strips Pi's discovered skills catalog. For in-process children this includes skills that loaded extensions add; herdr-placed children rely on Pi's `--no-skills`. |
360
368
  | `defaultContext` | Optional `fresh` or `fork` launch-context preference. An implicit `fork` falls back to `fresh` when the parent has no persisted session file or current leaf; an explicit launch `context: "fork"` remains strict. |
361
369
  | `skills` | Selects specific skills for the child, regardless of `inheritSkills`. |
362
370
  | `skillPath` | Invocation-private skill files or discovery directories. Relative paths resolve from the agent definition file. Local matches take precedence, while unresolved or unreadable matches fall back to normal skill discovery. This field discovers candidates only; `skills` still selects what the child receives. |
@@ -375,9 +383,11 @@ Field notes:
375
383
 
376
384
  ### Required host extensions
377
385
 
378
- Hosts can import `registerRequiredChildExtensions` from `pi-subagents/required-child-extensions` and register `{ sessionId, extensions: [{ id, path }] }`. Paths resolve to existing files and are canonicalized into an immutable launch snapshot; bounded safe IDs appear in evidence instead of paths. One registration is allowed per parent session until its idempotent `dispose()` runs, normally on `session_shutdown`.
386
+ Hosts can import `registerRequiredChildExtensions` from `pi-subagents/required-child-extensions` and register `{ sessionId, extensions: [{ id, path }], requireForAllRunners? }`. Paths resolve to existing files and are canonicalized into an immutable launch snapshot; bounded safe IDs appear in evidence instead of paths. One registration is allowed per parent session until its idempotent `dispose()` runs, normally on `session_shutdown`.
379
387
 
380
- Required paths follow ordinary extension resolution and survive agent defaults and `extensions: []` across native foreground, detached, nested, and recovery launches. A `capabilityCeiling.denyExtensions` conflict or required load/provider-registration failure rejects before model resolution. External runners are excluded, and status/watch paths do not query the registry.
388
+ Required paths follow ordinary extension resolution and survive agent defaults and `extensions: []` across native foreground, detached, nested, and recovery launches. A `capabilityCeiling.denyExtensions` conflict or required load/provider-registration failure rejects before model resolution. An error a required extension reports while the child binds its extensions, such as a throwing `session_start` handler, disposes the child and rejects the launch before its first prompt. By default external runners are excluded (they run without the required extensions), and status/watch paths do not query the registry.
389
+
390
+ With `requireForAllRunners: true`, a launch that resolves to an external CLI runner, an external-job runner, or a machine placement is rejected before a runner process, provider job, or remote owner starts, because only local native Pi children load these extensions. The requirement stays with the run through nested, detached, resumed, recovered, workflow-script, and appended launches, so disposing the registration or setting `extensions: []` cannot drop it. Launch preflight previews the runner-type rejection for the session's current registration; machine placement and requirements retained by nested or resumed runs are checked at launch.
381
391
 
382
392
  Successful completion is determined by observable gates such as process outcome, required outputs, explicit acceptance, verification commands, independent review, and staged-index integrity. Best-effort mutation observations remain diagnostic: unchanged or unknown evidence does not fail a run, and observed changes do not prove correctness.
383
393
 
@@ -442,9 +452,9 @@ How `tools` behaves:
442
452
 
443
453
  `excludeTools` is applied after this resolution. It can narrow an explicit `tools` allowlist or, when `tools` is omitted, remove names from Pi's default builtin tool set. Runtime-injected tools are excluded only when their exact names are listed. An empty `excludeTools` list has no effect.
444
454
 
445
- An allowlisted name does not load the extension that registers it. Load that provider through `extensions`, `subagentOnlyExtensions`, a path-like `tools` entry, or (background children only) normal Pi extension discovery.
455
+ An allowlisted name does not load the extension that registers it. Load that provider through `extensions`, `subagentOnlyExtensions`, a path-like `tools` entry, or (background children only) normal Pi extension discovery. Pi's built-in `codemode` is the exception: native children register the host SDK's official factory when codemode is permitted, without enabling it in the main session. On older Pi hosts without that factory, a child that requests codemode still reports it as unavailable; a capability ceiling that denies extensions prevents its registration.
446
456
 
447
- Ambient extensions depend on where the child runs. Local foreground children are sessions inside the parent Pi process and never load the parent's ambient extensions; otherwise the parent would start a second copy of each ambient extension, including this one. Background children are sessions inside the detached runner process and load the ambient extensions unless the agent sets `extensions` or the capability ceiling denies extensions. Local foreground children do inherit the providers the parent's extensions registered (`pi.registerProvider`), so their models resolve without loading those extensions again. Pane-native remote foreground children instead use 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 therefore run as background children (`async: true`). A foreground launch of such an agent fails with a diagnostic that says exactly that.
457
+ Ambient extensions depend on where the child runs. Local foreground children are sessions inside the parent Pi process and never load the parent's ambient extensions; otherwise the parent would start a second copy of each ambient extension, including this one. Background children are sessions inside the detached runner process and load the ambient extensions unless the agent sets `extensions` or the capability ceiling denies extensions. Local foreground children do inherit the providers the parent's extensions registered (`pi.registerProvider`), so their models resolve without loading those extensions again. Pane-native remote foreground children instead use the remote machine's provider discovery and configuration. Agents that need MCP tools from an ambient adapter such as pi-mcp-adapter (including `mcp:` entries the adapter resolves) must therefore run as background children (`async: true`). A foreground launch of such an agent fails with a diagnostic that says exactly that.
448
458
 
449
459
  More rules:
450
460
 
@@ -462,7 +472,9 @@ Examples:
462
472
  - `allowNestedSubagents: true` with `tools` omitted: normal builtin tools (and, for background children, ambient extensions) remain inherited, and the child-safe nested `subagent` runtime is added.
463
473
  - `tools: read, fixture_search` plus `subagentOnlyExtensions: ./tools/fixture-search.ts`: the provider loads only in this agent's child sessions, and the registered `fixture_search` name survives the strict allowlist.
464
474
 
465
- Direct MCP tools require [pi-mcp-adapter](https://github.com/nicobailon/pi-mcp-adapter). Subagents only receive direct MCP tools when `mcp:` entries are listed in their frontmatter; global `directTools: true` in the adapter's MCP config is not enough by itself. The generic `mcp` proxy tool can still be used for discovery when available. The adapter caches tool metadata at startup, so after connecting a new MCP server for the first time, restart Pi before relying on direct tools. Server `includeTools` and `excludeTools` policies are enforced while resolving cached metadata for children: both accept exact names and `*`/`?` glob patterns against raw, generated-resource, and server/short/mcp/none-prefixed names, with `excludeTools` taking precedence. `mcp:` entries must name servers from the adapter's configuration files. A server that exists only in the adapter's runtime snapshot (registered at runtime, not persisted) cannot be provided to a child: children are pi sessions inside the parent or the runner process, not `pi` processes that could receive an MCP config argument, so such a launch fails with an error saying that MCP tools must come from an ambient adapter extension in a background child. An `mcp:` entry named `subagent` does not authorize nested fanout; declare the builtin `subagent` tool or set `allowNestedSubagents: true`. If a resolved direct MCP name is missing from the child registry, pi-subagents keeps the launch failed under the strict allowlist and reports the registration mismatch; check the resolved names against what the host or pi-mcp-adapter actually registers before child startup.
475
+ When [pi-mcp-adapter](https://github.com/nicobailon/pi-mcp-adapter) is not installed and Pi has built-in MCP (Pi 0.99 or later), `mcp:server` and `mcp:server/tool` entries resolve against Pi's built-in MCP. Name the server and tool as the server reports them: `mcp:my-docs/get-item` selects the tool Pi registers as `mcp__my_docs__get_item`. The child connects the servers in Pi's `mcp.json` (the project's `.pi/mcp.json` only when the parent trusts the project) and gets only the selected tools, as direct tools, whatever exposure the server is configured with; tools configured as `hidden` cannot be selected. Servers that an extension adds with `pi.registerMcpServer()` work in background children, because the registering extension loads there too. They do not work in foreground children, which load no ambient extensions, so a foreground launch that selects one fails and says to use `async: true`. The launch fails if a selected tool does not register in the child within 10 seconds.
476
+
477
+ When pi-mcp-adapter is installed, it keeps priority and provides the direct MCP tools. Subagents only receive direct MCP tools when `mcp:` entries are listed in their frontmatter; global `directTools: true` in the adapter's MCP config is not enough by itself. The generic `mcp` proxy tool can still be used for discovery when available. The adapter caches tool metadata at startup, so after connecting a new MCP server for the first time, restart Pi before relying on direct tools. Server `includeTools` and `excludeTools` policies are enforced while resolving cached metadata for children: both accept exact names and `*`/`?` glob patterns against raw, generated-resource, and server/short/mcp/none-prefixed names, with `excludeTools` taking precedence. `mcp:` entries must name servers from the adapter's configuration files. A server that exists only in the adapter's runtime snapshot (registered at runtime, not persisted) cannot be provided to a child: children are pi sessions inside the parent or the runner process, not `pi` processes that could receive an MCP config argument, so such a launch fails with an error saying that MCP tools must come from an ambient adapter extension in a background child. An `mcp:` entry named `subagent` does not authorize nested fanout; declare the builtin `subagent` tool or set `allowNestedSubagents: true`. If a resolved direct MCP name is missing from the child registry, pi-subagents keeps the launch failed under the strict allowlist and reports the registration mismatch; check the resolved names against what the host or pi-mcp-adapter actually registers before child startup.
466
478
 
467
479
  `extensions` controls child extension loading:
468
480
 
@@ -498,12 +510,14 @@ Discovery uses project-first precedence:
498
510
  6. User packages and user settings packages via `package.json -> pi.skills`
499
511
  7. `~/.pi/agent/settings.json -> skills`
500
512
 
501
- Use agent defaults, override them at runtime, or disable them:
513
+ Use agent defaults, override them at runtime, or disable them inside the ```` ```js workflow ```` block:
502
514
 
503
- ```ts
504
- { workflowScript: `return runs.run("main", { agent: "scout", task: "..." })` }
505
- { workflowScript: `return runs.run("main", { agent: "scout", task: "...", skill: "tmux, safe-bash" })` }
506
- { workflowScript: `return runs.run("main", { agent: "scout", task: "...", skill: false })` }
515
+ ```js
516
+ return runs.all([
517
+ { key: "default", agent: "scout", task: "..." },
518
+ { key: "override", agent: "scout", task: "...", skill: "tmux, safe-bash" },
519
+ { key: "disabled", agent: "scout", task: "...", skill: false },
520
+ ])
507
521
  ```
508
522
 
509
523
  For chains, `skill` at the top level is additive. A step-level `skill` overrides that step; `false` disables skills for that step.
@@ -2,7 +2,7 @@
2
2
 
3
3
  `pi-subagents` reads optional JSON config from `~/.pi/agent/extensions/subagent/config.json`. This page lists every key, plus the environment variables and the settings-file keys that affect config resolution.
4
4
 
5
- Settings-level keys (`subagents.defaultModel`, `defaultProvider`, `defaultThinking`, `defaultExtensions`, `defaultSubagentOnlyExtensions`, `agentOverrides`, `machines`, `agentScanDirs`, `agentExcludeDirs`, `modelScope`, `disableThinking`, `disableBuiltins`, watchdog settings) live in Pi settings files, not this config file. `modelScope.agents.<name>` adds per-agent restrictions, and `allow: ["inherit"]` permits the current parent model. See [models.md](models.md), [agents.md](agents.md), and [watchdog.md](watchdog.md).
5
+ Settings-level keys (`subagents.defaultModel`, `defaultProvider`, `defaultThinking`, `defaultExtensions`, `defaultSubagentOnlyExtensions`, `agentOverrides`, `machines`, `agentScanDirs`, `agentExcludeDirs`, `modelScope`, `disableThinking`, `disableBuiltins`, watchdog settings) live in Pi settings files, not this config file. `modelScope.agents.<name>` adds per-agent restrictions, `allow: ["inherit"]` permits the current parent model, and `allow: ["scoped"]` permits the parent session's scoped models (the parent model when the session is unscoped). See [models.md](models.md), [agents.md](agents.md), and [watchdog.md](watchdog.md).
6
6
 
7
7
  ## Project root resolution (settings)
8
8
 
@@ -76,14 +76,30 @@ For a native Pi `model_verification_failed` where your proxy accepts `claude-hai
76
76
 
77
77
  Replace `YOUR_PROVIDER` with the resolved Pi provider ID. Keep the outgoing model alias unchanged. This native remedy already exists in v0.65.1; it does not infer equivalence from provider prefixes or dates. The built-in external `claude-code` adapter does not invoke this verifier or use this setting. If an external run shows this diagnostic, identify the installed version, resolved runner kind/adapter, and error location before applying a native remedy. Thanks to [sixtus](https://github.com/sixtus) for the concrete request-ID/response-ID example in [#1922](https://github.com/nicobailon/pi-subagents/issues/1922).
78
78
 
79
+ A local Pi child whose selected model is a virtual model (`pi.registerVirtualModel()`, such as a router) needs no alias. Its assistant messages name whichever physical model the router picked, so verification compares the child's selected virtual `provider/id` with the launch model instead, exactly. A different virtual selection fails, and `modelResponseAliases` does not override it.
80
+
79
81
  ## Tool activation lifecycle
80
82
 
81
- On Pi 0.86.1 or newer, a fresh unrestricted parent starts with `subagents_enable`, `bg_wait`, and `subagent_supervisor` active while `subagent` stays registered but inactive. Calling `subagents_enable({})` preserves unrelated active tools and exposes `subagent` on the next model request. It does not launch a child or infer authority from prompt keywords.
83
+ On Pi 0.86.1 or newer, when the model can take a new tool mid-conversation (see [`toolActivation`](#toolactivation)), a fresh unrestricted parent starts with `subagents_enable`, `bg_wait`, and `subagent_supervisor` active while `subagent` stays registered but inactive. Calling `subagents_enable({})` preserves unrelated active tools and exposes `subagent` on the next model request. It does not launch a child or infer authority from prompt keywords. With other models, a fresh parent starts with `subagent`, `bg_wait`, and `subagent_supervisor` active and no `subagents_enable`.
82
84
 
83
- The recorded native `subagent` selection is restored on resume, reload, and tree navigation, so an activated session stays activated and a cold session stays cold. Older history without tool-selection records keeps eager `subagent` availability. If Pi's allowlist or exclusions remove the loader, the extension does not hide `subagent`; if they remove `subagent`, the loader reports it unavailable. Hosts older than the verified dynamic-tool baseline keep eager behavior and log one compatibility warning.
85
+ The recorded native `subagent` selection is restored on resume, reload, and tree navigation, so an activated session stays activated and a cold session stays cold. With the default `toolActivation`, the recorded `subagents_enable` selection is restored too, so a session that started without the loader never gets it later. Older history without tool-selection records keeps eager `subagent` availability. If Pi's allowlist or exclusions remove the loader, the extension does not hide `subagent`; if they remove `subagent`, the loader reports it unavailable. Hosts whose extension API lacks `getAllTools`, `getActiveTools`, or `setActiveTools` keep eager behavior and log one compatibility warning. The host version is not read from disk, so in-process hosts such as pi-web activate the same way as the Pi CLI.
84
86
 
85
87
  Some providers fix the tool list for a whole prompt, for example bridges that hand Pi's tools to another agent SDK. There `subagent` appears only on the next user prompt, not the next model request. Start Pi with `--exclude-tools subagents_enable` to keep `subagent` active from the start.
86
88
 
89
+ ## `toolActivation`
90
+
91
+ ```json
92
+ { "toolActivation": "eager" }
93
+ ```
94
+
95
+ Controls how a new parent session offers the `subagent` tool. The default is `"auto"`.
96
+
97
+ - `"auto"`: a new session starts with the `subagents_enable` loader only when its model can take a new tool mid-conversation. Otherwise it starts with `subagent` active and no loader, because calling the loader on such a model makes Pi resend the conversation in a form the provider may not have cached. A model qualifies when its Pi `compat` settings set `supportsMidConvoSystemMessages: true` and, for its API, `supportsMidConvoToolChanges: true` (`anthropic-messages`), `supportsMidConvoToolAdditions: true` (`openai-completions`), or `supportsAdditionalTools: true` or `supportsToolSearch: true` (`openai-responses`, `openai-codex-responses`, `azure-openai-responses`). Other APIs, missing settings, and no model do not qualify.
98
+ - `"dynamic"`: every new session starts with the loader, whatever the model. This was the behavior before `toolActivation` existed.
99
+ - `"eager"`: the loader is not registered, so `subagent` is active from the first request, as with `--exclude-tools subagents_enable`. A resumed session that recorded the loader changes its tool list once on the next request.
100
+
101
+ The choice is made at session start or tree navigation, and only for a session with no messages. Resumed sessions keep the tools they recorded, and switching models mid-session does not change them. `"auto"` avoids only the loader's cache miss; other tool-list or provider changes can still miss the cache. An active `subagent` sends its full schema on every request. An invalid value is a config error, not a fallback to the default. Restart Pi after changing it.
102
+
87
103
  ## `toolDescriptionMode`
88
104
 
89
105
  ```json
@@ -94,6 +110,49 @@ Controls the parent-facing `subagent` tool description registered at startup. Th
94
110
 
95
111
  `custom` reads `subagent-tool-description.md` from the project config directory, then from `~/.pi/agent/subagent-tool-description.md`. Missing, empty, unreadable, or oversized custom files fall back to the full description. Custom templates may use `{{fullDescription}}`, `{{compactDescription}}`, `{{safetyGuidance}}`, `{{agentDir}}`, and `{{projectConfigDir}}`; the safety guidance is always present so custom prose cannot remove the runtime guardrails. Restart Pi after changing the mode or custom file.
96
112
 
113
+ ## `disabledFeatures`
114
+
115
+ ```json
116
+ { "disabledFeatures": ["watchdog", "panes", "preflight", "lane-metadata", "gates"] }
117
+ ```
118
+
119
+ Removes feature groups you do not use from the `subagent` tool. Each listed feature loses its parameters from the model-facing schema, and any request that still uses one of its parameters or actions fails with an error naming this setting. The check covers the parent tool, fanout-child tools, RPC, slash commands, prompt templates, scheduled launches, delegated launches, and workflow `runs.run`/`runs.all`/`runs.lanes` children, which are rejected before they launch. The built-in tool descriptions, the unknown-action list, the fanout-child tool description, and RPC `ping` no longer mention disabled features, and `{ action: "guide", topic: "tool-reference" }` starts with a notice listing what is disabled. Custom tool descriptions are not changed. Nothing is disabled by default, and the default schema and description are unchanged. An unknown or duplicate feature name fails config loading rather than silently re-enabling every feature.
120
+
121
+ | Feature | Parameters removed | Actions rejected |
122
+ |---|---|---|
123
+ | `agent-management` | `config` | `create`, `update`, `delete`, `eject`, `disable`, `enable`, `reset`, `refine`, `refine.show`, `refine.rollback` |
124
+ | `watchdog` | `scope`, `target`, `thinking` | `watchdog.status`, `watchdog.check`, `watchdog.configure`, `watchdog.recommend-model` |
125
+ | `panes` | `focus` | `inspector.*`, `project.*` |
126
+ | `missions` | `mission`, `missionUpdate`, `missionStatus`, `missionScope`, `missionId`, `runMode`, `runStatus`, `summary` | `mission.*` |
127
+ | `lane-management` | `handoffPath`, `laneId`, `merge`, `supersession`, `repo`, `planId` | `lane.status`, `lane.recordMerge`, `lane.recordSupersession`, `worktree.discard`, `worktree.cleanup` |
128
+ | `spawn-budget-grants` | `additional` | `grant-spawn-budget` |
129
+ | `preflight` | `preflight` | |
130
+ | `lane-metadata` | `lane` | |
131
+ | `gates` | `gate` | |
132
+ | `usage-budgets` | `usageBudget` | |
133
+ | `tool-budgets` | `toolBudget` | |
134
+ | `control-overrides` | `control` | |
135
+ | `extension-bindings` | `extensionBindings` | |
136
+ | `external-machines` | `machine` | |
137
+ | `workflow-scripts` | `workflow`, `args`, `preflight`, `globalConcurrencyLimit`, `maxSubagentSpawnsPerRun` | `validate` |
138
+
139
+ Disabling a per-call option removes only the per-call override. Configured defaults such as `toolBudget`, `usageBudget`, and `control` in this file still apply, the watchdog still follows its own settings, missions still attach automatically when [`missions`](#missions) enables them, and agents with a `machine` in their definition still run there. Operator screens that do not go through the `subagent` executor, such as `/subagents-admin`, are unchanged. With every feature and [`scheduledRuns.enabled`](#scheduledruns) disabled, the default `subagent` tool declaration (name, description, and parameter schema as JSON) shrinks from 18,239 to 10,263 characters (80 to 41 parameters). Restart Pi after changing this setting.
140
+
141
+ ### Chain and tasks without workflow scripts
142
+
143
+ `workflow-scripts` removes workflow scripts and named workflow resources from every entry point. The model can no longer write a script, and a script that still arrives from RPC `spawn` (`script` or `workflow`), `/prompt-workflow`, a saved schedule, or a delegated launch fails with an error that names the setting. Schedule inspection, pause, and delete still work, but `schedule.create` cannot succeed because it needs a script. `/run` still works: it launches its one child directly. The built-in tool description and prompt snippet drop the script guidance and describe two small inputs instead:
144
+
145
+ - `tasks: [{ agent, task }, ...]` runs the children in parallel and returns their results in order.
146
+ - `chain: [step, ...]` runs steps in order. A step is `{ agent, task?, as? }` or a parallel group `{ parallel: [{ agent, task }, ...] }`. A group waits for all of its children.
147
+
148
+ A top-level `task` is the original request. Tasks can use three placeholders:
149
+
150
+ - `{task}` is the top-level `task`. Using it without a top-level `task` is an error.
151
+ - `{previous}` is the output of the previous chain step. For a parallel group, the outputs are joined in input order with a blank line between them. A chain step without `task` uses `{previous}`. The first step has no previous output, so it needs a `task` and cannot use `{previous}`.
152
+ - `{outputs.name}` is the output of an earlier sequential step that set `as: "name"`. Names are identifiers, and each name can be used once.
153
+
154
+ `tasks` items can only use `{task}`. Placeholders are replaced in one pass, so placeholder text inside an output is not replaced again. Other brace text stays as written. `chain` and `tasks` exclude each other, `agent`, and `action`. Steps accept only the fields above, and inputs are limited to 64 items and 16 KiB. Top-level child options such as `model`, `skill`, `output`, and `worktree` apply to every child. If a child fails, the run fails: a chain stops after the failed step or group, `tasks` fails once every child has settled, and the error names each failed child. The results of the children that already finished are still returned. Without this setting, `chain` and `tasks` are rejected as removed legacy inputs.
155
+
97
156
  ## `inlineToolDisplay`
98
157
 
99
158
  ```json
@@ -165,7 +224,7 @@ Set `enabled` to `false` (or remove the block) as a kill switch. In that state,
165
224
  { "asyncByDefault": false }
166
225
  ```
167
226
 
168
- WorkflowScript calls use background execution when the request omits `async`. Set `asyncByDefault` to `false` to restore foreground-by-default behavior for tool launches that still use the internal single-run primitive. Callers can still force foreground with `async: false` unless `forceTopLevelAsync` is enabled.
227
+ Workflow script calls use background execution when the request omits `async`. Set `asyncByDefault` to `false` to restore foreground-by-default behavior for tool launches that still use the internal single-run primitive. Callers can still force foreground with `async: false` unless `forceTopLevelAsync` is enabled.
169
228
 
170
229
  ## `defaultSubagentContext`
171
230
 
@@ -237,6 +296,14 @@ Prompt modes keep their fixed keys. For example, `Esc` still cancels steer text
237
296
 
238
297
  Controls the under-editor widget for active background runs. It defaults to `true`, including when FleetView is enabled, so active work remains visible after reload. Set it to `false` to hide this widget while keeping FleetView available.
239
298
 
299
+ ## `asyncWidgetCollapsed`
300
+
301
+ ```json
302
+ { "asyncWidgetCollapsed": true }
303
+ ```
304
+
305
+ Starts each newly mounted under-editor async widget in its one-line folded state. It defaults to `false`. A header click still toggles the widget, and the folded state still resets when the widget is removed or Pi reloads.
306
+
240
307
  ## `waitTool`
241
308
 
242
309
  ```json
@@ -273,7 +340,7 @@ Forces depth-0 internal single, parallel, and chain runs into background mode an
273
340
  { "timeoutMs": 3600000 }
274
341
  ```
275
342
 
276
- Global default runtime deadline, in milliseconds, for subagent runs. It replaces the built-in 30-minute backstop for foreground launches (single, parallel, chain, and workflowScript) and plain single-agent async runs whenever no call-level `timeoutMs`/`maxRuntimeMs` applies. For single-agent launches, selected agent frontmatter `timeoutMs` still wins. This only moves the *default*. Expiring this run-level deadline is terminal.
343
+ Global default runtime deadline, in milliseconds, for subagent runs. It replaces the built-in 30-minute backstop for foreground launches (single, parallel, chain, and workflow scripts) and plain single-agent async runs whenever no call-level `timeoutMs`/`maxRuntimeMs` applies. For single-agent launches, selected agent frontmatter `timeoutMs` still wins. This only moves the *default*. Expiring this run-level deadline is terminal.
277
344
 
278
345
  This deadline bounds the whole run. The wait for a single model response is bounded separately by Pi's `httpIdleTimeoutMs` setting (default 300000; `0` disables it), which Pi applies both as the SDK request timeout and as the undici header/body idle timeout. Detached async runners read the same setting from `~/.pi/agent/settings.json` and the project `.pi/settings.json` for their own HTTP dispatcher, so a local model that queues or prefills for longer than five minutes needs `httpIdleTimeoutMs` raised or disabled in Pi settings, plus a `timeoutMs` long enough for the run.
279
346
 
@@ -309,7 +376,7 @@ An explicit `subagent` call value wins over this default. Choose a value at leas
309
376
  { "globalConcurrencyLimit": 20 }
310
377
  ```
311
378
 
312
- Caps simultaneously running children inside one run, including durable legacy multi-child runs and `workflowScript` launches through `runs.run`/`runs.all`. Queued workflow children retain their stable keys and begin when a running sibling releases capacity. The default is `20`.
379
+ Caps simultaneously running children inside one run, including durable legacy multi-child runs and workflow script launches through `runs.run`/`runs.all`. Queued workflow children retain their stable keys and begin when a running sibling releases capacity. The default is `20`.
313
380
 
314
381
  Inline or file-backed top-level workflow calls may set a positive safe-integer `globalConcurrencyLimit` to override this value for that workflow. The override is workflow-only and is not forwarded to child calls.
315
382
 
@@ -363,7 +430,7 @@ This limit bounds current top-level async load. It is separate from cumulative `
363
430
  { "scheduledRuns": { "enabled": false, "maxPending": 20 } }
364
431
  ```
365
432
 
366
- Durable schedules are enabled by default and stored per project under `.pi/subagents/schedules/<id>/`. See [missions.md](missions.md#schedules) for usage.
433
+ Durable schedules are enabled by default and stored per project under `.pi/subagents/schedules/<id>/`. See [missions.md](missions.md#schedules) for usage. Setting `enabled` to `false` also removes the schedule parameters (`name`, `at`, `every`, `sessionOnly`, `quiet`, `on`, `timezone`, `overlap`, `catchUp`) from the `subagent` tool and rejects `schedule.*` actions from every entry point. Saved schedules are kept and become manageable again when you re-enable schedules.
367
434
 
368
435
  Set `storeRoot` to keep durable schedules outside project repositories. It must be an absolute path or a `~/` path, which expands from the user home directory. Each project is stored under a hash of its resolved working directory, so projects do not share schedules.
369
436
 
@@ -426,7 +493,7 @@ Foreground children remain sessions inside the parent. Npm background children r
426
493
  export PI_PACKAGE_DIR=/path/to/pi-coding-agent-package
427
494
  ```
428
495
 
429
- Pi's own package/assets root is also authoritative when pi-subagents verifies the running host for dynamic tool activation. Host discovery prefers a package root owned by the real `process.argv[1]`, then a nonblank `PI_PACKAGE_DIR`, then `PI_SUBAGENTS_PI_CODING_AGENT_PACKAGE_ROOT`. For a proven Bun-compiled Pi process with a virtual argv entry, it can finally validate package assets adjacent to the canonical executable or in the installed `<prefix>/share/pi-coding-agent` layout. Every selected root must contain a `package.json` whose name is exactly `@earendil-works/pi-coding-agent`; an invalid explicit root fails closed rather than selecting another installation. Empty or whitespace-only values are ignored.
496
+ Pi's own package/assets root. Npm background children receive the detected npm host root as `PI_PACKAGE_DIR`, which overrides an inherited bundled layout; Bun-compiled hosts pass the parent's value through so children keep their release assets.
430
497
 
431
498
  ## `PI_SUBAGENTS_PI_CODING_AGENT_PACKAGE_ROOT`
432
499
 
@@ -434,7 +501,7 @@ Pi's own package/assets root is also authoritative when pi-subagents verifies th
434
501
  export PI_SUBAGENTS_PI_CODING_AGENT_PACKAGE_ROOT=/path/to/pi-coding-agent-package
435
502
  ```
436
503
 
437
- Overrides host-package discovery for spawned children. Foreground CLI resolution uses this root to locate the `pi` CLI script, and the detached background runner uses it for jiti host resolution and peer-package aliases, so both child kinds agree on one host. For running-host activation verification it follows argv ownership and Pi's own `PI_PACKAGE_DIR`, and precedes inferred Bun image layouts. The value must be the root of a canonical `@earendil-works/pi-coding-agent` installation (the directory containing its `package.json`, with that package name); both child kinds still validate the package name and its peer packages from that install tree, so a package whose manifest carries a different name is rejected even with the override set. Empty or whitespace-only values are ignored.
504
+ Overrides host-package discovery for spawned children. Foreground CLI resolution uses this root to locate the `pi` CLI script, and the detached background runner uses it for jiti host resolution and peer-package aliases, so both child kinds agree on one host. The value must be the root of a canonical `@earendil-works/pi-coding-agent` installation (the directory containing its `package.json`, with that package name); both child kinds still validate the package name and its peer packages from that install tree, so a package whose manifest carries a different name is rejected even with the override set. Empty or whitespace-only values are ignored.
438
505
 
439
506
  The default in-process child session loader consults the same discovery. Before falling back to a bare `@earendil-works/pi-coding-agent` import, it resolves the host package root (the running pi process's location, then this override, then pi-subagents' own install tree as a last fallback) and imports the host's entry file directly, so children share the host's single SDK instance instead of a second copy. Roots whose `package.json` name is not `@earendil-works/pi-coding-agent` are rejected. When this override is selected, an unimportable root is reported instead of falling back to a bare import from a different tree.
440
507
 
@@ -19,7 +19,7 @@ registerWorkflowResource({
19
19
  }): { dispose(): void }
20
20
  ```
21
21
 
22
- Names are case-sensitive, at most 128 characters, and match `[A-Za-z0-9][A-Za-z0-9._-]*`; use an extension prefix. Versions are positive safe integers. Registration throws for invalid input, protected builtins (`review`, `run-ci`), or duplicate names within the same session. Different sessions may register the same name. Dispose before replacement; there is no silent overwrite.
22
+ Names are case-sensitive, at most 128 characters, and match `[A-Za-z0-9][A-Za-z0-9._-]*`; use an extension prefix. Versions are positive safe integers. Registration throws for invalid input, protected builtins (`review`, `run-ci`, and `chain` and `tasks`, which back the tool's structured inputs), or duplicate names within the same session. Different sessions may register the same name. Dispose before replacement; there is no silent overwrite.
23
23
 
24
24
  Register in `session_start` using **`ctx.sessionManager.getSessionId()`**, not the session file path or a tool argument. Dispose in `session_shutdown`. New/resumed/forked sessions and reloads need registration from the replacement runtime's `session_start`; do not retain old `pi`/`ctx` references. The extension owns cleanup, not an automatic registration lifecycle manager. Disposal is idempotent and cannot remove a newer replacement. Missing cleanup can cause a duplicate-registration failure on reload.
25
25
 
@@ -108,7 +108,7 @@ pi.events.emit("subagents:rpc:v1:request", {
108
108
  requestId,
109
109
  method: "spawn",
110
110
  params: {
111
- workflowScript: `return runs.run("main", { agent: "reviewer", task: "Review the current diff" })`,
111
+ script: `return runs.run("main", { agent: "reviewer", task: "Review the current diff" })`,
112
112
  context: "fresh"
113
113
  }
114
114
  });
@@ -119,7 +119,7 @@ The RPC methods are `ping`, `status`, `manage`, `spawn`, `steer`, `interrupt`, `
119
119
  Method notes:
120
120
 
121
121
  - `manage` exposes a narrow schedule-only allowlist: `schedule.list`, `schedule.show`, `schedule.history`, `schedule.pause`, `schedule.resume`, `schedule.run`, and `schedule.delete`. All actions except `schedule.list` require `id`. Mission, agent, config, worktree, and arbitrary management actions are rejected before executor dispatch. `ping.capabilities.managementActions` advertises the exact allowlist.
122
- - `spawn` accepts structured single-child execution (`agent`, `task?`), inline `workflowScript`, or `workflowScriptPath` and is async-only: omit `async` or set `async: true`, omit `clarify`, and do not pass management `action` values. Relative script paths resolve against the request `cwd`. It goes through the same executor as the `subagent` tool, so agent discovery, validation, session attribution, configured spawn caps, child-safety depth, artifacts, and async status all behave the same.
122
+ - `spawn` accepts structured single-child execution (`agent`, `task?`), inline script text as `script`, or `workflow` with a script path (containing `/`, such as `"./ci/sweep.js"`) or a named workflow resource. `workflow: true` is rejected because RPC requests have no assistant reply to read a block from; the removed `workflowScript` and `workflowScriptPath` fields are rejected with errors naming `script` and `workflow`. Spawn is async-only: omit `async` or set `async: true`, omit `clarify`, and do not pass management `action` values. Relative script paths resolve against the request `cwd`. It goes through the same executor as the `subagent` tool, so agent discovery, validation, session attribution, configured spawn caps, child-safety depth, artifacts, and async status all behave the same.
123
123
  - `steer` requires an async run `id` (plus optional child `index`) and a non-empty `message`; its reply preserves the normal acknowledged-delivery result. Optional `mode` values are `steer` (default), `follow_up`, and `auto`, and receipts include `deliveryStatus: "delivered" | "queued"`. RPC steering disables the direct tool's pause-and-revive recovery in every mode so an extension keeps authority over the exact child it spawned; `ping.capabilities.nonRecoveringSteer` advertises this guarantee.
124
124
  - `resume` requires a run target and non-empty `message`. It delegates to the existing revival path, which validates current-session ownership, persisted session/recovery metadata, stopped/live state, capability ceilings, and the exclusive session lease before returning the new async run details. Callers may request a `file-only` output path for the revived result without overriding its model, tools, or budgets. `ping.capabilities.resume` advertises this seam.
125
125
  - `cost` returns the same parent-plus-child accounting `/subagent-cost` renders, as data: `{ version: 1, parent, children, childTotal, total, unresolvedAsyncChildren }`, where each usage is `{ input, output, cacheRead, cacheWrite, cost, turns }` and each child carries `label`, `agent`, `runId`, `usage`, and `sessionFile` when known. It is read-only and walks the current session branch plus existing run artifacts, so request it on your own turn boundaries (for example after `agent_settled` or an async completion wake), not on a timer. `unresolvedAsyncChildren` counts async children whose metadata could not be read; treat `childTotal` as a lower bound when it is non-zero, exactly as documented for `/subagent-cost` in [observability.md](observability.md). `ping.capabilities.cost` advertises `{ version: 1 }`.
@@ -251,7 +251,7 @@ const result = await resolveSubagentLaunchContract({
251
251
  if (!result.ok) {
252
252
  // missing_agent, ambiguous_agent, missing_skill, denied_required_tool,
253
253
  // invalid_artifact_dir, invalid_cwd, unsupported_mode, restricted_agent,
254
- // thinking_ceiling, invalid_extension_bindings, or invalid_intercom_bridge
254
+ // thinking_ceiling, model_scope, invalid_extension_bindings, or invalid_intercom_bridge
255
255
  throw new Error(result.message);
256
256
  }
257
257
 
@@ -262,7 +262,8 @@ Preflight covers ordinary single-agent launch resolution:
262
262
 
263
263
  - Selected agent identity and shadowed candidates.
264
264
  - A parsed-definition digest, including system prompt and launch-affecting model, tool, skill, extension, output, and memory fields. Runtime overlays such as the Intercom bridge never change it.
265
- - Fresh/fork context, effective model and thinking, skill and tool resolution, direct MCP selections, runtime/configured extensions.
265
+ - Fresh/fork context, effective model and thinking, skill and tool resolution, direct MCP selections, runtime/configured extensions. Pass your extension's `pi` as `runtimeSnapshotHost` so `mcp:` selections resolve against Pi's built-in MCP the way a launch does. Without it, preflight cannot see built-in MCP and resolves `mcp:` selections through pi-mcp-adapter's configuration, as before.
266
+ - Model scope allow lists accept the reserved tokens `inherit` and `scoped`; `scoped` expands to the caller-supplied `scopedModelIds` snapshot, degrading to `inherit` when it is omitted. Callers whose `modelScope.allow` uses `scoped` must pass `scopedModelIds` (the session's `/scoped-models` snapshot) alongside `parentModel`, otherwise preflight resolves it as `inherit` and may reject models the actual launch allows.
266
267
  - The resolved Intercom bridge state (`intercomBridge.mode` and `intercomBridge.active`). An active bridge appends the bridge instruction to the child prompt and adds `contact_supervisor` to a declared tool list, exactly as execution does.
267
268
  - Artifact/session paths, async lifecycle/status/result/event/process-terminal paths, package/lifecycle versions, capability-ceiling audit data, and stable digests.
268
269