- TypeScript 100%
| extensions/subagent | ||
| src | ||
| .gitignore | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
| spec.md | ||
su-subagent — Declarative Subagent System for Pi
A subagent system for the pi coding agent. Adds a single
subagent tool that delegates a bounded task to an isolated, sandboxed child
session with strict tool, filesystem, and resource-budget guardrails.
Implements spec.md.
Installation
pi install /path/to/su-subagent
Usage
The main agent gets one tool:
{
"prompt": "Find where auth tokens are parsed and summarize the flow.",
"workdir": "/optional/path",
"preset": "read_only | general"
}
prompt— required, self-contained task.workdir— optional, defaults to the main agent's cwd. Hard boundary.preset— optional, defaults togeneral.
Returns a structured result:
{
"status": "ok | blocked | error",
"summary": "...",
"evidence": [{ "path": "...", "note": "..." }],
"warnings": [],
"blocked": { "reason": "", "details": "" }
}
Presets
| Preset | Tools | Write | Exec | Net | Nested |
|---|---|---|---|---|---|
read_only |
read, ls, find, grep | ✗ | ✗ | ✗ | ✗ |
general |
read, ls, find, grep, bash, write, edit | ✓ | ✓ | ✗ | ✗ |
Each preset ships with a fixed resource budget (maxToolCalls, maxTurns,
timeoutSeconds, maxCommandExecutions). The main agent does not configure
these — the preset decides.
TUI
While a subagent runs, a live status widget is rendered below the editor showing the preset, workdir, an animated spinner, and tool/turn/command counters against the preset budget. One widget per concurrent subagent call.
renderCall shows subagent · preset · workdir · <prompt preview> and
renderResult renders the structured result with a status badge, summary,
evidence list, blocked details, and budget stats.
Guardrails
Enforced at the runtime layer (not the prompt), adapted from aliou/pi-guardrails (checking logic only, no UI/config/TUI):
- workdir path boundary on every file-touching tool, with symlink-aware recheck — absolute, relative-traversal, and symlink escapes are blocked.
- preset capability gating — writes, exec, and network are denied even if a tool slips through the allowlist.
- dangerous-command detection on
bash(rm -rf, sudo, dd of=, mkfs, chmod -R 777, chown -R, docker --privileged, …) plus network commands for no-network presets. - tool allowlist is enforced both via
--toolsat the process level and via the in-subagenttool_callhook. - Blocked actions return a verbose structured response (reason, message, allowed scope).
Model
Subagents always run on deepseek-v4-flash (provider opencode-go), regardless
of the caller's provider/model config.
Layout
extensions/subagent/index.ts # the `subagent` tool + TUI rendering
src/types.ts # data model (preset, request, result, budget)
src/presets.ts # built-in presets
src/prompt.ts # system-prompt template
src/runner.ts # subprocess runner + resource-budget enforcement
src/guardrails/index.ts # in-subagent tool_call guardrail extension
src/guardrails/paths.ts # path boundary checks
src/guardrails/bash-paths.ts # path extraction from bash args
src/guardrails/commands.ts # dangerous-command matchers
src/guardrails/shell.ts # minimal shell tokenizer
License
MIT