pi-multi-agent-mode

Codex-style collaboration for Pi: spawn_agent, followup_task, send_message, wait_agent, list_agents, and interrupt_agent. Named agent trees, configurable child model, history forks, mailboxes, and a packaged multi-agent-mode skill.

Packages

Package details

extensionskill

Install pi-multi-agent-mode from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-multi-agent-mode
Package
pi-multi-agent-mode
Version
0.1.0
Published
Sep 21, 2026
Downloads
195/mo · 15/wk
Author
kennyfrc
License
MIT
Types
extension, skill
Size
123.9 KB
Dependencies
1 dependency · 3 peers
Pi manifest JSON
{
  "extensions": [
    "./src/index.ts"
  ],
  "skills": [
    "./skills"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-multi-agent-mode

Codex V2's six collaboration tools, adapted to in-process Pi sessions. The model tool parameter is absent. The user selects the child provider and model in a config file.

Install

pi install npm:pi-multi-agent-mode

Then run /reload or restart Pi. The package ships the multi-agent-mode skill. Run /skill:multi-agent-mode <task> to load and submit it in one step.

Configure

Create ~/.pi/agent/extensions/pi-multi-agent-mode.json:

{
  "models": [
    { "provider": "hyper", "model": "deepseek-v4.1-flash" },
    { "provider": "opencode-go", "model": "deepseek-v4.1-flash" },
    { "provider": "novita", "model": "deepseek/deepseek-v4.1-flash" },
    { "provider": "neuralwatt", "model": "deepseek-v4.1-flash" }
  ],
  "agents": {
    "cyber": { "provider": "zro", "model": "dolly1-security" },
    "reviewer": {
      "provider": "zro", "model": "dolly1-security",
      "instructions": "Read only. Report findings; change nothing.",
      "tools": ["read", "grep", "ls"]
    }
  },
  "maxConcurrentAgents": 4,
  "maxDepth": 2
}

The pre-rename pi-subagents.json is still read when the new file is absent, so existing setups keep working without a change. A pre-array config that sets only provider and model is accepted as a one-entry pool.

These are also the defaults if the file is absent. The provider and model must exist in Pi's model registry. No credentials belong in this file; use Pi's normal provider setup. Use /reload after changing the config.

Named agent types

The optional agents map defines named agent_type values, each pinning one model. spawn_agent with agent_type: "cyber" runs that child on the pinned zro/dolly1-security model and does not advance the rotation cursor. A pinned model outside the models pool still fails over: when its run ends in an error, the child rotates into the pool starting at the pool's first entry (see Failover). Add the pinned model to models to control where its walk starts. default and worker are reserved and cannot be redefined. Names use lowercase letters, digits, underscores, or hyphens. An unavailable pinned model fails the spawn with a clear error instead of silently using the pool.

A role may also carry instructions (appended to the child prompt) and a tools allowlist (the pi analog to a Codex role sandbox). The allowlist is opt-in: a role without it keeps the parent's full inherited tool set. Top-level maxDepth caps nesting; it is undefined (unlimited, Codex V2 behavior) unless set. Codex's V1 default of 1 excludes grandchildren.

Model rotation

spawn_agent picks the next entry in models with a simple round robin. The cursor is a global file, ~/.pi/agent/pi-multi-agent-mode-cursor.json, so all Pi sessions on the machine advance one shared rotation, and it survives restarts. Entries whose provider/model is unavailable are skipped, so one dead backend cannot block spawning; every spawn fails only when the whole pool resolves to nothing. Each child keeps the model it was spawned with, including follow-ups. The cursor is written with atomic file replacement.

Failover

When a run ends in an error, the child switches to the next pool entry and continues the same task. The pool is walked once per run, so each entry is tried at most once. Failover attempts do not touch the rotation cursor. The walk covers every child, including a model pinned by agent_type and a per-spawn model: override; a starting model outside the pool begins at the pool's first entry.

Two guards keep the switch useful:

  • A candidate whose context window cannot hold the failed attempt's input is skipped.
  • A context overflow only fails over to a candidate with a strictly larger window. If none exists, the child reports the overflow error.

Aborts and interrupts never fail over. Pi's own retry runs first, so transient errors still get their in-place attempts before the pool takes over (default 3 at the provider level). The child reports the provider that actually served the final turn, and the engine stores it in the agent record, so follow-ups and restarts stay on that provider. Failed attempts stay in the transcript.

The configured pool applies to all new children, including full-history forks. It does not change the root model. A continued agent starts on the model and tool access saved in its record, then fails over into the pool if that run errors. The cap counts active children across the entire tree, including nested agents; it excludes the root.

Tool interface

? marks optional parameters. All six schemas reject extra fields.

Tool Parameters
spawn_agent task_name: string, message: string, agent_type?: string, fork_turns?: string, reasoning_effort?: string, model?: string
followup_task target: string, message: string
send_message target: string, message: string, interrupt?: boolean
close_agent target: string
resume_agent target: string
spawn_agents_on_csv csv_path: string, instruction: string, id_column?: string, agent_type?: string
wait_agent timeout_ms?: number
list_agents path_prefix?: string
interrupt_agent target: string

Spawn and fork

  • spawn_agent returns {task_name: "/root/review", nickname: null} before constructing the child. Construction or model failures arrive as reports.
  • task_name accepts lowercase letters, digits, and underscores. Names are unique under each parent. Reuse an agent with followup_task.
  • fork_turns accepts "all" (default), "none", or a positive integer string, such as "3". A turn starts at a user message. Forks use the current branch with compaction applied, and omit unfinished tool calls.
  • A fork is framed for the child. The child prompt says the copied messages are the parent's, not the child's own history, and a boundary entry marks where the parent's context ends. Otherwise the child's last assistant message is the parent's orchestration turn, and it continues that work instead of its task.
  • agent_type is an optional role label. default and worker always exist and behave the same. A name defined in the config's agents map pins that type's model (see Named agent types). The child inherits the parent's active tools, including extension tools such as web and image tools, plus its skill catalog. The removed explorer value is rejected rather than silently widened. Pass no agent_type unless you want a specific role or model.
  • Child sessions load workspace context files. They share the root's filesystem and working directory. This is not an OS sandbox.
  • Reasoning effort defaults to the parent's level. Overrides require an empty or partial fork. Pi accepts off, minimal, low, medium, high, xhigh, and max; Codex's none maps to off, and ultra maps to max. Pi clamps the result to the child model's supported levels.

Tool and skill inheritance

Every new agent captures its parent's active tool list at spawn. Nothing is withheld by role, so a research child has the parent's web, image, and file tools. This applies to empty forks too: fork_turns controls history, not tools. Each child reloads the files that own those tools, including builtin overrides, against its own Pi session. Calls to tools such as todo therefore use the child's session state, not a function tied to the parent.

The child also inherits deferred tools: these need select_tools before use. Other inactive tools stay blocked. An inherited extension cannot enable them. A nested child takes its own snapshot from its immediate parent. Follow-ups and reloads keep the saved tool limit; changing the root's active list does not widen an existing child.

File-based extensions that own commands are also reloaded as companions. This keeps hooks from those extensions, such as permission checks, in the child. Hook-only extensions with no tools or commands are not discoverable through Pi's public extension API. Child sessions have no terminal UI. Each loaded extension must support headless use and its own shutdown cleanup. Hooks cannot start independent child prompts at startup or while idle. New tasks must go through collaboration tools so the engine can track their slots.

Skills keep their parent catalog and file paths, with a visible skill list in the child prompt. The child reads skill files on demand.

Inline/SDK tools without a reloadable source file cause a clear spawn error. The extension never drops these tools or copies functions tied to the parent. Missing tool files or failed child startup produce an error report before any model call. An agent saved without a tool set re-inherits the root's current tools and skills when it is resumed. This covers records from before tool inheritance and records from the removed read-only mode.

Messaging and lifecycle

  • Targets accept canonical names such as /root/review, direct child names such as review, or internal agent IDs. Cross-branch messages use canonical names. send_message can address /root.
  • followup_task starts an idle agent or queues a task on a running agent. It keeps the existing transcript. It cannot target the root.
  • send_message queues information without starting an idle agent. Pi delivers it at a message boundary after pending tools, not mid-token. Steer from evidence: read the target's trace tail first, and read the file or artifact in question when the trace alone is not enough. Send on a condition (a gate clears, a defect appears, a lane must be handed back, a constraint could be violated), not on a schedule. If conflicts keep causing rebuilds or stale evidence, the skill calls for reducing parallel work, not more messages.
  • Each settled run sends one FINAL_ANSWER to its parent. Pi custom messages carry Message Type, Task name, Sender, and Payload. Reports wake idle parents; ordinary messages do not. Verify reports. They do not grant user permission.
  • wait_agent blocks until mailbox activity, user steering, cancellation, or timeout. Last resort: a wait says nothing about what a running agent is doing. Read that agent's trace tail instead, then steer it with send_message. Call this once with a short timeout and only when local work is done and nothing is left to read; do not loop it. A subagent with no agents of its own has nothing to wait for, and the engine returns at once. It returns {message, timed_out}, not the report body. Default: 30 seconds; minimum: 1 second; maximum: 1 hour. Smaller values are clamped; values above the maximum are rejected.
  • list_agents returns {agents: [{agent_name, agent_status, transcript_path}]}. The path is absent until a child session opens. Settled agents remain available. path_prefix filters a subtree, without a trailing slash. The root is listed as running while its tools are in use.
  • interrupt_agent returns {previous_status}. It interrupts the current turn without deleting the agent. Pi rejects self/ancestor interrupts from child tool calls to avoid deadlocks. Follow-ups can restart an interrupted agent. Interrupting an idle agent is a no-op.

Commands and the multi-agent-mode skill

  • /agents lists the team. /agents stop <task_name> interrupts one agent.
  • /skill:multi-agent-mode <task> loads and submits the packaged skill in one step, with no review prompt. Delegation is optional; one implementer can be the right choice. The skill checks shared inputs, output paths, test state, and resource limits before a spawn or follow-up. Work orders name who owns each resource and when to release it. Builds and tests use stable inputs. The root follows the same ownership rules as its children. Steers must come from trace evidence. When conflicts cost more than the split saves, reduce the team. Verify the integrated result before reporting done.
  • The extension injects no system reminders and defines no delegation toggle. The six tools are available whenever the extension loads, and the policy lives in the skill plus the tool descriptions. These resource rules are policy, not runtime locks. The concurrency cap always applies; it is a ceiling, not a target or a CPU, RAM, or disk budget.

Persistence and compatibility

Transcripts live under ~/.pi/agent/subagents/agents/<agent_id>/. Team records and unread child mailboxes live in ~/.pi/agent/subagents/teams/<root-session-id>.json. Records use atomic file replacement. Reload or shutdown interrupts active children, disposes their sessions, and suppresses completion wakes. After a restart, followup_task reopens an agent's transcript; stale tasks never start model calls on their own.

This replaces the old subagent{description,prompt,files,readOnly,resume} interface. Legacy run files are left untouched, but are not imported into the named-agent tree. Pass file paths in message and use followup_task to continue an agent. Agents saved by the removed read-only mode re-inherit the root's tools on their next run. The older async design document describes the previous interface; this README is the current contract.

Tool names and parameters follow Codex V2's tool schemas, except for model. The packaged multi-agent-mode skill adapts OpenAI's multi-agent instructions and mode instructions (Apache-2.0). Runtime choices follow Pi as described above, not Codex's wire protocol.

Checks

npm run check
npm test

Tests cover schemas, models, prompts, and history forks. They check mailbox races, interruption, shutdown, and persistence. Real Pi SDK tests use an offline scripted provider to check inherited tools, builtin overrides, deferred tools, guards, skill catalogs, nested agents, tool inheritance, and reloads. Tests make no live model calls.

Skill checks guard the policy text and its serial/parallel decision examples. They check skill loading and required wording. They do not prove that a model follows the policy or that the runtime locks resources.