pi-subagents 0.74.0 makes workflow scripts much easier to write: the model now writes a normal js workflow code block in its reply instead of cramming the whole script into an escaped JSON string. Models that can't add a tool mid-conversation now get subagent from the start, so turning it on no longer costs a full uncached reprocess of the conversation. You can also slim the subagent tool down to the parts you actually use, and background workflows now survive /reload and session resumes. Subagent children also respect an untrusted project the same way the main session does.
Highlights
- Workflow scripts as code blocks. Write the script in a
```js workflowblock and callsubagent({ workflow: true }). No more JSON escaping. - No cache miss when turning on subagents. On models that can't add tools mid-conversation,
subagentis available from the first turn. The newtoolActivationsetting lets you choose. - A smaller tool when you want one.
disabledFeatureshides feature groups you don't use. Withworkflow-scriptsdisabled, simplechainandtaskslists replace scripts. - Background workflows survive
/reload. Running children keep going, and relaunching the same script reuses the children that already finished. - Children follow project trust. In an untrusted project, subagent children no longer load that project's settings, prompts, skills, or extensions.
Need to know
| Who | What to do |
|---|---|
Anyone calling subagent with workflowScript or workflowScriptPath
| These parameters were removed. Use workflow: true with a ```js workflow block in the same reply, or workflow: "./path/to/script.js" for a file. Old calls fail with an error that shows the new forms.
|
RPC spawn callers
| Pass inline script text as script, and a path or workflow name as workflow.
|
| Extensions that register workflow resources | The names chain and tasks are now reserved.
|
Saved schedules and existing run records keep working without changes.
Full changelog
Highlights
- Workflow scripts are now written as a normal
```js workflowcode block in the reply and run withworkflow: true, with no JSON escaping. This replacesworkflowScriptandworkflowScriptPath. - On models that cannot add a tool mid-conversation,
subagentis now available from the start, so turning it on no longer reprocesses the whole conversation at full price. - The new
disabledFeaturessetting hides parts of thesubagenttool you do not use, and withworkflow-scriptsturned off you can run children with simplechainandtaskslists. /reloadand session resumes no longer kill running background workflows, and relaunching one reuses the children that already finished.- Subagent children now respect an untrusted project the same way the main session does.
Added
disabledFeaturesinconfig.jsonremoves feature groups you do not use from thesubagenttool, such as agent management, watchdog, panes, missions, lane management, and per-call options liketoolBudgetormachine. 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: falsenow removes the schedule parameters the same way, and a malformedscheduledRunsvalue 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. Thanks to @tmustier for #2542.disabledFeaturesalso acceptsworkflow-scripts. It removes theworkflow,args,preflight,globalConcurrencyLimit, andmaxSubagentSpawnsPerRunparameters and thevalidateaction, and the tool description no longer explains how to write scripts. In their place, the tool takestasks: [{ agent, task }]to run children in parallel andchain: [{ agent, task?, as? } | { parallel: [{ agent, task }] }]to run steps in order. Chain tasks can use{task}(the top-leveltask),{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;/runstill 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 namedchainortasks. See configuration.- On Pi 0.99 and later without pi-mcp-adapter,
mcp:serverandmcp:server/toolentries in an agent'stoolsnow select tools from Pi's built-in MCP, and the child gets exactly those tools. Servers frommcp.jsonwork in foreground and background children; servers that extensions add withpi.registerMcpServer()work in background children. With pi-mcp-adapter installed, nothing changes. Thanks to @fmoda3 for #2555. subagents.modelScopeallow lists accept ascopedtoken, 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,scopedmeans the same asinherit. Error messages list at most 8 patterns before summarizing the rest. Thanks to @coreyryanhanson for #2538.subagents.agentOverrides.<name>.advertiselists 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 for #2534.- Native Pi subagents can use Pi's built-in
codemodetool 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 for #2574. - 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.
Changed
- Breaking: Workflow scripts had to be passed to the
subagenttool as a JSON string, so every quote and newline was escaped. The tool now takes oneworkflowfield with three forms:workflow: trueruns the single```js workflowcode block written in the same reply; a string containing/(such as"./ci/sweep.js") loads a script file relative tocwd; any other string runs a named workflow. TheworkflowScriptandworkflowScriptPathparameters were removed, and calls that still pass them fail with an error that shows the new forms. RPCspawntakes inline script text asscriptand a path or workflow name asworkflow. Saved schedules and run records keep working. - On models that cannot take a new tool mid-conversation, calling
subagents_enablemade the provider reprocess the whole conversation at the uncached price. New sessions on those models now start withsubagentalready available. Models that can add tools mid-conversation still start withsubagents_enable. Resumed sessions keep the tools they had, and switching models mid-session does not change them. The newtoolActivationsetting inconfig.jsonchooses"auto"(the default),"dynamic"(always start withsubagents_enable, the old behavior), or"eager"(always start withsubagent, like--exclude-tools subagents_enable). See configuration. Thanks to @tinoy1336 for #2589. - After
subagents_enable, the model was sometimes told to wait for the next prompt even whensubagentwas already usable. It is now told to check its tool list: usesubagentif it is there, otherwise wait for the next prompt instead of retrying. - CI now runs the tool-activation smoke test as a required check. Thanks to @quifox for #2528.
Fixed
- 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.
/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 asworkflow.stopCause: "runtime-replaced". Fixes #2546.- 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.
- Reviving a failed background workflow child with
subagent({ action: "resume", id })did not show up in the workflow: its status, receipt and keyedlatest: trueresume still pointed at the failed run. Workflowstatusnow showsRevived → <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 for reporting #2579. - 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 and #2567.
- After pi-subagents was updated on disk while Pi was running, for example by
git pullin a local checkout or a package update, the firstsubagentcall 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/reloador restart Pi to use the new version. - With Pi 0.99's
codemodeturned on, codemode scripts could callsubagent,subagents_enable,subagent_supervisor,contact_supervisorandstructured_output, none of which work from a script: asubagentrun there had no progress card and was cancelled unless awaited,contact_supervisorblocked the script, andstructured_outputhad no effect. Codemode also added the wholesubagentschema 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. - With the
subagenttool 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 for reporting #2581. - With pi-mcp-adapter 3.x on Pi 0.99 or later,
mcp:entries in an agent'stoolslooked 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. - After upgrading pi-mcp-adapter to 3.1.0,
mcp:tool selections for stdio servers stopped resolving, because the adapter started includinginheritEnvandliteralEnvin its config hash. pi-subagents now computes the same hash. Thanks to @qsgy-edge for #2539. - 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 for reporting #2578.
- 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 runningand the Fleet view said5 active agents. The widget now counts each running workflow lane and each agent of a parallel run, like the Fleet view. Thanks to @l3gz for reporting #2578. - 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 for #2556.
- 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
subagentalways loaded. Thanks to @q107580018 for #2526. - 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.
inheritSkills: falsenow also removes skills that extensions add to a child session (for example throughsubagents.defaultExtensions), so they no longer appear next to the agent's own skills. Thanks to @zeezooz for #2540.- A child that was aborted by compaction now recovers when Pi reports the compaction late. Thanks to @jiuai233 for #2537.
- 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. Thanks to @LCorleone for #2536.
- 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 for reporting #2559.
- 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 for reporting #2558.
- 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 for reporting #2560.
- Worktree diffs now work with older Git versions that lack the
--default-prefixoption. Thanks to @quifox for #2527. - Updated
undicifrom 8.10.0 to 8.10.2, outside the range of GHSA-3wwx-pv8p-q78v, so projects that install pi-subagents no longer failnpm auditbecause of it. pi-subagents does not use the affected WebSocket client. Thanks to @advaitpaliwal for #2548. - A package-discovery test no longer fails when the system temp directory is inside a Pi project. Thanks to @abdwhb-png for #2553.