@nijaru/pi-subagents
v0.0.2
Published
Task-first child delegation for Pi: foreground runs, background completion notices, and bounded subprocess lifecycle.
Maintainers
Readme
pi-subagents
Delegate a self-contained task to a fresh Pi child, either foreground or background. The parent supplies the task—not a named role or workflow.
Install
pi install npm:@nijaru/pi-subagentsRestart Pi or use /reload. The package registers one tool, subagent.
Usage
Ask Pi to delegate a specific task, or use these tool-call shapes:
{"command":"run","prompt":"Review the parser changes. Report concrete regressions with file/line and evidence. Do not edit files.","tools":["read"]}run joins the child within a foreground budget (60 seconds by default) and returns its final result. If the budget expires first, the child keeps working in the background and reports completion like spawn. For independent work while the parent continues:
{"command":"spawn","prompt":"Implement the parser regression test in tests/parser.test.ts. Own only that file, run its tests, and report changes and results.","cwd":"../parser-worktree"}
{"command":"status"}
{"command":"wait","id":"<child-id>","timeoutMs":30000}
{"command":"stop","id":"<child-id>"}Background children send a completion notice and request a follow-up parent turn. wait returns the retained final result, or reports that the child is still running when its wait budget expires. Cancelling a wait does not cancel the child; stop cancels it and waits for cleanup. Cancelling run cancels its child.
A blocking run or wait claims the result it delivers: the completion notice is suppressed while a join is in flight and re-armed only if that join expires or is cancelled while the child is still running. The notice carries the final result inline and points at wait only when its excerpt was truncated. A notice queued before the join started can still arrive afterwards.
Handles belong to the current parent session. All children stop on quit, reload, or session replacement. Background work requires a live parent process; a one-shot print invocation is not a persistent worker host.
The TUI shows each prompt once, short IDs, and up to five visible output lines. Expand tool output for full IDs, working directory, tools, and usage. Short IDs are display-only; tool calls still require the full ID. Completion notices occupy one line, with results available on expansion.
Tools and context
- Defaults are the parent's active tools among
read,bash,edit,write,grep,find,ls,web_search,web_fetch,web_research,resolve-library-id, andquery-docs. Research tools require their extensions; they are not supplied by this package. toolsselects an explicit allowlist, restricted to tools active in the parent.tools: []is reasoning-only. An empty default selection is rejected rather than silently launching an unusable coding child.- Children are leaves. The
subagenttool cannot be passed to them, and nested calls are rejected. modeloptionally selectsprovider/model-id; otherwise the parent's model is inherited. Thinking effort inherits the parent's session level.cwddefaults to the parent cwd; relative paths resolve against it.- Every child starts a new conversation. The prompt should include scope, relevant evidence, constraints, expected output, and verification. Parent conversation history is not copied.
The subprocess loads its own Pi configuration, extensions, skills, and applicable AGENTS.md files. Fresh context does not mean an empty system prompt. Runtime-only tools, providers, credentials, and permission-hook state are not cloned from the parent; required integrations must also be configured in child Pi. A tool active only in the parent may therefore be unavailable in the child.
tools filters tool names, not extension code: child Pi still loads its configured extensions, so unrelated extension behavior (commands, hooks, providers) keeps running even when its tools are excluded. Use tools: [] to give the model no tools; that is not a sandbox.
When to delegate
Use spawn for independent work alongside useful, non-overlapping parent work. Use run when a fresh perspective or context-heavy investigation is worth waiting for. Keep routine lookups and tightly coupled edits local. The parent owns integration and verification; do not repeat the child's assignment while it runs.
Children are separate processes that share your working tree. The extension counts concurrency slots; it does not arbitrate write ownership, and it cannot guard the parent's own edits. Give concurrent writers distinct worktrees rather than relying on children to stay out of each other's way. Read-only children may overlap, but reading files while another process changes them does not provide a consistent snapshot.
Limits and safety
| Resource | Limit |
|---|---|
| Active children | 4 per parent session; excess starts are rejected |
| Retained handles | 32; oldest completed handles are evicted first |
| Foreground run | 60 seconds by default; PI_SUBAGENT_FOREGROUND_MS changes it, and expiry hands the child to background work |
| Child execution | 30 minutes by default; PI_SUBAGENT_TIMEOUT_MS may set up to 2 hours |
| One wait call | 30 seconds by default, at most 120 seconds; never extends the child deadline |
| Task prompt | 100 KiB |
| Tool response and result details | 50 KiB each |
| Child stderr | 50 KiB, keeping both ends so the final stack trace survives |
| Background completion excerpt | 8 KiB |
All children use the same subprocess runner: pi --mode json -p --no-session. The task prompt travels on the child's stdin, not in command arguments and not through a temporary file. Normal completion and cancellation sweep the child's process group before releasing the concurrency slot. No profiles, workflow scheduler, recursive delegation, session persistence, or managed worktree creation is included.
A successful child must produce terminal assistant output. Failures, cancellation, and timeouts remain distinguishable in retained status. run and completed wait throw tool errors for failed children; status remains available to inspect them. stop reports the resulting state without treating requested cancellation as a tool failure.
Parent death. Children run detached in their own process groups, so they do not die with the parent by default. Each child is watched by a detached supervisor that holds a pipe from the parent: when that pipe closes—graceful shutdown, crash, or SIGKILL—the watcher terminates the child's process group. On Windows there is no equivalent without a native job object, so only graceful shutdown, the leader process, and a best-effort taskkill /T sweep are guaranteed there.
Tool allowlists and subprocesses are not sandboxes. A child with shell access can produce effects outside the managed process group. Parent permission state is not an inherited security boundary.
Environment variables are allowlisted, with standard model credentials, $VAR references from Pi's models.json, and *_API_KEY/*_TOKEN variables forwarded. Other variables require PI_SUBAGENT_PASSTHROUGH_ENV (comma-separated exact names or globs). * explicitly forwards all environment variables. Credentials saved through pi /login remain available through the child's Pi configuration.
Release notes
0.0.x is pre-release: the tool schema is stable, but behavior and the exported ChildResult shape are not promised across patch releases. Read this file, not the version number, for what changed.
- 0.0.2:
runjoins within a foreground budget and then continues as background work;ChildResultcarriesstateinstead ofexitCode/termination; prompts travel on stdin instead of a temporary file; a blocking join claims the result it delivers; a crashed or killed parent now stops its children; stderr keeps both ends. - 0.0.1: task-first child lifecycle.
Migration from the profile/workflow API
This package replaces the profile/workflow API rather than maintaining a second interface:
{agent, task}→{command: "run", prompt: task, tools?: [...]}. Include useful profile instructions in the task prompt.background.action: "start"→command: "spawn";runId→id;result→wait.- Parallel batches → separate
spawncalls. Chains and workflows → parent-issued calls after inspecting prior results; no{previous}substitution. - Agent discovery,
agentScope, role Markdown files, profile schemas, and recursive policies are no longer consumed. Existing user files are left untouched. Validate structured results in the parent when required.
Restart or reload after updating. Old handles do not migrate. Update any personal instructions that still describe named agents or workflow modes; this package does not edit your settings or profiles.
Development
bun install --frozen-lockfile
bun run checkPi loads the TypeScript extension directly; there is no build step. Node 22.19+ is required. Checks use the pinned Pi 0.85.1 packages, including real CLI foreground delegation, background RPC notification, and abrupt-parent-death tests against a local fake model endpoint. No live model calls are needed. The process-tree and death-watchdog tests are POSIX-only and skip on Windows.
The subprocess boundary is kept separate from session ownership so a future native Pi child API can replace it; unreleased pico designs are not a supported backend.
MIT licensed.
