@williamcr01/pi-subagents

Recursive, isolated, asynchronous subagents for Pi

Packages

Package details

extension

Install @williamcr01/pi-subagents from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@williamcr01/pi-subagents
Package
@williamcr01/pi-subagents
Version
0.2.5
Published
Sep 8, 2026
Downloads
681/mo · 681/wk
Author
williamcr01
License
MIT
Types
extension
Size
333.9 KB
Dependencies
0 dependencies · 3 peers
Pi manifest JSON
{
  "extensions": [
    "./index.ts"
  ],
  "image": "https://raw.githubusercontent.com/williamcr01/pi-subagents/main/assets/pi-subagents-demo.png"
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-subagents

Recursive, isolated, asynchronous subagents for the Pi coding agent.

pi-subagents adds background delegation to Pi without external npm dependencies. Spawn several focused agents in parallel, let agents recursively delegate their own work, monitor the live tree in Pi's footer, inspect real child transcripts, and collect results when they finish.

pi-subagents running recursive background agents

Features

  • Asynchronous spawningspawn_agent returns immediately while the child runs in its own Pi process and session.
  • Recursive delegation — children can create grandchildren within the configured depth budget.
  • Parallel work — concurrency is configurable, including unlimited mode with maxConcurrency: -1.
  • Live monitoring — the footer shows a recursive status tree with provider/model, activity, and elapsed time.
  • Interactive transcripts — open any child to read its complete Pi session from the original delegation prompt, including messages and tool calls.
  • Steering and follow-ups — message a running child to redirect it, or message a finished child to continue its existing session.
  • Automatic delivery — finished results arrive with the next completed parent tool result. An idle parent receives one batch and resumes. check_subagents can collect pending results explicitly.
  • Cancellation — stop a running or queued child by run ID, session ID, or name.
  • No added dependencies — uses Pi's extension and TUI APIs plus Node.js built-ins.

Install

Install from npm with Pi:

pi install npm:@williamcr01/pi-subagents

This version requires Pi 0.85.0 or newer. Restart Pi or run /reload after installing. To install the latest published version explicitly:

pi update npm:@williamcr01/pi-subagents

For local development, the git install still works:

pi install git:github.com/williamcr01/pi-subagents.git

Usage

Once installed, Pi automatically loads the extension. Ask Pi to delegate work, or use the tools directly:

spawn_agent({
  task: "Inspect the authentication flow and report security risks",
  name: "auth-reviewer",
  cwd: ".",
  tools: ["read", "grep"]
})

Use check_subagents to inspect progress or wait for results:

check_subagents({ wait: true, timeoutMs: 120000 })

Use send_to_subagent to steer a running child or continue a completed one. Use cancel_subagent to stop a child. Both accept a full run ID, a unique run-ID prefix (including the eight characters shown in tool output), a session ID, or an exact name. Exact matches take precedence over prefixes; ambiguous targets are rejected with full run IDs for disambiguation.

Isolation model

Each child has a separate Pi process and session, but it is not an OS sandbox. Children use the same user account, filesystem permissions, environment, and installed extensions as the parent.

A trusted parent passes project approval only when the child's canonical working directory remains inside the parent's canonical directory. A symlink that points outside that tree does not inherit approval, so Pi evaluates trust for the target directory normally.

In TUI mode, press Down at the bottom of the editor to open the live subagent panel. Open a transcript, type a message, and press Enter to steer or continue that subagent. Use /subagents to review finished agents and transcripts.

Tools

spawn_agent

Start an isolated child in the background. It returns immediately, so continue other work while the child runs.

spawn_agent({
  task: "Inspect the authentication flow and report security risks",
  name: "auth-reviewer",
  cwd: ".",
  tools: ["read", "grep"]
})

Optional fields are name, cwd, model, thinking, and an exact tools allowlist. Model selection is resolved as:

  1. Per-spawn model
  2. defaultModel in configuration
  3. The creating agent's active model

When the creating session has a model scope from Pi's --models flag or enabledModels setting, the selected child model must be in that scope. The scope and its pinned thinking levels are passed to the child. A pin is applied as the child's --thinking value; an explicit thinking that disagrees with the pin is rejected. An empty scope keeps Pi's unrestricted model behavior.

Omitting tools copies the creating session's active tool set. An explicit list can only remove tools from that set, and tools: [] starts the child with --no-tools. Include spawn_agent to allow recursive delegation. A child receives it automatically only when spawn_agent is active in the parent and tools is omitted or explicitly includes it.

Thinking level follows the same precedence and is clamped to the selected child model.

check_subagents

Inspect descendants and collect newly finished results without repeating results already delivered. Each ancestor sees a descendant execution once, without claiming the direct parent's result. Use wait: true before relying on work that is still running:

check_subagents({ wait: true, timeoutMs: 120000 })

timeoutMs defaults to 30 seconds and is capped at 300 seconds. The wait returns as soon as every descendant finishes; the timeout is only a maximum.

send_to_subagent

Steer a running child or continue its completed session by exact name, run ID, unique run-ID prefix, or session ID. Messages to deeper descendants are acknowledged by their creating session after RPC acceptance (or retention during queued startup). Cross-process admission waits are cancellable and time out after five minutes; cancellation does not undo a prompt already accepted, and the creator keeps the concurrency slot until that turn settles:

send_to_subagent({ target: "auth-reviewer", message: "Focus on the token refresh path." })

cancel_subagent

Stop a child by exact name, run ID, or session ID:

cancel_subagent({ target: "auth-reviewer" })

Result delivery

While the parent works, finished child reports stay in the registry until a completed parent tool result or check_subagents consumes them. Automatic delivery appends reports to the tool output without steering the parent or skipping sibling tool calls. If the parent becomes idle first, it receives the pending reports in one message that starts a new turn.

This replaces the previous behavior of queueing a separate follow-up prompt for every completion. Reports no longer accumulate behind a long parent run and replay after its final answer. If a child completes several follow-ups before the parent consumes its report, only the latest execution is delivered. Earlier output remains available in the child's transcript.

Configuration

Global settings live at ~/.pi/agent/subagents.json. A trusted project's <configDir>/subagents.json (.pi by default; Pi's CONFIG_DIR_NAME) can override them for that project.

