pi-agentteam
Multi-agent team orchestration for pi — leader-coordinator pattern with researcher, planner, and implementer teammates in tmux panes
Package details
Install pi-agentteam from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-agentteam- Package
pi-agentteam- Version
0.5.5- Published
- May 28, 2026
- Downloads
- 510/mo · 35/wk
- Author
- linys77
- License
- MIT
- Types
- extension
- Size
- 551.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-agentteam
Multi-agent team orchestration for pi
Coordinate a leader with specialized teammates — researcher, planner, and implementer — each running in a visible tmux pane, collaborating through shared tasks and typed messages.
✨ Highlights
| Feature | ||
|---|---|---|
| 🖥️ | tmux-native teamwork | Each teammate is a real pi session in its own pane — watch them work in real time |
| 📋 | Leader-gated task board | Leader-owned task facts with worker report_done/report_blocked reports and review |
| 💬 | Typed messaging | assignment · question · inform; task reports handle done/blocked outcomes |
| 🎯 | Role-based tool guard | Researcher/Planner (read-only) → Implementer (full tools) — least privilege by default |
| 📡 | Event-driven delivery | Teammates are notified for actionable messages when tasks are unblocked; mailbox reads stay explicit |
| 📊 | Unified /team console |
Browse state, recover old teams, remove stale teammates, and cleanup without memorizing extra commands |
| 🔗 | Peer context handoff | Workers communicate through mailboxes with hidden task audit refs/diagnostics; leader reviews attention signals and explicitly starts downstream work |
| 🧹 | Zero footprint | One folder, file-based state, no database — delete and it's gone |
📦 Install
pi install npm:pi-agentteam
Requirements: pi ≥ 0.60 · tmux. The leader pi session must run inside tmux.
🚀 Quick Start
You (leader):
Create a team and ask the leader to handle the routing work.
> Create an agentteam for this project.
> Spawn one researcher to analyze the build pipeline.
> When the research task is done, ask a planner for an optimization plan.
The leader should create/assign shared tasks, choose the matching teammate
from the roster, send short task-id based assignments, then receive and
synthesize task reports.
Equivalent low-level tool flow when you need it:
> agentteam_create({ team_name: "my-project", description: "Optimize the build pipeline" })
> agentteam_spawn({ name: "research", role: "researcher" })
> agentteam_task({ action: "create", title: "Analyze build pipeline",
description: "Report bottlenecks with evidence", owner: "research" })
> agentteam_send({ taskId: "T001", message: "Analyze the build pipeline and report bottlenecks",
type: "assignment" })
> agentteam_receive()
Because T001 has owner research, the assignment can omit to. Explicit to is still available when you need to override task-owner routing.
Or open the unified local console:
/team ← local console for status, recovery, and cleanup
🧭 Recommended Workflows
Use agentteam when work benefits from visible role separation, not for every small edit.
| Want | Suggested flow |
|---|---|
| Understand unfamiliar code | Spawn researcher → task-local note with files, facts, risks → report_done for leader review → leader synthesizes |
| Plan a risky change | Leader assigns researcher fact-finding first → researcher reports to leader → leader reviews task-local notes → leader creates/assigns a separate planner planning task |
| Execute an approved plan | Assign one focused task to implementer → run checks → worker report_done with files changed → leader close when accepted |
| Keep a handoff from stalling | Ask the leader to route a task-id based inform or assignment to the right teammate |
| Resolve uncertainty | Worker sends question or an agentteam_task blocker report → leader agentteam_receive() → decide next step |
| Check team health | Open /team for status, mailbox attention, stale panes, recovery, or cleanup |
Recommended loop:
clarify → create task with owner when clear → send task-id assignment → teammate works visibly → receive full mailbox text → inspect task-local notes → synthesize
Use natural language first:
Let a researcher inspect this area. Create the task, choose the matching teammate, send the assignment, then summarize the result when it reports back.
The leader should not make you memorize teammate names when the intent is clear. If one teammate matches the requested role, reuse it. If several could match, ask a short clarification. If none exists, ask before spawning. Once a task has an owner, agentteam_send can omit to and route through taskId. Never broadcast by default.
Keep the leader as coordinator: teammates produce facts, plans, edits, and reports; the leader decides what to adopt and how to answer the user.
🎮 /team Console
/team is the only slash command exposed by agentteam. It opens a local console instead of a pile of maintenance commands.
Attached to a team:
/team
→ Members · Tasks · Mailbox · Details
→ select an item
→ Enter opens contextual actions
Not attached to a team:
/team
→ AgentTeam Console
→ list saved teams and stale panes
→ recover an old team as current leader, delete a team, or cleanup all agentteam state
| Key | Action |
|---|---|
Tab |
Cycle sections |
↑ ↓ |
Move selection |
Enter |
Open action menu / choose action |
Esc |
Step back / close |
The panel intentionally does not focus tmux panes or perform task/message CRUD. Use tmux for pane navigation, and use tools for collaboration work. /team is for local runtime visibility, recovery, and cleanup. Expanded Details use an internal reader so long notes/messages remain readable without flooding terminal scrollback.
Available action-menu operations include:
- refresh/reconcile tmux pane bindings;
- sync compact leader mailbox projection without marking messages read or delivered;
- remove selected teammate;
- delete selected/current team;
- recover an existing team as the current leader;
- cleanup all agentteam state and stale panes while keeping the current pane alive and clearing its agentteam label.
💬 Messages & Wake Behavior
Public collaboration vocabulary is intentionally small: task status is open | blocked | done, worker health is offline | idle | busy | error, agentteam_send types are assignment | question | inform, and task reports are report_done | report_blocked.
Messages carry an implicit wake hint that controls whether AgentTeam creates a bridge delivery/projection request. Mailbox read state is simple: messages remain unread until agentteam_receive({ markRead: true }), which is the explicit read boundary and the only normal full-text mailbox entry point. Single-message receive output stays clear/full; when multiple unread messages are returned, the human-facing receive text folds them by task/thread with compact ids/types/from/summary previews while details.messages remains the full returned mailbox payload with full text unchanged. tmux is the visible pane/container layer only; AgentTeam has a single bridge-only delivery policy and uses durable Outbox effects, durable bridge worker requests, compact durable leader mailbox projection, and bounded leader attention wakes. deliveryMode is not a vNext config key; remove it from config or roll back by pinning npm pi-agentteam@0.5.0 instead of selecting legacy terminal transport. Worker-to-leader signals use compact native/idempotent projection plus compact bounded leader attention for question to leader and owner report_done/report_blocked. Projection and attention are reminders/wake signals with message id, task, type, summary, and a receive instruction; they do not carry the full message body. inform never requests leader attention. If bridge/projection is unavailable, work remains visible as public busy/error worker health plus diagnostics; AgentTeam does not silently fall back to terminal key injection. Native submit/projection/attention never marks mailbox readAt or deliveredAt; explicit receive owns those transitions.
agentteam_send type |
Purpose | Wake | Typical Flow |
|---|---|---|---|
assignment |
Leader → worker task assignment | hard | Leader delegates unblocked actionable work |
question |
Clarification request | soft | Anyone asks a question |
inform |
Informational update | none | Context sharing; does not wake a worker by default |
report_doneandreport_blockedare task-report outcomes, notagentteam_sendtypes. Non-leaders may useagentteam_task action=report_doneoragentteam_task action=report_blockedonly for tasks they own; non-owners should useinformorquestionfor context.Bounded leader attention means one compact native leader wake that should
agentteam_receive, review, decide, and stop. It must not auto-spawn, auto-create downstream tasks, broadcast, or start worker-to-worker chains.Task-bound sends keep the recipient mailbox as the communication source of truth. The task stores only a hidden communication ref for audit/indexing; internally this uses
sourceKind=communication_ref,displayMode=hidden, andlinkedIds.mailboxMessageId, while retaining legacy P0 markers for compatibility./teamfolds these refs by default and may show only a compact ref count; it does not copy the message body, does not count refs as ordinary/latest notes, and does not bump task recency.Peer
informhandoffs are mailbox communication plus hidden task audit refs/diagnostic event refs only; diagnostic refs are compact, do not copy the full body, and do not create ordinary panel/prompt context. They do not create worker delivery requests or authorize downstream work. For researcher→planner chains, the leader should review the researcher report and then create/assign a separate planner task or direct question.Task-based routing: when
taskIdis provided andtois omitted, leader messages route to the task owner; messages from the task owner route back toteam-lead. Unowned, missing, or ambiguous tasks return an error instead of falling back to broadcast.
✅ Leader-Gated Task Governance
Task facts are leader-gated. By default, only team-lead factually changes task.status, task.owner, task.blockedBy, title, or description. Planner is advisory by default, not a second leader: it can report findings and recommendations, while the leader decides what to create, assign, block/unblock, or close.
Non-leader task actions are memory/report-oriented:
agentteam_task action=noteappends task-local memory only. It does not notifyteam-lead, create mailbox/projection/attention side effects, or create linked communication notes. If someone needs to know, useagentteam_send.agentteam_task action=report_donefrom the task owner appends one primaryreport_donenote, creates a leader mailbox item, requests compact leader projection plus bounded leader attention, and leaves the task open until leader review. The leader closes accepted work withaction=close.agentteam_task action=report_blockedfrom the task owner appends one primary blocked report note, creates a high-priority leader mailbox item, requests compact leader projection plus bounded leader attention, and does not factually mutatestatusorblockedBy. Unread blocked reports appear as panel attention; after the report mailbox item is read, long-lived panel attention comes from factual blocked tasks (status/blockedBy) instead. The leader blocks/unblocks withaction=block blockedBy=[...]oraction=unblock.blockedByis a hard actionability gate: blocked tasks cannot receive actionableassignmentsends or worker delivery. Non-actionagentteam_sendcommunication such asinformandquestionremains allowed so the team can converge; done/blocked reports useagentteam_task.- In worker delivery prompts, same-task assigned task facts and task-bound mailbox messages are merged into one task-centric block so the instruction/question appears once; unscoped or different-task messages still appear separately in Messages.
Rollback/migration baseline remains npm pi-agentteam@0.5.0; do not treat local WIP versions as a stable runtime fallback.
👥 Built-in Roles
agentteam intentionally keeps a small fixed role set for predictable permissions and prompts.
🔬 researcher — read grep find ls + collab
Fact finding: relevant files, constraints, risks, and evidence-backed findings
📋 planner — read grep find ls + collab
Advisory planning for complex work: options, risks, dependencies, and acceptance criteria
🛠 implementer — read grep find ls bash edit write + collab
Focused code changes, checks, and validation evidence
collab =
agentteam_send+agentteam_receive+agentteam_task
⚙️ Model Configuration
npm/pi install does not create runtime config files. To assign models per subagent role, run:
/team config init
/team config show
/team config validate
/team config init creates ${PI_AGENTTEAM_HOME || ~/.pi/agent/agentteam}/config.json from the bundled config.example.json and refuses to overwrite an existing file. You can also copy config.example.json manually:
{
"agentModels": {
"planner": null,
"researcher": null,
"implementer": null
}
}
Set a role value to a pi model selector, preferably the fully qualified selector you use in pi (for example openai/gpt-5.3-codex or your configured alias). null, empty string, or a missing key means use the current default model. Configuration is role-level only (planner, researcher, implementer); per-member overrides and live model switching are intentionally not supported. Spawn output and /team member details show the effective launch model (model: <selector> or model: default). Changes apply only to future teammate spawns/respawns; existing workers keep the model they were launched with. The leader always uses your current session model.
Runtime state is stored under ~/.pi/agent/agentteam/ (teams/<team>/team.json, teams/<team>/inboxes/, teams/<team>/outbox.json, teams/<team>/runtime.json, sessions/, and worker-sessions/). config.json lives in the same directory. Set PI_AGENTTEAM_HOME for testing or temporary sandboxes; /team config show displays the effective path and role models.
🛠 Tools & Commands
Tools
| Tool | Description |
|---|---|
agentteam_create |
Create a new team |
agentteam_spawn |
Spawn a teammate (omit task for idle) |
agentteam_send |
Send typed communication to a specific teammate, an owned task, or explicit broadcast |
agentteam_receive |
Pull unread mailbox messages; this is the full-text read boundary; multi-message human output is compactly grouped while details keep full text |
agentteam_task |
Leader-gated shared tasks plus task-local note memory and owner-only report_done/report_blocked action requests |
Command
| Command | Description |
|---|---|
/team |
Unified local console for status, recovery, teammate removal, team deletion, and cleanup |
🏗 Architecture
Current boundary layout: api/app/adapters/core/runtime/state are explicit; removed root facades are not part of the package surface.
index.ts ← Extension entry point
├── api/ ← Pi-facing registration entrypoints for tools/commands composition
├── tools/ ← Thin tool registrations plus team/message/task/worker services, routing, and policy helpers
├── commands/ ← /team console command and runtime action handlers
├── hooks/ ← Thin hook registrations plus lifecycle/context services and tool guard
├── teamPanel/ ← Interactive console (layout, view model, input, actions)
├── types.ts ← Public vocabulary/types (Task, Message, Worker)
├── internalTypes.ts ← Internal persisted/runtime store shapes (not public API)
├── config.ts / agents.ts / session.ts / protocol.ts / policy.ts / renderers.ts
├── state/ ← Focused file-based stores (team, inbox, sessions, runtime, outbox, quarantine)
├── adapters/ ← Explicit runtime/tmux/bridge adapters used by hooks, tools, commands, and panel
│ ├── runtime/ ← Session attachment, team lookup, storage readiness, naming/spawn rules, runtime service
│ ├── bridge/ ← Bridge delivery/projection/lifecycle adapter surface
│ └── tmux/ ← Patchable tmux visibility adapter and team pane reconcile/cleanup
├── runtime/ ← Focused bridge/projection/outbox runtime internals; no top-level runtime facade
├── protocol.ts ← Message type defaults & wake hints
├── orchestration.ts ← Leader digest (coordination counters)
├── policy.ts ← Leader delegation policy
├── agents.ts ← Role discovery & agent loading
├── tmux/ ← Low-level tmux client, pane/window/process/label helpers
├── messageLifecycle.ts ← Mailbox delivered/read helpers
└── agents/ ← Bundled role prompts (markdown)
├── researcher.md
├── planner.md
└── implementer.md
Design Principles
- Removable — delete the folder and reload; no core modifications
- Observable — each teammate is a visible tmux pane you can watch
- Minimal prompt burden — role behavior in markdown, not inflated system prompts
- File-based state — JSON + lock files + atomic writes; no database
- Event-driven — teammates wake on actionable messages, not polling
✅ Checks & Release Readiness
npm test # unit/package smoke suites
npm run typecheck # tsc --noEmit
npm run check:boundaries # import/public-surface boundary guard
npm run check # test + typecheck + git diff --check + boundaries
npm run release:check # npm run check + npm pack --dry-run --ignore-scripts
npm run test:e2e # optional manual tmux smoke; requires real tmux/pi runtime
release:check is safe for local CI: it does not publish, install, tag, bump versions, or edit user settings. It intentionally does not run test:e2e because the e2e smoke requires a real tmux/pi environment and is best run manually in a clean PI_AGENTTEAM_HOME sandbox.
The package surface is intentionally explicit: package.json#files lists required top-level files plus api/, app/, adapters/, commands/, hooks/, core/, runtime/, state/, teamPanel/, tmux/, tools/, and bundled agents/. It does not use broad *.ts, and removed root facades/wrappers are explicitly excluded/guarded.
Current automated/source-level status: FULL PASS only after npm test, npm run typecheck, git diff --check, npm run check:boundaries, npm run check, and npm run release:check pass in the working tree. This is local validation, not publishing.
| Suite | Covers |
|---|---|
| Tools + state flow | create → spawn → send → receive → task lifecycle |
| Command | /team unified console |
| Protocol + orchestration | Wake defaults, leader digest injection |
| Panel rendering | Visual output across terminal widths |
| Delivery + permission guards | Role-based access control |
| Service unit helpers | Pure worker/message/task/context helper behavior |
🧪 Manual smoke checklist
These checks are release-readiness notes for the current working tree; they do not imply a package has been published.
- Current vNext layout sanity
- Fresh state should use
teams/<team>/team.json,teams/<team>/inboxes/<member>.json,teams/<team>/outbox.json,teams/<team>/runtime.json,sessions/session-<sha>.json, andworker-sessions/. - Active old layout files such as
state.json,mailboxes/,outbox-state.json,bridge-state.json,delivery-state.json, andleader-projection-state.jsonshould quarantine rather than load.
- Fresh state should use
- Package surface sanity
npm run release:checkshould finish withnpm pack --dry-run --ignore-scriptsonly; do not runnpm publish, do not bumpversion, do not tag/commit, and do not edit~/.pi/agent/settings.json.docs/remains local design notes andscripts/remains local development helpers; neither directory is included in the npm packagefileslist by default.
- Stable fallback remains documented
- Compare or roll back with npm
pi-agentteam@0.5.0when needed; do not treat unpublished local vNext work as a stable fallback.
- Compare or roll back with npm
- Internal delivery diagnostics sanity
- Evidence: unit coverage in
tests/suites/service-units.cjsfor expired/stale request handling, recovery, and no-resend behavior. These are runtime diagnostics, not public task/worker states.
- Evidence: unit coverage in
- PushMailbox failure evidence
- Evidence: unit coverage in
tests/suites/tools-state.cjsfor leader mailbox push failure warnings/details on non-leaderreport_doneandreport_blocked.
- Evidence: unit coverage in
- Bridge-only delivery remains in effect
- Confirm no tmux terminal-key fallback is used; mailbox read still happens only through
agentteam_receive.
- Confirm no tmux terminal-key fallback is used; mailbox read still happens only through
⚠️ Limitations
- Workers are separate visible
pisessions in tmux panes, but tmux is only the visible container/labels/reconcile/cleanup/debug layer. AgentTeam uses one bridge-only delivery policy: bridge requests/projection only, with no automatic fallback to terminal key injection. - Durable Outbox plus runtime adapter diagnostics are production delivery diagnostics (
outbox.json,outbox-diagnostics.json, andruntime.jsonsections for bridge lease, delivery request, leader projection, and leader attention state). Internal request/projection/attention lifecycles such as pending, claimed, submitted, started, completed, projected, or failed may appear only in diagnostics/details; inbox read state remains owned byagentteam_receive. - In diagnostics, the durable bounded-leader-attention Outbox effect kind is
leader_attention_requested. Legacy active persisted outbox effects usingleader_triage_requestedhave no compatibility path; they quarantine as unsupported legacy state instead of being normalized or executed. - Rollback/migration: pin or reinstall a rollback package version (for example npm
pi-agentteam@0.5.0) and respawn workers. There is no automatic in-process switch from bridge-only delivery to terminal transport; bridge unavailable appears as publicbusy/errorworker health with diagnostics. For manual smoke, use a cleanPI_AGENTTEAM_HOMEand respawn old workers so bridge leases exist. agentteam_task action=createcan includeownerwhen the responsible teammate is already clear; this assigns shared state only and does not send/wake by itselfagentteam_task action=noteis task-local memory only; it is not a leader notification channelagentteam_sendcan omittoonly whentaskIdsafely routes through an owned task; it never falls back to implicit broadcast- Passing
tasktoagentteam_spawnstarts work immediately; omitting it creates an idle teammate for latersend/taskfollow-up - State is local to one machine (no remote/distributed support)
- Requires tmux; Windows terminals not supported (WSL works)
📄 License
MIT © 2026 linys77