pi-mono/packages/coding-agent/examples/extensions/subagent
Michael Renner aba42ae6b9
fix(coding-agent): make subagent progress and failures reliable (#8250)
The shipped subagent example could say a child was done while it was
still working, lose the useful part of process failures, and return a
normal-looking tool result when the delegated work had actually failed.
Single and chain output could also exceed the normal tool limit.

This also adds a dedicated regression suite covering progress state,
cancellation, process failures, output limits, cwd-based agent
selection, and persisted tool-result error state.

After this change:

- queued, running, completed, failed, and aborted work stay distinct
throughout the run;
- interrupting the parent run preserves partial child results, stops
queued work from starting, and escalates when a child ignores SIGTERM;
- signal exits, spawn failures, provider errors, stderr, and assistant
output remain visible instead of collapsing to `(no output)`;
- failed subagents become failed tool results, so the parent model can
react instead of treating them as successful calls;
- single and chain results stay within the normal 50 KB / 2,000-line
limit;
- project agents are selected and confirmed from each task's actual
working directory rather than the dispatcher's directory.

## Further potential improvements

These are useful follow-ups, but they are separate product and storage
decisions rather than part of the failure-handling fixes in this PR.

<details>
<summary>Potential follow-ups</summary>

### Keep persisted transcripts bounded

Subagent tool results persist the full child message history in
`details`, which can make parent session files large and slow to reload.
A follow-up could compact that history or spill it to disk.

### Define an aggregate parallel-output budget

Parallel mode still gives every task its own 50 KB budget. A follow-up
could keep every task represented while enforcing one overall
tool-result limit.

### Report child usage to the calling session

Per-child token and cost usage is visible in result cards but is not
added to the calling session's totals.

### Isolate malformed agent definitions

One malformed YAML agent can still break discovery for every valid agent
in the same directory.

### Limit subagent recursion

A nesting limit would prevent accidental process and paid-request
multiplication when subagents can invoke the subagent tool again.

* https://github.com/earendil-works/pi/issues/8195

### Add a configurable timeout

Unattended runs would benefit from a generous opt-in timeout for
children that never complete.

</details>

## Related issues

### Spawn failures lose their diagnostics

This directly addresses the reported case where a nonexistent child
working directory produces `(no output)` instead of the actual spawn
error. The regression suite includes that same reproduction.

* https://github.com/earendil-works/pi/issues/8129

### Persisted child history can bloat sessions

This PR intentionally keeps full child history in tool-result details,
so session compaction or spill-to-disk remains follow-up work rather
than something fixed here.

* https://github.com/earendil-works/pi/issues/7452
2026-11-04 11:24:12 +01:00
..
agents Merge hooks and custom-tools into unified extensions system (#454) 2026-01-05 01:43:35 +01:00
prompts Merge hooks and custom-tools into unified extensions system (#454) 2026-01-05 01:43:35 +01:00
agents.ts fix(examples): accept array-form tools in the subagent example (#7598) 2026-08-14 09:59:42 +02:00
index.ts fix(coding-agent): make subagent progress and failures reliable (#8250) 2026-11-04 11:24:12 +01:00
README.md fix(coding-agent): make subagent progress and failures reliable (#8250) 2026-11-04 11:24:12 +01:00

Subagent Example

Delegate tasks to specialized subagents with isolated context windows.

Features

  • Isolated context: Each subagent runs in a separate pi process
  • Streaming output: See tool calls and progress as they happen
  • Parallel streaming: All parallel tasks stream updates simultaneously
  • Markdown rendering: Final output rendered with proper formatting (expanded view)
  • Usage display: Shows turns, tokens, cost, and context usage inside each subagent result
  • Abort support: Ctrl+C propagates to kill subagent processes

Structure

subagent/
├── README.md            # This file
├── index.ts             # The extension (entry point)
├── agents.ts            # Agent discovery logic
├── agents/              # Sample agent definitions
│   ├── scout.md         # Fast recon, returns compressed context
│   ├── planner.md       # Creates implementation plans
│   ├── reviewer.md      # Code review
│   └── worker.md        # General-purpose (full capabilities)
└── prompts/             # Workflow presets (prompt templates)
    ├── implement.md     # scout -> planner -> worker
    ├── scout-and-plan.md    # scout -> planner (no implementation)
    └── implement-and-review.md  # worker -> reviewer -> worker

Installation

From the repository root, symlink the files:

# Symlink the extension (must be in a subdirectory with index.ts)
mkdir -p ~/.pi/agent/extensions/subagent
ln -sf "$(pwd)/packages/coding-agent/examples/extensions/subagent/index.ts" ~/.pi/agent/extensions/subagent/index.ts
ln -sf "$(pwd)/packages/coding-agent/examples/extensions/subagent/agents.ts" ~/.pi/agent/extensions/subagent/agents.ts

# Symlink agents
mkdir -p ~/.pi/agent/agents
for f in packages/coding-agent/examples/extensions/subagent/agents/*.md; do
  ln -sf "$(pwd)/$f" ~/.pi/agent/agents/$(basename "$f")
done

# Symlink workflow prompts
mkdir -p ~/.pi/agent/prompts
for f in packages/coding-agent/examples/extensions/subagent/prompts/*.md; do
  ln -sf "$(pwd)/$f" ~/.pi/agent/prompts/$(basename "$f")
done

Security Model

This tool executes a separate pi subprocess with a delegated system prompt and tool/model configuration.

Project-local agents (.pi/agents/*.md) are repo-controlled prompts that can instruct the model to read files, run bash commands, etc.

Default behavior: Only loads user-level agents from ~/.pi/agent/agents.

To enable project-local agents, pass agentScope: "both" (or "project"). Only do this for repositories you trust.

When running interactively, the tool prompts for confirmation before running project-local agents unless the session trust context reports trusted and the agents come from that session project's .pi/agents directory. Agents loaded from another task cwd still require confirmation. Set confirmProjectAgents: false to disable confirmation.

Usage

Single agent

Use scout to find all authentication code

Parallel execution

Run 2 scouts in parallel: one to find models, one to find providers

Chained workflow

Use a chain: first have scout find the read tool, then have planner suggest improvements

Workflow prompts

/implement add Redis caching to the session store
/scout-and-plan refactor auth to support OAuth
/implement-and-review add input validation to API endpoints

Tool Modes

Mode Parameter Description
Single { agent, task } One agent, one task
Parallel { tasks: [...] } Multiple agents run concurrently (max 8, 4 concurrent)
Chain { chain: [...] } Sequential with {previous} placeholder

Output Display

Collapsed view (default):

  • Status icon (✓/✗/⏳) and agent name
  • Last 5-10 items (tool calls and text)
  • Usage stats: 3 turns ↑input ↓output RcacheRead WcacheWrite $cost ctx:contextTokens model

Expanded view (Ctrl+O):

  • Full task text
  • All tool calls with formatted arguments
  • Final output rendered as Markdown
  • Per-task usage (for chain/parallel)

Parallel mode streaming:

  • Shows all tasks with live status (⏳ running, ✓ done, ✗ failed)
  • Updates as each task makes progress
  • Distinguishes pending, running, completed, failed, and aborted tasks
  • Returns each completed task summary to the parent model with its own 50 KB limit
  • Returns failure diagnostics from stderr/error messages when a child exits before producing output

Tool call formatting (mimics built-in tools):

  • $ command for bash
  • read ~/path:1-10 for read
  • grep /pattern/ in ~/path for grep
  • etc.

Agent Definitions

Agents are markdown files with YAML frontmatter:

---
name: my-agent
description: What this agent does
tools: read, grep, find, ls
model: claude-haiku-4-5
---

System prompt for the agent goes here.

When model is omitted, the subagent inherits the dispatching session's active model and thinking level.

Locations:

  • ~/.pi/agent/agents/*.md - User-level (with agentScope: "user" or "both")
  • .pi/agents/*.md - Project-level (only with agentScope: "project" or "both")

Project agents override user agents with the same name when agentScope: "both".

Sample Agents

Agent Purpose Model Tools
scout Fast codebase recon Haiku read, grep, find, ls, bash
planner Implementation plans Sonnet read, grep, find, ls
reviewer Code review Sonnet read, grep, find, ls, bash
worker General-purpose Sonnet (all default)

Workflow Prompts

Prompt Flow
/implement <query> scout → planner → worker
/scout-and-plan <query> scout → planner
/implement-and-review <query> worker → reviewer → worker

Error Handling

  • Exit code != 0 or signal termination: Tool returns an error with preserved stderr/output
  • Spawn errors: Tool returns the spawn diagnostic
  • stopReason "error": LLM error is propagated with its error message
  • Abort: Ctrl+C sends SIGTERM, escalates to SIGKILL after five seconds if needed, and preserves partial details/usage
  • Chain mode: Stops at the first failing step and reports which step failed

Limitations

  • Output truncated to last 10 items in collapsed view (expand to see all)
  • Single and chain output is capped at 50 KB/2,000 lines; full results remain in tool details
  • Parallel output keeps a separate 50 KB budget per task, allowing up to roughly 400 KB across eight tasks
  • Child usage is displayed in tool details but is not added to the calling session's usage totals
  • Agents are snapshotted from each task's effective cwd when the tool invocation starts; relative task cwd values resolve from the session cwd
  • Parallel mode limited to 8 tasks, 4 concurrent