{
  "defaultModel": "anthropic/claude-sonnet-4-5",
  "defaultThinking": "medium",
  "maxDepth": 4,
  "maxConcurrency": -1
}

All fields are optional. Defaults are maxDepth: 2 and maxConcurrency: 4.

  • defaultModel — fallback model for spawns that omit model.
  • defaultThinking — fallback thinking level for spawns that omit thinking.
  • maxDepth — maximum recursive depth. The root is depth 0; maxDepth: 0 disables spawning. Descendants inherit the root limit and may only tighten it.
  • maxConcurrency — number of children allowed to run at once per creating session. Use -1 for unlimited or a positive integer for a limit; extra children queue automatically. Resuming a completed child also waits for its creator's slot, even when an ancestor sends the follow-up. Steering a running child does not require another slot.
  • rpcMaxLineChars — defensive limit per child stdout JSONL record, default 67108864 (64 Mi UTF-16 code units, including an optional trailing CR but excluding LF). Must be a positive safe integer; there is no unlimited mode. Set it in global or trusted-project subagents.json, for example "rpcMaxLineChars": 134217728 for unusually large workloads.

Pi RPC embeds base64 images in tool/message events and aggregates messages in turn_end and agent_end. The 64 Mi default allows several multi-megabyte images and aggregate results that exceed ordinary text-output limits; it is a client safety bound, not a Pi protocol maximum. Both terminated and unterminated records exceeding it fail the child with an explicit error. Input is checked before buffering, scanned incrementally, and discarded on failure. Memory remains proportional to the configured bound (UTF-16 storage, joining, and JSON parsing can require several times the record size per concurrent child); raise it cautiously or reduce concurrency. LF-only framing and split UTF-8 decoding are preserved.

The --subagent-depth N Pi flag overrides configured depth for the tree; descendants inherit that override rather than reapplying file limits. Without a flag override, explicit global or trusted-project depth settings may tighten the inherited limit. Built-in defaults never tighten an inherited limit. An explicit descendant --subagent-depth N may also tighten the limit and overrides file limits for its subtree. No descendant can raise an inherited limit.

Footer controls

When children exist, the footer displays a tree rooted at the current agent:

main · openai-codex/gpt-5.5
├─ ● auth-reviewer · openai-codex/gpt-5.5 · running grep
└─ ● test-runner · openai-codex/gpt-5.5 · running npm test
↓ inspect
  • Press Down at the bottom edge of the editor to inspect subagents.
  • Press Up/Down to select; Enter/Right to open a child transcript; x stops a running child.
  • In a transcript, type a message and press Enter to steer or continue the child.
  • Transcripts open in a focused overlay: Up/Down, PageUp/PageDown, and mouse-wheel scrolling affect only the child transcript, not the main conversation.
  • In a transcript, Esc or Left on an empty input returns.
  • Press Left to go back; Esc is also supported.
  • Finished children remain visible until the next user turn, then leave the footer. Use /subagents to review full history.

Development

The extension is plain TypeScript loaded directly by Pi. The regression suite uses a local fake Pi child and makes no API calls:

node subagents.test.cjs

Source files are organized by responsibility:

  • index.ts — Pi registration, lifecycle hooks, tools, delivery, and UI wiring
  • config.ts — settings validation and precedence
  • registry.ts — atomic run records
  • wait.ts — event-driven wait for descendant completion (check_subagents wait:true)
  • spawn-agent.ts — RPC process control, concurrency, cancellation, and depth enforcement
  • owner-control.ts — cross-process requests/acknowledgements routed through the target's creating session; revoked requests abort pending admission
  • events.ts — child JSON event parsing and status updates
  • panel.ts — footer tree, selection, and transcript detail view
  • transcript.ts — rendering child session files

Publishing

This repository is ready to publish as @williamcr01/pi-subagents:

npm login
node subagents.test.cjs
npm pack --dry-run
npm publish --access public

After publishing, verify the package from a clean Pi installation:

pi install npm:@williamcr01/pi-subagents

For a later release, bump the version (for example with npm version patch), push the commit and tag, then run npm publish again.

License

MIT © William Crona