pi-agentteam

Multi-agent team orchestration for pi — leader-coordinator pattern with researcher, planner, and implementer teammates in tmux panes

Packages

Package details

extension

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.6.8
Published
Jun 4, 2026
Downloads
559/mo · 308/wk
Author
linys77
License
MIT
Types
extension
Size
646.8 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.

npm license pi


✨ 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 compact TaskMessageRef 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.

pi install npm:pi-agentteam installs the npm latest version. GitHub-only vNext notes in this README can appear before an npm publish is explicitly performed, so do not assume unreleased GitHub changes are available from npm until a package release is published. If v0.6.8 is promoted to npm, it may sync npm users from pi-agentteam@0.6.3 across several GitHub-only releases; see Package Surface Tiers for the release-notes-only compatibility posture.


🚀 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 researcherreport_done creates a durable TaskReport with files, facts, risks → leader receives/reviews → leader synthesizes
Plan a risky change Leader assigns researcher fact-finding first → researcher reports to leader → leader receives the inbox report and reviews task history/reports → 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 inbox text → inspect task history/reports when needed → 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
→ two-box master-detail console
→ tabs: Cockpit · Tasks · Mailbox · Members
→ Enter opens selected-item context actions
→ a opens team maintenance actions

The Cockpit tab is an interactive attention queue for active tasks and unread mailbox items, not a passive status box. The Tasks tab surfaces compact v0.6.2 history: latest TaskReport id/type/author/summary, latest TaskEvent/TaskMessageRef activity, and counts for reports/events/messageRefs. It does not hydrate full report text or task-bound message bodies; use agentteam_task action=report reportId=<id> or agentteam_receive for explicit full-text reads.

Not attached to a team:

/team
→ global two-box master-detail console
→ tabs: Teams · Panes
→ Enter opens selected-team/pane context actions
→ a opens global maintenance actions
Key Action
Tab / Shift+Tab Cycle tabs
1..4 Attached tabs: Cockpit, Tasks, Mailbox, Members
1..2 Global tabs: Teams, Panes
Move list selection, or scroll details when detail focus is active
/ e Move scroll focus from list to detail
/ Esc Return detail scroll focus to list; then collapse details or close
Enter Open selected-item context actions / choose action
a Open team/global maintenance actions
q Close

The panel intentionally does not focus tmux panes, perform task/message CRUD, or mark mailbox items delivered/read. 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 descriptions and compact history summaries remain readable without flooding terminal scrollback.

Action menus keep selected-item actions separate from maintenance and destructive operations. Sections render as SELECTED ITEM, MAINTENANCE, and DANGER ZONE; the footer shows the selected action description, and destructive confirmation defaults to No, Cancel operation.

Available action-menu operations include:

  • selected-item context actions such as inspecting details, recovering a selected team, deleting a selected team, or removing a selected teammate;
  • team/global maintenance actions such as refresh/reconcile, compact leader mailbox projection sync without marking messages read or delivered, deleting the current team, and cleanup of all agentteam state/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_done and report_blocked are task-report outcomes, not agentteam_send types. Non-leaders may use agentteam_task action=report_done or agentteam_task action=report_blocked only for tasks they own; non-owners should use inform or question for 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 compact TaskMessageRef audit/index rows (taskId, mailboxMessageId, sender/recipient/type/thread/summary metadata) and does not copy the message body into task history. Legacy task.notes are migrated into TaskReport/TaskEvent/TaskMessageRef history and removed from active state; new task-bound sends produce zero hidden communication-ref notes. /team now shows compact TaskReport/TaskEvent/TaskMessageRef summaries and counts instead of latest-note/folded-ref primary UI. Refs do not count as ordinary/latest notes and do not bump task recency.

Peer inform handoffs are mailbox communication plus compact TaskMessageRef 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 taskId is provided and to is omitted, leader messages route to the task owner; messages from the task owner route back to team-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 report/history-oriented:

  • agentteam_task action=report_done from the task owner creates a durable TaskReport, creates a compact leader mailbox notification, requests compact leader projection plus bounded leader attention, and leaves the task open until leader review. The leader closes accepted work with action=close.
  • agentteam_task action=report_blocked from the task owner creates a durable blocked TaskReport, creates a high-priority compact leader mailbox notification, requests compact leader projection plus bounded leader attention, and does not factually mutate status or blockedBy. 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 with action=block blockedBy=[...] or action=unblock.
  • agentteam_task action=progress records compact local TaskEvent progress/history only. It does not append legacy task-note rows, notify team-lead, create mailbox/projection/attention side effects, or create linked communication refs. If someone needs to know, use agentteam_send; use report_done/report_blocked for durable report artifacts/action requests.
  • blockedBy is a hard actionability gate: blocked tasks cannot receive actionable assignment sends or worker delivery. Non-action agentteam_send communication such as inform and question remains allowed so the team can converge; done/blocked reports use agentteam_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.

🔬 researcherread grep find ls + collab

Fact finding: relevant files, constraints, risks, and evidence-backed findings

📋 plannerread grep find ls + collab

Advisory planning for complex work: options, risks, dependencies, and acceptance criteria

🛠 implementerread 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 task facts plus TaskReport/TaskEvent/TaskMessageRef history queries; owner-only report_done/report_blocked create durable report 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

