103 lines
2.5 KiB
Markdown
103 lines
2.5 KiB
Markdown
# pi-subagents
|
|
|
|
Pi extension that registers a `subagent` tool. Subagents are defined by markdown prompts in `prompts/*.md`.
|
|
|
|
## Prompt format
|
|
|
|
```md
|
|
---
|
|
name: scout
|
|
description: Fast codebase reconnaissance
|
|
approved_tools:
|
|
- read
|
|
- bash
|
|
---
|
|
System prompt for the subagent goes here.
|
|
```
|
|
|
|
- `approved_tools` / `allowed_tools` is whitelist mode: the subagent receives only those tools.
|
|
- `denied_tools` is blacklist mode: the subagent inherits currently active tools except `subagent` and internal tools.
|
|
- Do not define whitelist and blacklist fields together; the extension rejects ambiguous configs.
|
|
|
|
## Tool usage
|
|
|
|
```json
|
|
{
|
|
"agent": "scout",
|
|
"task": "Find where authentication middleware is registered"
|
|
}
|
|
```
|
|
|
|
The tool returns the subagent's finalized result as normal text with a compact status/session header for clients that hide structured tool metadata:
|
|
|
|
```md
|
|
**Status:** SUCCESS
|
|
**Session ID:** `550e8400-e29b-41d4-a716-446655440000`
|
|
|
|
---
|
|
|
|
...
|
|
```
|
|
|
|
Metadata also includes the sticky session id:
|
|
|
|
```json
|
|
{
|
|
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
|
|
"finalized": {
|
|
"status": "SUCCESS",
|
|
"result": "..."
|
|
}
|
|
}
|
|
```
|
|
|
|
To continue the same child subagent context, pass the returned `sessionId`:
|
|
|
|
```json
|
|
{
|
|
"agent": "scout",
|
|
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
|
|
"task": "Keep going and inspect the registration path"
|
|
}
|
|
```
|
|
|
|
If `sessionId` is omitted, a new child session is created.
|
|
|
|
## Sticky sessions
|
|
|
|
Subagent sessions persist under:
|
|
|
|
```txt
|
|
~/.pi/subagent-sessions/<cwd-hash>/<agent>_<sessionId>.jsonl
|
|
```
|
|
|
|
Session identity is scoped by working directory, agent name, and session id. Reusing the same `sessionId` with the same agent and cwd resumes that child context.
|
|
|
|
## Finalization
|
|
|
|
Subagents do not return final answers as free-form assistant text. Child runs get an internal `subagent_finalize` tool and must call it as their final action:
|
|
|
|
```ts
|
|
subagent_finalize({
|
|
status: "SUCCESS" | "ERROR",
|
|
result?: string,
|
|
error?: string,
|
|
})
|
|
```
|
|
|
|
Rules:
|
|
|
|
- `SUCCESS` requires a non-empty `result`.
|
|
- `ERROR` requires a non-empty `error`.
|
|
- `ERROR.result` may contain partial findings.
|
|
- If the child exits without valid finalization, the extension continues the same session with corrective feedback, up to a small retry limit.
|
|
- `subagent_finalize` is registered only in child subagent processes, never in the parent context.
|
|
|
|
## How it runs
|
|
|
|
The extension spawns an isolated child pi process in JSON mode with the resolved tools and a persistent session file:
|
|
|
|
```txt
|
|
pi --mode json -p --session <session-file> --tools <resolved-tools> <task>
|
|
```
|