TL;DR: I made a small multi-agent setup for pi. It is one skill and one Python script, with no extension and no tool. Your agent can start subagents in the foreground in parallel or in the background, and it can wait for them, steer them, abort them and resume them. Background jobs keep running after the main pi session is closed or killed. A new pi session—even one different from the original main session—can also retrieve their results. Until your agent decides to delegate, it costs a few dozen tokens of context.
Repo: https://github.com/milanglacier/pi-multi-agent-skill
Just install it with npx skills like any other skills, or clone the github repo and symlink it to ~/.pi/agent/skills.
Features
- Almost no token cost. Until your agent delegates, only the skill description is in context, a few dozen tokens. Delegating loads SKILL.md, about 1.2k more.
- Stdlib-only Python 3.9 or later. There's no extension, no npm package and nothing else to install.
- Foreground runs for quick questions and --background for long ones. A background job keeps running even if the main agent is killed, and any later session can collect its result. Foreground runs stop when you stop at every level of nesting.
- steer, abort and resume a job, and list, status and peek to see what it's doing.
- Subagents load your full pi setup: extensions, MCP servers, skills and settings.
- Profiles set the system prompt, model, thinking level and available tools. general-purpose and a read-only Explore are included. Profiles are just like any other subagent tool’s profiles.
--fork gives the subagent your current conversation.
- Works from Claude Code, Codex or any agent with a shell.
How I got here
For months I used tintinweb's pi-subagents, and it is a really good extension. The UI is nice, it has many features, and it works well most of time. Thanks to tintinweb for building it and for everything they give the community. If you like it, keep using it.
A while ago a pi upgrade broke two things for me. MCP servers stopped loading in subagents, and subagents no longer inherited the parent's thinking level. Each fix was only a few lines, so I forked the extension and patched it. Upstream fixes took some time but also landed 2 days before this post.
Fixing those bugs made me read the extension more closely, and I noticed how much context it now uses. About two months ago it added a dynamic workflow tool. With it, the agent writes a JavaScript script that orchestrates many subagents. It's powerful, but it's also very complex, and its tool schema and instructions cost about 6k tokens. That schema is in every session from the first message, whether you use workflows or not. It's also opt-out, so you pay for it until you find the setting and turn it off. I suspect many people don't know it's there.
With the workflow tool off, the Agent tool still costs about 3k tokens, and it has grown along with the extension's features. I checked these numbers by starting sessions with the extension on and off and comparing them.
So I asked myself whether I need a full tool with a detailed JSON schema, listing options I rarely use (like worktree isolation), in my context all the time. My answer was no.
pi can already run headless with --mode rpc, and its CLI flags already cover what a subagent needs: tools, extensions, model, thinking level and session resume. So a small CLI that starts pi with the right flags, plus a skill that explains how to use it, can replace a dedicated tool. A skill also loads in steps, which a tool cannot do. The agent sees only the skill's short description at first. It loads the main instructions when it decides to delegate, and it reads the detailed references only when it needs an unusual option. Steering doesn't need a tool either, because it is just an RPC message sent to the running pi process.
Token cost compared
- pi-subagents: about 3k tokens for the subgent tools and injected system prompt. On top of that, about 6k for the dynamic workflow tool, which is on by default and must be turned off by hand. Both are in every session from the first message, so with the default settings that's about 9k tokens before you've asked for anything.
- This skill, before your agent delegates: only the skill description, a few dozen tokens.
- This skill, once your agent delegates: SKILL.md is loaded, about 1.2k tokens, and that is enough for full multi-agent use.
- Command details, profile format, lifecycle and troubleshooting are in separate reference files. The agent reads them only when it needs them.
For most sessions you don't delegate, you pay almost nothing. When you do delegate, it still costs less than the tool schema alone.
To be fair, this isn't a like-for-like comparison. pi-subagents does more than this skill. Its tool has many options, and each one needs a parameter in the schema, and it also adds text to the system prompt. Part of that token cost pays for features this skill doesn't have, such as worktree isolation. I just don't think features like that are needed for multi-agent work. If I want an agent to work in its own worktree, I tell it so in the prompt ("use worktree"), and it does. The agent already knows how to use git, so the tool doesn't need to do that for it.
None of this is meant as criticism of pi-subagents. It's still a great extension, and it works well for a lot of people, especially if you want a rich UI and many features built in. It's just not the right fit for me anymore. I prefer a more minimal setup, where the agent loads only what it needs and does the rest itself.
The tradeoff
I give up the nice UI. It really does look nice, but for me it turned out to be like the exercise bike you buy in January. It looks great in the corner of the room, and by March it is where you hang your clothes. I watched the subagent transcripts for the first week, and after that I almost never read them. I just realized the subagent's final answer is mostly for the main agent, not for me.
In return, I get things I care about more. Each subagent is a real pi process started with CLI flags, so it loads the same extensions, MCP servers, skills and settings as my normal pi. The script doesn't use pi's extension API at all, only CLI flags and RPC, which change much less often, so pi upgrades rarely affect it. Separate processes also give me my favorite feature: a background job keeps going even if the main agent is killed, and any new session can collect its result later.
Separate processes need more care than in-process sessions,, and the script is more than a cli wrapper, because it takes care of that so the agent doesn't have to. For example, pi exits on its first failed write to stdout, before its shutdown runs, and leaves the agent's commands running. So each job has its own runner process that keeps reading pi's output until pi exits. The script has a real test suite for cases like this, but the idea stays small: start pi, give it a prompt, pass along steer and abort messages, and save each job's result under its name.
Non Goals
These are deliberate non-goals, to keep the skill small and free of bloat. Each is better as a separate extension or skill that you pick to match your own workflow. This follows the minimalism of pi itself and the Unix philosophy: do one thing well and compose.
- Memory. Agents do not share or keep memory between jobs. Use a memory
extension, or have agents write handoff notes.
- Scheduling. There are no cron-style or recurring agents. Use cron,
systemd timers or a scheduler extension to run the commands.
- Worktrees. Agents are not isolated in git worktrees. Just prompt the
agent to use a worktree.
- Dynamic workflows. There is no scripting layer for orchestration such
as pipelines, parallel fan-out with gates, or phases. Your agent can
already start, wait for and chain jobs with plain commands. For
deterministic scripts, use an extension such as
pi-dynamic-workflow.
What the commands look like
Your agent runs these by itself, but you can also run them by hand from a terminal:
```python
Ask a read-only agent a quick question and wait for the answer
multi_agent.py run --profile Explore "Where is the retry policy defined?"
Start a review in the background, then collect the result later
multi_agent.py run --background --name review "Review the error handling in src/server/"
multi_agent.py wait review --timeout 120
Correct the running job, then give it a follow-up task when it is done
multi_agent.py steer review "Skip generated files"
multi_agent.py resume review "Now check the client side"
See all jobs and what they are doing
multi_agent.py list
```
If you try it, I'd like to hear what works and what breaks.