Package Surface Tiers

Packed runtime files are not all stable public API. The package intentionally has no restrictive exports map at this surface tier, so existing deep imports are not newly blocked yet, but only the surfaces below should be treated as stable promises.

  • Public/stable promises
    • Pi extension default entrypoint is package.json#pi.extensions pointing at ./index.ts; index.ts is the extension facade.
    • Public collaboration vocabulary and simple public shapes live in types.ts.
    • User-facing Pi tool/command schemas and behavior are the primary product API.
    • deliveryPolicy.ts bridge-only helpers document the supported delivery policy surface.
  • Compatibility/composition surfaces
    • api/tools.ts and api/commands.ts are extension composition helpers for wiring AgentTeam into a Pi extension; they are kept stable, but they are not a broad end-user API.
    • adapters/bridge/index.ts is a bridge runtime adapter compatibility surface for worker bridge composition, not a broad user API.
  • Internal/packed-for-runtime paths
    • app/, runtime/, state/, teamPanel/, commands/, hooks/, tmux/, most tools/, adapters/runtime/, and adapters/tmux/ are packed so the extension can run, not because every subpath is stable API.
    • package.json#files is a runtime packaging allow-list, not a promise that every packed subpath is stable API.
    • docs/ and scripts/ remain local-only and excluded from the package by default.

v0.6.8 npm sync compatibility note

If v0.6.8 is promoted to npm, npm latest may jump from pi-agentteam@0.6.3 to v0.6.8 after several GitHub-only releases. The package comparison against npm 0.6.3 is additive: 8 internal runtime/source files added and 0 packed files removed.

No root compatibility facades/wrappers were added: commands.ts, tools.ts, state.ts, tmux.ts, runtime*.ts, and runtimeWake.ts were not packed in npm 0.6.3 and remain absent. Adding those paths would expand the public-looking surface rather than restore npm 0.6.3 compatibility.

Stable/public entries remain present: index.ts, types.ts, deliveryPolicy.ts, api/tools.ts, api/commands.ts, and adapters/bridge/index.ts. Packed implementation dirs are included so the TypeScript Pi extension can run, but they are not all stable subpath APIs. Unsupported deep imports into internals may need adjustment.

Release notes are the compatibility path for v0.6.8. Targeted shims/wrappers are considered only with concrete external-user evidence for a specific broken import path that existed in npm 0.6.3; absent that evidence, AgentTeam will not add broad compatibility wrappers.

Public behavior remains behavior-preserving: agentteam_receive is the full-text/read boundary; /team stays compact/read-mostly and does not mark mailbox read/delivered; delivery stays bridge-only with no terminal-key fallback; AgentTeam does not add autopilot, hidden workers, worker-spawns-worker, automatic downstream task creation, or other downstream automation.

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, and worker-sessions/.
    • Active old layout files such as state.json, mailboxes/, outbox-state.json, bridge-state.json, delivery-state.json, and leader-projection-state.json should quarantine rather than load.
  • Package surface sanity
    • npm run release:check should finish with npm pack --dry-run --ignore-scripts only; do not run npm publish, do not bump version, do not tag/commit, and do not edit ~/.pi/agent/settings.json.
    • docs/ remains local design notes and scripts/ remains local development helpers; neither directory is included in the npm package files list by default.
  • Stable fallback remains documented
    • Compare or roll back with npm pi-agentteam@0.5.0 when needed; do not treat unpublished local vNext work as a stable fallback.
  • Internal delivery diagnostics sanity
    • Evidence: unit coverage in tests/suites/service-units.cjs for expired/stale request handling, recovery, and no-resend behavior. These are runtime diagnostics, not public task/worker states.
  • PushMailbox failure evidence
    • Evidence: unit coverage in tests/suites/tools-state.cjs for leader mailbox push failure warnings/details on non-leader report_done and report_blocked.
  • Bridge-only delivery remains in effect
    • Confirm no tmux terminal-key fallback is used; mailbox read still happens only through agentteam_receive.

⚠️ Limitations

  • Workers are separate visible pi sessions 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, and runtime.json sections 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 by agentteam_receive.
  • In diagnostics, the durable bounded-leader-attention Outbox effect kind is leader_attention_requested. Task-bound send indexing uses task_message_ref_append_requested. Legacy pending task_note_append_requested effects are migrated/cleaned before validation when possible; otherwise unsupported legacy state is quarantined. Legacy active persisted outbox effects using leader_triage_requested have 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 public busy/error worker health with diagnostics. For manual smoke, use a clean PI_AGENTTEAM_HOME and respawn old workers so bridge leases exist.
  • agentteam_task action=create can include owner when the responsible teammate is already clear; this assigns shared state only and does not send/wake by itself
  • agentteam_task action=progress records compact local TaskEvent progress/history only; it is not a leader notification channel and active team state has no legacy task-note rows
  • agentteam_send can omit to only when taskId safely routes through an owned task; it never falls back to implicit broadcast
  • Passing task to agentteam_spawn starts work immediately; omitting it creates an idle teammate for later send/task follow-up
  • State is local to one machine (no remote/distributed support)
  • Requires tmux; Windows terminals not supported (WSL works)

📄 License

MIT © 2026 linys77