pi-subagents routes a typed mention off the main model and leaves no trace
Claude Code like Sub-Agents & Workflow Orchestration for Pi — parallel execution, live widget, fleet view, custom agent types, mid-run steering, claude compatible dynamic workflows and more ...
At a glance
- What is it?
- A pi extension that spawns sub-agents with their own tools, system prompts, models and thinking levels, adds a fleet view, mid-run steering and a scripted workflow tool whose sandbox is a virtual machine context with three globals disabled. Four runtime dependencies include two different packages with the same name, and the peer ranges have no upper bound.
- Who is it for?
- pi-subagents is worth reading if you are moving an existing setup to pi rather than starting fresh, because the compatibility work is specific and mostly favourable.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 30 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Four dependencies, two of them with the same name
The runtime dependency list has four entries, which is small for an extension that manages concurrent sessions, a terminal interface and a script runtime.
Two of them are schema libraries with almost identical names. One is the scoped classic package at a 0.34 version. The other is an unscoped package with the same name at a 1.3 version. Both are in the list, and nothing in the visible documentation says which part of the extension uses which.
The third is a cron library at a 10 version, and the fourth is an identifier generator. The cron library is the interesting one, because the feature list on the page never mentions scheduling, timers or anything periodic. A recurring-expression scheduler is a dependency with a persistent side effect, and it is not described anywhere in the parts of the page that are visible.
Everything else the extension does appears to be built on what pi provides. The three peer dependencies are the AI layer, the coding agent and the terminal interface components of the host, so the concurrency, the terminal rendering and the model access are the host's job rather than this package's.
For an extension whose job is orchestration, four dependencies is a good sign. Two libraries that differ only by a scope is the sort of thing that survives a refactor and then confuses the next person to read the manifest.
Peer ranges have a floor and development versions have a pin
Three peer dependencies, each with the same shape of range: a floor of 0.84.0 and nothing above it.
So a host at 0.84 works, and a host at 1.0, or 2.0, or a future major with breaking interface changes, also satisfies the range and will install. For an extension whose entire surface is three host interfaces, an upper bound is what you would normally expect, because the extension calls into those packages rather than merely importing types from them.
The development dependencies pin the same three packages to an exact patch release. So the code is written and tested against one specific version and declares compatibility with everything above it.
That combination is not unusual and it is not wrong, but it does mean the compatibility claim is untested in the direction that matters. A maintainer shipping a breaking host release would have to update the extension's peer ranges to signal it, and until they do, an install gives no warning.
The manifest also declares its public type as a scoped package name, a public access flag for publishing, and a keyword list that includes two markers identifying it as a package for the host and as an extension for it. There is no executable entry point, which is consistent with a package that the host loads by discovery rather than something you run.
An agent mention leaves the conversation without appearing in it
The mention feature is documented in more operational detail than anything else on the page, and it is the one to read twice.
Type an at-sign followed by an agent name and some text at the prompt, and that text goes to that agent instead of to the main model. The page states twice, in different words, that not one word of it enters the chat.
The same syntax covers four situations. You can message an agent that is running. You can resume one that has finished. You can reopen its session from disk long afterwards. And you can start one that has never run.
The last case is the one with a consequence worth naming. Mentioning an agent that is not running spawns it through an off-screen clone of the conversation, so that it receives the same context-written prompt another tool call would produce, without any of it reaching the visible chat. There is a second mode that starts the agent from your text directly, with no model call at all.
So there are two paths where typed text becomes work dispatched to another agent, one of which skips the model entirely. Neither leaves a line in the conversation. The at-sign also completes live agents, resumable ones and startable types alongside the host's own file completion, and a special mention forces text back to the main model.
The orchestrator can name agents so you address them by a label rather than a type, and the same tools can be used from inside a running agent. That last part is what makes the mention syntax a general routing mechanism rather than a front-end convenience.
The nested allowlist is documented as a privilege boundary
Delegation to sub-agents is off by default, which is the right default for a feature that expands what a model can reach.
When a custom agent type sets an allowlist, it receives its own copies of the three agent tools, scoped to its own ownership. Depth is capped from the main session, at two by default. It can control only its own children, the children are stopped when it finishes, and their transcripts and token spend roll up to the parent.
The documentation then says the thing that matters: the allowlist is a privilege boundary, a child runs with its own tools, so choose it as carefully as the tool list itself.
That framing is correct and unusual. Most delegation features describe the capability and leave the boundary implicit. Here the comparison being drawn is to the tool allowlist on an agent definition, which is the right comparison, because both are the set of things an agent can do without asking.
Agent definitions themselves are markdown files with YAML frontmatter, in one of two project locations or globally, and the frontmatter carries a custom system prompt, a model choice, a thinking level, tool restrictions and a coloured name badge. So the whole delegation policy is expressible in files you can review and diff, which is what makes the privilege-boundary claim checkable rather than aspirational.
Agent types resolve case-insensitively, which means three files differing only in case are three distinct types on a case-sensitive filesystem and an ambiguity to be resolved on a case-insensitive one. The page is explicit about that: a name that does not resolve to exactly one enabled agent falls back to a general-purpose agent with a note, or is refused outright under a strict setting.
The workflow sandbox is a VM context with three globals disabled
The scripted workflow tool runs a deterministic JavaScript file that orchestrates many agents, and the page is explicit about the execution environment.
Scripts run in a virtual machine context on a worker thread, and inside that context three things throw when touched: the current-time function, the random number generator, and dynamic evaluation.
The page calls this a sandbox. It is worth being precise about what it delivers, because the two goals are different. Disabling those three functions is a determinism measure: a script that produces the same result every run cannot read the clock or roll dice, and cannot reach the ambient scope through dynamic evaluation. What it does not provide is isolation, because a virtual machine context in that runtime shares the process it runs in and is not a boundary against code that wants to reach outside it.
The extension itself points at the real boundary elsewhere. In the delegation feature, the allowlist is called a privilege boundary and compared to the tool list. That framing is the accurate one, and it applies to a workflow script as much as to a nested agent: a script runs with the extension's own permissions.
The rest of the workflow surface is well specified. There are helpers to spawn a single agent, to run many at once, to run a pipeline, to declare phases, to log, and to read arguments, with a metadata block that has to be a literal. A pipeline has no barrier between stages, so one item can be in a later stage while another is still in the first, which is the difference from the parallel helper and is called out explicitly because it changes how you write the script. A single agent call can also verify its child by running a command rather than asking another model, and can resume a labelled child instead of paying its context again.
A budget directive that always reports no target
The compatibility story with the other tool's workflow format is the most specific passage on the page, and one clause in it is a compatibility shim rather than a feature.
A script written for the other tool runs here unchanged. The page enumerates what that means: the same globals are present, the schema helper returns a validated object exactly as it does there, and nested workflow calls compose saved workflows one level deep.
Then the budget clause. The helper is present, and it always reports no token target, because the host has no such directive. The consequence is stated precisely: patterns guarded by the budget's total check still take the branch they were written for.
So a script that checks whether it has a budget will read zero or no target, and will behave as a script authored for a system that does have one. That is deliberate and it is the right call for compatibility, but it means the budget guard is inert: it is not a limit, it is a branch selector that always resolves the same way. A script that relied on that guard to stop work at a token ceiling will not stop.
The extension also stands down rather than compete. If another extension already provides a tool with either of the two workflow names, this one warns and disables itself for the session, rather than exposing the model two orchestrators that mean different things. That is a good call and an unusual one, since the usual extension behaviour is to register anyway and let the host resolve the collision.
The interface is a keyboard language and the widget has three positions
Most of the feature list is interface, and the interface is described in key presses rather than in words, which tells you what kind of tool this is.
The fleet view is a list of the main session plus every running agent, rendered below the editor, ordered by launch time so the oldest is first. You jump into it from an empty prompt with a down or left arrow, move the selection with the arrows, open the selected agent with return, and come back with escape. Finished agents linger briefly before dropping out, and a viewer stays open through completion so you can read the final output rather than having it disappear.
The conversation viewer opens as an overlay over the selected agent's full conversation, follows new content automatically, and pauses when you scroll up. Inside it, return opens a composer so you can steer a running agent inline; the message appears as a user message and redirects the agent after its current tool call, which is the detail that makes steering predictable rather than racy. Escape or an empty submit backs out. A running agent is stopped with the letter x, confirmed with a second press, and the page notes that this works for background agents too. The letter m cycles assistant text rendering through off, assistant only and everything.
Above the editor there is a persistent widget with spinners, live tool activity, token counts and coloured status icons, and it has three positions: everything, background only as the default, or off. The default hides foreground runs on the stated ground that they already render inline as the result of the agent tool call, so the widget is for the work you would otherwise have no way to see.
The publish step is the one that stands out against most packages here: it runs lint, typecheck, tests and build, in that order.
Editorial conclusion
pi-subagents is worth reading if you are moving an existing setup to pi rather than starting fresh, because the compatibility work is specific and mostly favourable. The tool names, calling conventions and interface patterns match what the other coding agent uses, agent types resolve case-insensitively, models can be named loosely and filtered to what is configured, and a workflow script written for the other tool's orchestrator runs unchanged, including its schema validation and its budget guard, which takes the branch it was written for even though the underlying capability does not exist here.
Three things to weigh before you enable the parts. Agent mentions are the quiet one: text typed at the prompt is routed to a named agent instead of the main model, and by design nothing about it enters the chat, so a request can leave the conversation you are reading and you will not see it happen. Nested delegation is opt-in and capped at depth two by default, and the documentation is clear that the allowlist is a privilege boundary and should be chosen as carefully as the tool list, which is the right framing. And the workflow sandbox is a virtual machine context on a worker thread with three named globals throwing, which is a determinism measure rather than an isolation guarantee, so scripts you write are running in your own trust context, not a walled one.
The configuration surface is wide and all of it lives behind one settings command, with three display toggles and a fallback policy for unresolvable agent names. Everything the extension persists is a settings file you can edit or pin, which is the right shape for something that changes how your editor behaves.
Frequently asked questions
What does the pi-subagents extension add to pi?
Autonomous sub-agents in isolated sessions, each with its own tools, system prompt, model and thinking level, run in the background by default or blocking, steerable mid-run and resumable, plus a deterministic script orchestrator and the same tool names and interface patterns the other coding agent uses.
Can a pi subagent spawn its own subagents?
Yes, opt-in and off by default. An agent type that sets an allowlist gets its own agent tools scoped to its own children, with depth capped from the main session at two by default. The documentation calls the allowlist a privilege boundary and says to choose it as carefully as the tool list.
What happens when I type an at-sign and an agent name at the pi prompt?
The text is routed to that agent instead of the main model, and the page states twice that none of it enters the chat. If the agent is not running, mentioning it spawns one through an off-screen clone of the conversation; a direct mode starts it from your text with no model call at all.
How are pi subagent workflows executed?
In a virtual machine context on a worker thread, with the current-time function, the random number generator and dynamic evaluation all throwing when touched. The helpers cover single agents, parallel runs, pipelines with no barrier between stages, phase declarations, logging and arguments.
Does pi-subagents depend on other packages at runtime?
Four: two different schema libraries with almost the same name, one of them scoped and one not, plus a cron library that the visible feature list never mentions, and an identifier generator. The host's AI, coding agent and terminal packages are peer dependencies with a floor and no upper bound.
What happens if another pi extension already provides a workflow tool?
This one warns and disables itself for the session rather than registering a second tool with the same name and leaving the model to choose between two orchestrators. The behaviour can be pinned either way through a settings flag in the config file or through the settings command.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/tintinweb-pi-subagents)