pi-subagents 0.75.0 makes background subagents work on Pi 1.0.0 again. If async children stopped starting after you upgraded Pi, this release fixes that without any change on your side. Claude Code children can now use a specific Claude model and effort level per launch, and npm-installed external CLIs launch on Windows. Children on model routers and other virtual models now start and pass model verification, and a mistake in your config no longer silently turns off your permission or tool limits.
Highlights
- Background subagents on Pi 1.0.0. Async children start again instead of failing with "does not provide @earendil-works/pi-agent-core/node".
- Pick the Claude model per launch.
claude-codeandclaude-code-writeraccept a model and effort, for examplemodel: "claude-opus-5.5:high", within yourmaxThinkingandmodelScopelimits. - npm CLIs on Windows.
claude-code,codex-exec, andcursor-agentlaunch CLIs that npm installed as.cmdfiles, still without a shell. - Virtual models work for children. Children on a model router or another extension-registered virtual model launch and pass verification.
- Safer config loading. An invalid config value no longer drops
authorityPolicy,permissions, ortoolBudget. Loading fails instead, so nothing runs with weaker limits than you set.
Changelog
Highlights
- 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".
- The built-in
claude-codeandclaude-code-writeragents can pick a Claude model and effort level per launch, for examplemodel: "claude-opus-5.5:high". - On Windows,
claude-code,codex-exec, andcursor-agentcan now launch CLIs installed with npm. - Children on a virtual model from an extension, such as a model router set as
subagents.defaultModel, now launch and pass model verification. - An invalid config value no longer silently turns off
authorityPolicy,permissions, ortoolBudget. Loading the config fails instead.
Added
- The built-in
claude-codeandclaude-code-writeragents accept a model and thinking level per launch or in agent frontmatter, and pass them to Claude Code as--modeland--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.maxThinkingand an enforcedsubagents.modelScopeapply 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. Thanks to @lexxbyte for #2602. - The parent can now manage a long
bashcommand inside a native Pi child that is granted bothbashandsubagent_command:command.statusshows it,command.yieldlets the child continue while the command keeps running, andcommand.cancelstops only that command. The child can do the same itself withbash'syieldTimeMsand thesubagent_commandtool. 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 for #2598. - Hosts that require child extensions with
registerRequiredChildExtensionscan passrequireForAllRunners: 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. Thanks to @doc-krieger for #2639. schedule.createaccepts an existingmissionId, 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 for #2616.asyncWidgetCollapsed: truestarts the async widget under the editor folded to one line. Clicking its header still unfolds it, and the default is unchanged. Thanks to @unrelentingfox for #2621.
Changed
- CI now runs the clean-install test against both Pi
0.86.1and1.0.0, as separate jobs with separate logs. Thanks to @EightDoor for #2648.
Fixed
- 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 for #2634.
- An invalid value for any config key no longer silently drops
authorityPolicy,permissions, ortoolBudget. 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) - A required child extension (
registerRequiredChildExtensions) that throws duringsession_startnow 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 for reporting #2639. - On Windows, external-CLI agents such as
claude-code,codex-exec, andcursor-agentfailed withEINVALwhen the CLI was installed with npm, because npm installs it as a.cmdfile 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.cmdor.batfile. Thanks to @lexxbyte for tracing the cause in #2631. - A child could not launch on a virtual model that an extension registers with
pi.registerVirtualModel(), such as a router set assubagents.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 for #2636 (#2635). - A child on a virtual model failed with
model_verification_failedeven 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 for reporting #2637 (#2635). - A background chain whose
expandstep runs an external-CLI agent such asclaude-codefailed 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 for reporting #2629. - 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 for #2627.
- Codex children now keep tool-call IDs in the
call_id|item_idform when both parts are at most 64 characters and use only letters, digits,_, or-. Other IDs are shortened as before. Thanks to @jtabke for #2628 (#2623). - With Pi's built-in MCP,
mcp:entries whose server or tool name contains-, such asmcp: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 for #2607. - Some MCP clients, such as pi-claude-bridge, send
workflow: trueas the string"true", which failed with an error asking forworkflow: true. The string now works the same as the boolean (#2600). action: "validate"now checks workflowargsagainst 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 itsargs. (#2608)- 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 for #2598.
- 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 asinterrupted, with a later resume recording again. Thanks to @limin411 for #2620. /subagent-costand the RPCcostmethod 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 for #2601./subagent-costand the RPCcostmethod 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 asAsync child usage unavailableinstead of being left out of the total without notice. (#2614)- 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 for #2618.
- Headless sessions now deliver goal-mission notices even when finishing background work fails. The failure is still reported to the caller. Thanks to @quifox for #2605.
- 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 for #2604.
- 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 for #2606.
- Saved subagent profiles with an invalid
machinevalue are now rejected when loaded or checked, before any settings are written.machine: falsestill clears a pin. Thanks to @quifox for #2619.