pi-subagents
Delegate separate pieces of work to child agents: one can explore the code while another reviews the tests. The main session assigns the tasks and brings their results together.
Off by default. Until you opt in, the subagent tool stays inactive and its
instructions stay out of the model's prompt. Each child starts with fresh context,
not a copy of your conversation, and cannot spawn more children. Returned text
is capped; full transcripts are saved for later inspection.
Use it
/subagents on opt in — activates the tool and the orchestrator brief
/subagents off opt out (running children keep going; new spawns stop)
/subagents pick a running or queued child, then steer or stop
Use scout and reviewer in parallel: have the scout trace authentication and the reviewer inspect its tests.
A status widget above the editor lists the fleet. It is display-only. While
enabled, the footer status line shows a live subagents: N running · M queued
count. The enabled state lasts for the pi process (survives session switches,
resets on restart).
Tool
subagent({
agent, // scout | reviewer | oracle | worker | researcher | custom type
task, // full prompt — the child cannot see this conversation
description?, // 3–5 words for the widget
max_turns?, // 1–30, may only lower the resolved cap
timeout_ms?, // wall-clock cap in ms (up to 2h), may only lower the resolved cap
})
Unknown or disabled types error. There is no general-purpose fallback.
Built-in types
| Type | Job | Writes |
|---|---|---|
scout |
Fast recon. repo_map → code_search → key files → compressed start-here. | read-only |
reviewer |
Reviews the diff (not the whole file). Findings with path:line, severity, verdict. No edits. |
read-only |
verifier |
Independently reproduces a change. Runs the build, tests, and artifact, and reports observed evidence. | write-capable (bash unrestricted) |
oracle |
Second opinion. Challenge assumptions. Name what is missing. | read-only |
worker |
Implements a fully-specified change: edits files, runs checks, reports a diff summary. | edit/write + full bash |
researcher |
Web/docs research with cited sources and a concise brief. | read-only |
reviewer and oracle default to model: cross-family: the strongest model
listed in ~/.pi/agent/router.json (frontier, then mid, then base) that is
authenticated and from a different family than the parent (families are read
from the model id, so openai/gpt-* and openai-codex/gpt-* count as one). A
reviewer on the author's own family tends to share its blind spots. With
nothing eligible, they inherit the parent and the result carries a note saying so.
When the parent runs router/auto, family is taken from the router's last physical
model (or the configured base before the first route). The rest inherit the parent model. A per-call model parameter (provider/id or
cross-family) overrides the type's default. Read-only types get bash restricted to plan-mode's
fail-closed allowlist. The worker is write-capable with prompt-level guard
rails only (stay in scope, never commit/push/install, stop early on ambiguity).
Builtins are pre-tuned: scout (10 turns, low thinking), reviewer (15/high),
verifier (25/high), oracle (8/high), worker (30/high), researcher (12/high).
Custom types
.md files with YAML frontmatter, highest wins:
<cwd>/.pi/agents/*.md— only if the project is trusted~/.pi/agent/agents/*.md- shipped builtins
---
name: writer
description: Implements a small approved change
tools: read, edit, write, bash
---
You implement the task. Do not spawn other agents.
A declared tools: list is honored for every agent (builtin or custom) and
defines the child's exact toolset. Files that omit tools: get an explicit
read-only allowlist (read, grep, find, ls, bash, the code-search tools,
and the web tools) — never a blocklist, so no future mutating tool can leak in.
Full bash is granted only to write-capable agents: those that declare
edit/write in tools:. Every other agent — builtin or custom, listed or
not — runs bash under the read-only allowlist, so a "read-only" agent cannot
rm -rf its way around missing write tools. enabled: false hides that name
(including a builtin).
Copy-paste examples live in examples/custom-agents/ —
a write-capable writer and a read-only docs-auditor. Drop them into
~/.pi/agent/agents/ (or <cwd>/.pi/agents/) to use them as subagent types.
v1 frontmatter: name, description, tools, model (exact provider/id, or cross-family),
thinking, max_turns (1–30), timeout_ms (ms), enabled.
Limits
- Max 4 running; extras queue.
- 30 turns, wrap-up steer, then 2 grace turns, then abort; plus a 30-minute
wall-clock timeout (frontmatter/
timeout_mscan adjust) so a hung tool call cannot block the parent forever. - Last assistant text, capped at 12 KB (head + tail kept), plus usage stats. Every run's
full transcript is written to
~/.pi/agent/subagent-runs/*.jsonl(newest 200 kept) and its path is on the result. A child that is stopped, times out or aborts returns its recent assistant text and tool trace instead of an empty message. - A "start converging" steer at ~70% of the turn cap (caps of 5+), before the wrap-up steer. Child token usage is
attributed to the session (
usageon the tool result). - Child runtime failures (error / timed out / aborted) return as normal content
— never
isError, so pi does not blindly auto-retry the same failing spawn. - Always fresh context. No resume, no background, no nested orchestrator, no worktrees.
- Children load host extensions except this package and the interactive-only ones
(
lore,prompt-coach,skill-select), and never getsubagent. The router loads on purpose so children that inheritrouter/autostill register the virtual model; pinned or cross-family children keep their physical model. - The orchestrator brief (roster + spawn rules) is appended to the system prompt only while subagents are on — never otherwise.
Notes
/planis unchanged. Subagents do work; plan-mode decides work. While plan mode is active thesubagenttool is not callable (its read-only toolset excludes it).- In-process spawn uses the host SDK (
createAgentSession). That is not a new npm dependency. - Recursion guard:
PI_SUBAGENT_CHILD=1during child bind, plusexcludeTools: ["subagent"].
TypeSafe judgments (optional)
With a TypeSafe key (see pi-typesafe) three batched Jev judgments run; without one they
are skipped silently — every path fails open.
- Preflight (before spawn): rejects a task once when it leans on context the child
cannot see, or (write-capable agents) leaves a design decision open. Resubmitting the
identical task runs it. A missing deliverable or scope is added to the child's task as a
hint instead. Thresholds:
THRESHOLDSinjudge.mjs. - Triage (after a clean run):
triage: answered | partial | blocked | off_task (p). - Scope check (write-capable agents): the real
git diffsince the spawn is appended aschanges:, and a warning is added when the diff likely goes beyond the task.
node scripts/subagent-usage-report.mjs counts spawns, fan-out, triage, tokens and lossy handoffs from local sessions (see docs/workflow-evaluation.md).