pi-open-agents
Unified agent and subagent management for pi coding agent, with OpenCode-compatible agent definitions.
Package details
Install pi-open-agents from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-open-agents- Package
pi-open-agents- Version
0.1.27- Published
- Oct 17, 2026
- Downloads
- 829/mo · 149/wk
- Author
- andrea-tomassi
- License
- MIT
- Types
- extension
- Size
- 187.1 KB
- Dependencies
- 0 dependencies · 4 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-open-agents
Unified agent and subagent management for pi, with OpenCode-compatible agent definitions.
Replaces pi-agent-mode + @johnnywu/pi-subagents with one coherent plugin.
Why pi? Pi's minimalist core keeps system prompts under 1,000 tokens — making it exceptionally fast on local models and cheap on cloud APIs. pi-open-agents is built to leverage that minimalism. See Pi vs OpenCode: Performance & Architecture for a detailed comparison.
🐑 Herd your agents. pi-open-agents + Herdr runs a full team of coding agents — persistent workspaces, live agent awareness, control from one screen. Set up the stack in 5 commands →
Quick start
pi install npm:pi-open-agents
Remove old plugins from ~/.pi/agent/settings.json:
{
"packages": ["npm:pi-open-agents"]
}
Existing .agent.md files work without changes (default mode: all).
Agents vs subagents (and why you need both)
People tend to lump "agents" and "subagents" together. They're not the same thing, and the difference is the whole game.
An agent changes your session. Switch to one and the conversation you're already having starts thinking with a different brain — different prompt, different model, different tools, different rules. The thread keeps going; what's running it changes. Planning wants a slow, deliberate mind. Coding wants a fast one. Reviewing wants a skeptic. An agent is how you become the right one for the moment.
A subagent never touches your session. It's a separate process you spin up for one job — usually on a cheaper, faster model, with locked-down permissions — that works in isolation and hands you back an answer. Your context stays clean; your main model keeps its focus.
The payoff is using both. You sit in an orchestrator agent — the strong model holding the plan — and delegate the grunt work to subagents: search these five hundred files, run that test matrix, draft the boilerplate. One mind to think, many hands to do. You get the big model's reasoning and the small models' speed and economy, without one poisoning the other's context.
And the moment you delegate, control stops being optional. A subagent is a real process with real tools — it can read your secrets, rewrite your files, run shell. So you choose its model, set its thinking level, clip its permissions to read-only or git-only, cap how deep it can recurse, decide who's even allowed to spawn whom. That's not red tape. It's what turns delegate and pray into delegate and trust — and it's exactly what this plugin gives you.
Why this exists
Pi splits agent management across two separate plugins — one for primary agents,
one for subagents. They use incompatible schemas, conflict on model routing, and
have no permission system. pi-open-agents replaces both:
pi-agent-mode |
pi-subagents |
pi-open-agents |
|
|---|---|---|---|
| Primary agent switching | ✅ | ❌ | ✅ |
| Subagent delegation | ❌ | ✅ | ✅ |
| Per-agent thinking level | ❌ | ❌ | ✅ |
| Permission system | ❌ | ❌ | ✅ |
OpenCode .agent.md format |
❌ | ❌ | ✅ |
Popular requests, already covered
Some of the most upvoted agent/subagent asks across the ecosystem are already here — or native in pi itself:
| Asked elsewhere (👍) | Status in pi + pi-open-agents |
|---|---|
AGENTS.md adoption — anthropics/claude-code#31005 👍336, openai/codex#12115 👍109 |
✅ Native in pi: AGENTS.md/CLAUDE.md discovery with AGENTS.override.md layering |
Agent Skills standard (.agents/skills/) — agentskills/agentskills#15 👍183 |
✅ Native in pi; shared agents from .agents/ (#7 aligns to the dotagents layout) |
| Tool restrictions that actually reach subagents — anthropics/claude-code#18950 👍70 | ✅ Since v0.1.14 via --tools; full deny/ask inheritance (effective-set ceiling + arg patterns) since v0.1.27 |
| Model selection per subagent / per call — sst/opencode#6651 👍71 | ✅ Per-agent model: + per-call model: override in subagent() (since v0.1.19) |
| Reasoning effort per agent — Kilo-Org/kilocode#13105 👍8 | ✅ thinking: off…xhigh per agent, forwarded to the child process |
| Delegation guards — Kilo-Org/kilocode#9985 | ✅ allowedAgents allowlist + maxDepth recursion limit |
| Agent management UI — openai/codex#22321 👍41 | ✅ /agent, /agents, /agent-search, Ctrl+Shift+M, programmatic set_agent |
Features
Per-agent model, thinking, and permissions
Every agent defines its own model:, thinking:, and permission: — no global
overrides, no sentinel values, no workarounds. An orchestrator can run on a strong
reasoning model while subagents run on a fast local model:
---
name: orchestrator
mode: primary
model: anthropic/claude-sonnet
thinking: high
---
---
name: fast-worker
mode: subagent
model: lm-studio/qwen-2.5-coder
thinking: off
---
Permission system
Go beyond a simple tool whitelist. OpenCode-style rules with glob patterns, deny rules, and per-action restrictions:
permission:
"*": allow # default: everything allowed
"edit": deny # read-only agent
"bash":
"git *": allow # only git commands
"rm *": deny # never delete
"subagent": deny # no delegation
Tool names are normalized automatically: task → subagent, vscode → read,
apply_patch → edit (OpenCode-only tool). In pi, write and edit are
separate tools — write creates/overwrites files, edit does search-and-
replace — so they have separate permission categories.
Runtime enforcement (v0.1.24). Every tool call is evaluated against the active agent's rules before it runs — not just used to filter the toolset:
denyblocks the call; the model receives a clear denial reasonaskopens a dialog: Allow once / Allow always (this session) / Deny- Patterns are argument-aware: file paths for
read/edit/write, command strings forbash("rm -rf *": deny,"**/*.env": deny—*doesn't cross/, use**for nested paths) - Rules are evaluated top-to-bottom, last match wins — put specific rules
after catch-alls (
"*": askfirst, then"git *": allow) - A call matching no pattern within a configured category proceeds (rule lists are deny/ask lists, not exhaustive allowlists)
⚠️ Migration note (v0.1.24):
askis now enforced — previously it was parsed but silently ignored. In non-interactive processes (subagent children, print/JSON mode) anaskrule blocks the call (fail-closed): add an explicitallowrule if a subagent needs that tool.denynow also blocks matching individual calls (patterns included), not just statically hiding whole tools. (#20)
Inheritance down the delegation chain (#8). A subagent can never exceed the authority of the agent that delegated to it — in both directions of the rule language:
- Tool ceiling: at delegation the parent's live tool set is snapshotted
(
pi.getActiveTools()), minus tools it blanket-denys or blanket-asks (askis not authority: headless children have no approval bridge). The child's own whitelist is intersected with that ceiling and passed via--tools— an empty intersection becomes--no-tools, never "all tools". - Argument patterns: the parent's
deny/askrules (patterns included) travel to the child's gate and are evaluated last, so the child cannot widen them (write: {"**/*.env": deny}upstream blocks.envwrites two levels deep, whatever the child declares). - Transitive: the ceiling the child launches with is the child's active set — a grandchild cannot regain any tool removed at an earlier hop.
Iterating on agents: /reload
Edit a .agent.md file (or add/remove one) and run pi's built-in /reload
— no session restart (#9). Agent definitions are re-discovered, the active
agent is kept (your mid-session switch survives; --agent is a
startup-only default), and a deleted/disabled active agent falls back cleanly
with a warning. New agents appear in /agents and the subagent tool list
immediately.
Auto-injected delegation guidance
If an agent has the subagent tool, the plugin automatically appends a
## Subagent Delegation block to its system prompt — listing available
subagents and the correct call syntax:
subagent({ agent: "<name>", task: "<task>", cwd?, session?, model? })
You never need to explain delegation mechanics in agent prompts. The plugin handles it, the same way pi handles tool descriptions.
Subagent execution engine
When an agent delegates, the plugin spawns a child pi process with the target
agent's configuration. The child runs in isolation — it gets --model,
--system-prompt, and --tools from the executor, not from settings.json.
This means:
- The primary agent's
defaultAgentnever leaks into subagents - Each subagent runs with exactly the model and tools it declares
- Skills load per-agent, with wildcard support (
security-*,git-*)
skills:is subagent-only (#19). pi discovers skills once at session startup and exposes no per-agent filter, so a primary cannot role-scope them. Declaringskills:on a primary (orall) agent warns on apply and the field is ignored; the subagent child receives exactly its listed skills, injected into its system prompt.
Per-call model override: the caller can override the agent's default for a
single call — subagent({ agent: "deep-research", task: "...", model: "zai/glm-5.3-flash" }).
Handy for "run this one task on the cheap model" without forking an agent
definition. Malformed values (no-slash) are rejected before any spawn.
Aggregator providers work too — the model id may contain slashes:
model: "openrouter/anthropic/claude-opus-5.5".
The --tools whitelist is derived from both explicit tools: arrays and
permission allow-lists. An agent with permission: { read: allow, edit: allow }
will only get read and edit in the child process. Wildcard permissions
(*: allow) cannot produce a finite whitelist — the child gets all tools.
OpenCode compatibility
Your .opencode/agent/ files work as-is. The tools map format is auto-converted
to permission rules, and pi-specific fields (thinking, maxDepth, allowedAgents)
are simply ignored by OpenCode without breaking:
# OpenCode format — works in pi without changes
name: triage
mode: subagent
tools:
read: true
bash: false
The tools map is converted to permission rules and also restricts the
subagent child process — a subagent with tools: { read: true, bash: false }
will only have access to the read tool when spawned.
Mode-based visibility
mode |
TUI selector | subagent tool |
set_agent tool |
|---|---|---|---|
primary |
✅ visible | ❌ | ✅ |
subagent |
❌ | ✅ available | ✅ |
all (default) |
✅ visible | ✅ available | ✅ |
Use primary for user-facing agents, subagent for delegated workers, all when
an agent serves both roles.
Agent definition format
---
name: my-agent # required
description: One-line description
mode: subagent # primary | subagent | all (default: all)
hidden: false # hide from TUI selectors
color: "#44BA81"
model: anthropic/claude-sonnet # per-agent model override
thinking: xhigh # off|minimal|low|medium|high|xhigh
systemPrompt: replace # append | replace | replace-all (default: append)
permission:
"*": allow
"question": deny
"edit":
"*.env": deny
maxDepth: 5 # subagent recursion limit
allowedAgents: [explorer] # restrict which subagents this can spawn
skills: security-audit, git-* # per-agent skills with wildcards
---
Your prompt goes here. This becomes the agent's system prompt.
System prompt modes
The systemPrompt field controls how the agent body interacts with pi's default
prompt and workspace context files (CLAUDE.md, etc.):
| Mode | System prompt | Context files |
|---|---|---|
append (default) |
pi's prompt + agent body | ✅ loaded |
replace |
Agent body only | ✅ loaded |
replace-all |
Agent body only | ❌ disabled |
Use replace-all for fully isolated agents that should not be influenced by
workspace context — e.g., a subagent that must run identically regardless of
the project it's invoked from.
For subagents (child process), the agent body is the system prompt — pi's default prompt is not included. Skills are injected as an XML block after the body.
Discovery paths
Agents are loaded from multiple locations (project overrides global by name):
| Path | Scope | Format |
|---|---|---|
~/.pi/agent/agents/*.md |
Global | pi |
~/.opencode/{agent,agents,mode}/*.md |
Global | OpenCode |
.pi/agents/*.md |
Project | pi |
.opencode/{agent,agents,mode}/*.md |
Project | OpenCode |
.agents/agents/*.md |
Project | Shared |
⚠️ Migration note (v0.1.22): discovery in the shared
.agents/directory is now scoped to.agents/agents/*.md— previously every markdown file under.agents/(includingskills/andcommands/) was parsed as an agent and showed up in/agentsand thesubagenttool. If you relied on the loose loading, move your agent files into.agents/agents/. Skills and commands are picked up natively by pi as before. (#14)
Usage
Interactive
| Action | What it does |
|---|---|
/agent |
Open agent selector (primary/all only) |
/agent <name> |
Switch to agent directly |
/agents |
List all agents |
/agent-search <query> |
Search agents |
Ctrl+Shift+M |
Cycle agents |
--agent <name> |
CLI flag for startup agent |
Programmatic (LLM tools)
| Tool | Description |
|---|---|
set_agent |
Switch agent programmatically |
search_agents |
Search agents by name/description/body |
subagent |
Delegate task to a subagent (subagent/all mode only) |
Migration
pi install npm:pi-open-agents
Remove npm:pi-agent-mode and npm:@johnnywu/pi-subagents from settings.json.
Existing agent .md files work without changes.
Optional cleanup:
- Add
mode: primaryormode: subagentto agent files for explicit visibility - Gradually adopt
permission:over the oldtools:whitelist
Run a fleet 🐑
Pi stays minimal on purpose — one agent, done well. When you need many,
add Herdr: persistent workspaces, mouse-first UX, live
agent awareness (idle / working / blocked), and cross-agent control
from one screen — pi, or any mix of the 25 supported agent kinds. Six agents,
six sessions, zero chaos: that's the exact workstation setup documented in
pi × Herdr × pi-open-agents.
Roadmap
Parent permission inheritance for subagents— ✅ shipped in 0.1.27 (#8)Agent hot-reload— ✅ works via pi's built-in/reload, shipped in 0.1.27 (#9)Per-call model override in— ✅ shipped in 0.1.19 (#10)subagent()- Parallel subagent limit — #11
Development
Contributing? Please read the Contributing Guide before opening an issue or pull request.
npm install
npm test # 178 tests
npm run typecheck # tsc --noEmit
Docker testing
docker compose run --rm pi-sandbox
See ARCHITECTURE.md for the full technical design.
Attribution
This project builds on code and ideas from:
- pi-agent-mode by ZGltYQ (MIT)
- pi-subagents by jwu (MIT)
- opencode by sst (MIT)
See ATTRIBUTION.md for details.
License
MIT