@pi-kaush/pi-simple-subagents
Delegate background tasks or persistent interactive workers to isolated Pi processes, with execution profiles, bounded delegation, and process-tree cleanup.
Package details
Install @pi-kaush/pi-simple-subagents from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@pi-kaush/pi-simple-subagents- Package
@pi-kaush/pi-simple-subagents- Version
0.3.1- Published
- Oct 14, 2026
- Downloads
- 410/mo · 133/wk
- Author
- kaushikgopal
- License
- MIT
- Types
- extension
- Size
- 428.4 KB
- Dependencies
- 1 dependency · 4 peers
Pi manifest JSON
{
"extensions": [
"./src/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-simple-subagents
The default mode runs bounded tasks in the background and returns structured output. Interactive workers keep their Pi session between assignments.
Despite the name, this is the full-featured subagent tool — "simple" refers to the bounded default: tasks in, structured results out.
Quick start
pi install npm:@pi-kaush/pi-simple-subagents
The tool needs two things on disk before it is useful: Running the tool with { "action": "init" } writes both starter files when they are missing; it never overwrites existing files.
At least one agent definition. A subagent call names an agent, and an unknown name fails with the list of available agents. Create
~/.pi/agent/agents/bee.md:--- emoji: 🐝 profile: quick --- You are a general worker. Do the delegated task and report the result concisely.Run
/reloadafter adding or renaming agents. See Agents.~/.pi/agent/profiles.yaml. The extension loads it at startup and fails to register without it. A minimal file:version: 1 profiles: quick: description: Fast, low-cost execution for simple tasks. candidates: - model: anthropic/claude-haiku-4-5Use any
provider/modelyou are authenticated for. The schema lives in@pi-kaush/pi-model-profiles.
Examples
Ask the parent model in plain language; it chooses the subagent call.
Background runs (the default) return a result inside the current turn:
Use a quick bee subagent to count the .ts files under src and reply with the number only.In parallel, have two quick bee subagents summarize README.md and CHANGELOG.md in one sentence each.Chain: a bee subagent lists the exported functions in src/index.ts, then a bee subagent writes one line describing {previous}.- Press Esc during a run to stop every child; partial results are kept.
Interactive workers keep their session and report back on their own:
Start an interactive bee worker: read src/index.ts and tell me in 3 bullets what it does.In Herdr it opens in an unfocused pane below. Outside Herdr, it uses the headless RPC fallback and warns that no interactive pane is available. The result arrives without awaitcall.Send that worker a follow-up: list any timers it creates.Same session, new assignment, second report.Steer that worker: focus only on error handling.Folds into the running task.Stop the worker.thenResume it and ask what it remembers.Context is kept; interrupted work is never replayed./subagentopens a picker to inspect, focus, message, or stop workers.
Interactive workers survive /reload, come back idle after pi --continue, and each result
is reported once. Background runs and interactive workers share five slots; when idle
workers hold them all, background runs fail immediately and name workers to stop.
What it adds
subagent, an LLM-callable tool with three task forms:- single — one agent, one task
- parallel — a
tasks[]batch with an optional shared immutablecontext - chain — sequential steps where
{previous}placeholders receive the prior step's output
- Execution profiles (
quick,coder,default,thinker,deep-thinker): ordered model-candidate ladders from the shared machine-local~/.pi/agent/profiles.yaml, shared with@pi-kaush/pi-agent-modeand@pi-kaush/pi-model-profiles. Profiles reload on file change — ladder edits apply to long-running sessions without a restart. - Model-facing discovery: user agents are read from
~/.pi/agent/agents/*.mdwhen the extension loads and listed alongside the execution profiles in the tool guidance. Agent names select behavior and tools; profile names select compute. When both appear in a request, their order does not matter:thinker redteamandredteam thinkerselect the same pair. - Bounded delegation: depth 2, five children per call, five active children per Pi session, at most thirty simultaneously active descendants. Completed bounded children release their slots; idle interactive workers do not.
- Subtree-safe lifecycle: depth-1 children lead POSIX process groups; abort,
timeout, and session shutdown terminate the whole subtree (graceful then
forced). Windows uses
taskkill /T. - Child watchdogs: two hours total runtime and fifteen minutes without
output by default; either configurable in
src/limits.json,0disables. The orchestrator is never watchdogged. - Resumable child sessions: children persist real Pi sessions, named
subagent(<agent>): <task preview>. Expanded tool output shows the full session ID with api --session <id>resume hint and the session file path for livetail -fviewing. Disable withpersistChildSessions: false. - Transcript artifacts: bounded children's complete stdout/stderr streams to a
private JSONL artifact under
~/.pi/agent/subagent-runs/; interactive workers retain Pi session transcripts, bounded status previews, and assignment result archives under~/.pi/agent/managed-subagents/. - Structured yield: delegated children finish through a terminating
yieldtool (completed,blocked,failed), with artifact paths; ordinary final assistant output remains a fallback. - Model resolution: before delegation, refresh Pi's authenticated model catalog
locally; select profile candidates and bare model overrides from that catalog, not
the parent's
enabledModels/scopedModelscycling list. An explicit model overrides an invocation profile, which overrides the agent'sprofilefrontmatter, then its legacymodelfield. Bare ids resolve family-scoped by nearest version; qualified refs pass through to the child for validation.
Interactive mode
The default action: "run" runs background work. It supports single, parallel, and
chain tasks. Use action: "interactive" for persistent workers.
An interactive worker keeps its session for later assignments. In Herdr, it
opens a pane. Interactive mode accepts one agent/task or a tasks[] batch
with optional shared context. It does not support chains.
{ "action": "interactive", "agent": "coder", "task": "Implement the parser", "profile": "coder" }
{ "action": "send", "handle": "mw-…", "message": "Also cover empty input" }
{ "action": "wait", "handle": "mw-…", "assignmentId": "a-…" }
Use list and status to inspect workers, send to steer active work, and
wait to collect a specific assignment. delivery: "followUp" queues a
separate assignment. Interrupted tasks are never replayed automatically; use
the returned assignment ID to avoid collecting an older result.
Finished assignments report themselves. Each terminal result (completed,
blocked, failed, timed out, aborted, interrupted, or cancelled) arrives in the
parent session as one bounded managed-subagent-result message with the
worker's identity, model, result preview, artifacts, usage, and transcript
path. An idle parent starts a turn to present the answer; a busy parent receives it
as a follow-up after the current turn. Steers merged into a running assignment
are reported with it. Reports are recorded in the parent session, so /reload
and restarts neither repeat nor lose them, and results already collected with
wait are not reported again. Receipts follow the active branch: after /tree
navigation, a result reported only on the abandoned branch is reported again.
Each report is sent at most three times. wait remains available for
deterministic collection inside a turn. The interactive-worker status line hides
exited or stopped workers once their results are reported or collected; live
idle workers stay visible.
Interactive worker status is published as the extension status
below-footer:managed-subagents, one worker per line, at most five rows plus a
+N more row. With pi-footer-minimal
installed, each line renders as its own dimmed row below the footer. Without it,
Pi's native footer joins every extension status into one line, so the worker
rows appear inline with other statuses, separated by spaces and clipped to the
terminal width.
Interactive launch confirmations and controls stay in the expanded tool output. IDs are
explicitly labeled worker-handle [mw-…] and assignment-id [a-…]; expand the
completion message to inspect status, task, usage, and transcript details. The
collapsed completion message adds no card or metadata above the parent's answer.
The parent is instructed to present brief answers directly without launch or
completion announcements, task recaps, IDs, or closing commentary. This is model
guidance, not filtering or rewriting its messages.
A worker handle identifies the reusable child session; use it with status,
send, stop, and resume. Each task or follow-up has an assignment ID; pass it
to wait alongside the handle to collect that specific result, not whichever
task finished most recently. Routine use needs neither copied ID: automatic
reports and /subagent provide the normal workflow.
Interactive workers share the session's concurrency gate with background runs. An idle
worker keeps a slot until it exits, is stopped, or is suspended. stop retains
the worker's Pi session and transcripts; resume restarts it. Parent shutdown
suspends interactive workers and releases their slots. They resume idle with their
saved context when that parent session starts again; interrupted instructions
and uncertain message deliveries are never replayed automatically. /reload
leaves interactive workers running. If interactive workers hold every slot,
background runs fail immediately and list workers to stop.
Interactive sessions persist even when persistChildSessions is disabled for background runs.
In Herdr, each interactive worker runs in an unfocused, extension-owned pane split down from
the caller; later workers stack below earlier ones. The /subagent picker can
inspect it or focus it for native TUI use. Outside Herdr, interactive workers run through Pi
RPC and remain headless. Interactive mode warns when no pane is available; the
expanded tool output and picker give a fish-safe command for the saved session
and tell you to stop a running headless worker before opening it elsewhere. That
command opens a standalone session, not a live attachment: close it before
resuming the worker from the parent. Open never resumes an unsupported headless
worker implicitly. /reload refreshes the
default host adapter without moving existing worker tabs or restarting processes;
subsequent launches use the current split layout. Host-specific launch, focus,
and cleanup remain behind the existing host port for future multiplexer adapters.
Future direction: Pi Durable's multiplayer model
could let multiple clients observe and steer the same running worker without
starting a second writer. One process owns storage; clients attach to that
owner. This could solve the headless-to-interactive attachment problem: opening
pi --session today starts another process, not a client of the existing worker.
Durable is an experimental, separate framework, not a drop-in attachment feature
for these Pi CLI workers. Adopting it would require a worker backend and UI adapter;
it does not make independent concurrent storage writers safe.
Herdr workers use the Herdr server's provider environment and the shared Pi agent directory. Parent-only exported credentials are not copied into launch arguments. Blocked trust or permission prompts are never automatically approved.
Profiles and model overrides are resolved when an interactive worker starts and reused for
later assignments. Explicit models override invocation profiles, which override
agent profiles and legacy agent models. The parent's cycling model scope is not
inherited. Isolation flags are opt-in; noMcp is currently supported only for
background runs (requires Pi 1.0.4 or newer), and noExtensions explicitly loads this package's child bridge
and yield tool.
The offline RPC smoke runs in the ordinary test suite. Native Herdr smoke is opt-in because it creates and closes a real unfocused split pane:
env PI_MANAGED_HERDR_SMOKE=1 npx vitest run extensions/pi-simple-subagents/test/subagent-managed-cli.test.ts
Both smoke tests use a deterministic local provider, not network model calls.
Agents
Agent definitions are Markdown files with optional frontmatter (emoji,
profile, model, tools, confirmProjectAgents). Declare either profile
or model, not both. Discovery:
- user:
~/.pi/agent/agents/*.md - project: nearest
.pi/agents/*.md, withagentScope: "project" | "both"
User agents are advertised to the parent model at extension load. Additions or
renames need /reload to refresh that catalog. Project agents remain dynamically
discoverable by exact name without being embedded in the global catalog.
Project-controlled agents prompt for confirmation before first use.
Example agents
Two worked agent definitions live in
examples/agents: a read-only reviewer and a plan-only
architect. Both show the handback contract this extension
delegates well: findings or decisions with severities, the checks
already run, and the checks that remain. Adapt them; they are not
loaded automatically. Their shape is adapted from the bundled agents in
championswimmer/pi-subagent-manager (MIT).
Configuration
src/limits.json bounds delegation (validated against hard ceilings):
{
"maxDepth": 2,
"maxChildrenPerCall": 5,
"maxConcurrency": 5,
"maxRuntimeMs": 7200000,
"maxInactivityMs": 900000,
"persistChildSessions": true
}
The model-profiles schema lives in
@pi-kaush/pi-model-profiles.