pi-interactive-subagents-herdr

Interactive subagents for pi - spawn, orchestrate, and manage sub-agent sessions in Herdr

Packages

Package details

extension

Install pi-interactive-subagents-herdr from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-interactive-subagents-herdr
Package
pi-interactive-subagents-herdr
Version
1.0.1
Published
Sep 21, 2026
Downloads
360/mo · 31/wk
Author
jontstaz
License
MIT
Types
extension
Size
222 KB
Dependencies
0 dependencies · 3 peers
Pi manifest JSON
{
  "extensions": [
    "./pi-extension/subagents/index.ts"
  ]
}

Security note

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

README

pi-interactive-subagents

Async subagents for pi, running in Herdr panes. Spawn a sub-agent, keep working in the main session, and get the result steered back when it finishes. Fully non-blocking.

Herdr-only fork. See Acknowledgements for the upstream project, which also supports tmux, cmux, zellij, and WezTerm.

Installation

Prerequisite: Herdr — the extension runs subagents in Herdr panes, and requires HERDR_ENV=1 (i.e. run pi inside Herdr).

Install from npm via pi's package manager:

pi install npm:pi-interactive-subagents-herdr

Or install straight from the git repo:

pi install git:github.com/jontstaz/pi-interactive-subagents-herdr

Restart pi after installing. To update later:

pi update --extension npm:pi-interactive-subagents-herdr

To uninstall:

pi remove npm:pi-interactive-subagents-herdr

How it works

subagent() returns immediately. The sub-agent runs in its own Herdr pane — a split off the parent pi pane that never steals keyboard focus (--no-focus). A live widget above the input tracks every running sub-agent, and when one finishes, its result is steered into the main session as a notification that triggers a new turn.

╭─ Subagents ──────────────────────────── 2 running ─╮
│ 00:23  scout      active · bash 7m                 │
│ 00:45  scout-2    waiting 2m                       │
╰────────────────────────────────────────────────────╯

Spawn several in parallel — they run concurrently and steer results back independently as each finishes.

Panes are kept usable: Herdr has no window re-tiling, so each spawn splits the largest pane this extension owns (the parent pi pane plus its own subagent panes) — wide panes split right, tall/narrow panes split down. Parallel spawns converge on near-even tiling instead of collapsing into ever-narrower columns. The strategy lives in chooseSplitTarget in pi-extension/subagents/herdr.ts.

If your shell startup is slow and launch commands get dropped before the prompt is ready, raise the delay:

export PI_SUBAGENT_SHELL_READY_DELAY_MS=2500   # default: 500

Tools

Tool Description
subagent Spawn a sub-agent in a dedicated Herdr pane (async)
subagent_message Message a sub-agent by name — steers it if running, resumes its session if finished
subagents_list List available agent definitions
ask_question (sub-agent sessions only) Ask the orchestrator a question and wait for the reply

There is also a /subagent <agent> <task> command for spawning directly, plus roster inspection: /subagent list shows every available agent and /subagent info <agent> prints an agent's resolved frontmatter. Typing /subagent tab-completes subcommands and agent names.

Spawning

subagent({ agent: "scout", task: "Analyze the auth module" });
subagent({ agent: "worker", name: "dark-mode", task: "Implement the dark mode toggle" });
Parameter Type Default Description
agent string required Which agent to spawn (must be known and permitted)
task string required Task prompt
name string agent name Display name for the pane and widget. Must be unique — duplicates are auto-suffixed (scout, scout-2, …)
model string agent's model Override the model for this spawn
cwd string agent's cwd Working directory (see Role folders)

Messaging

subagent_message is addressed by name only. Names are unique per session and persist after a sub-agent finishes, so the same name works either way:

subagent_message({ name: "scout", message: "Also check the auth middleware" });
  • Running — the message is typed into the live pane (newlines flattened) and picked up at the next turn boundary. The call returns immediately; the eventual completion still arrives as a steer message.
  • Finished — the session is resumed with the message as the follow-up task, like a fresh spawn: fire-and-forget, always autonomous, result steered back later. The resumed run reclaims its original name.

Every spawn records name → session file in artifacts/<sessionId>/subagent-registry.json, so names stay addressable across pi restarts. A nested sub-agent that spawns children gets its own registry keyed by its own session id. Resume is refused with a clear error (listing known names) if the name isn't registered, the session file is gone, or the session predates sandboxed resume.

Resume replays the original sandbox. At spawn time the fully-resolved loadout — tool allowlist, backing extensions, model, thinking level, system prompt, spawn whitelist, cwd — is snapshotted to <session>.loadout.json. Resume rebuilds the exact same restricted process from that snapshot rather than relaunching unrestricted.

ask_question

A sub-agent can ask its orchestrator a single freeform question when requirements are ambiguous or a decision materially affects the work. The session stays open (parked as waiting) instead of exiting; the parent is notified with the sub-agent's name, replies via subagent_message({ name, message }), and the reply arrives as the sub-agent's next turn. Parallel questions are supported — each waiting sub-agent has its own name.

If the reply arrives while the sub-agent is still mid-turn, it is absorbed into the current turn — either way the question is marked answered and the session exits normally when the work is done. If the parent never replies, the pane stays open until a human closes it. Only available inside sub-agent sessions.

Bundled agents

Agent Model Tools Role
scout omniroute-coolify/glm/glm-5.3 read, grep, find, ls Fast read-only codebase recon
researcher omniroute-coolify/glm/glm-5.3 web_search, web_fetch, safe_bash + pinchtab skill Web research via the PinchTab browser, synthesized into a sourced brief
worker omniroute-coolify/glm/glm-5.3 read, write, edit, bash, web_search, web_fetch + spawning General implementer; may spawn scout, researcher, critic, planner, git-butler, scribe
critic omniroute-coolify/glm/glm-5.3 read, grep, find, ls Adversarial diff/code review — BLOCK / HOLD / CLEAR verdicts
planner omniroute-coolify/glm/glm-5.3 read, grep, find, ls Codebase-grounded, dependency-ordered implementation plans
git-butler omniroute-coolify/glm/glm-5.3 read, grep, find, safe_bash Git hygiene — dirty-tree forensics, commit slicing, conflict resolution
scribe omniroute-coolify/glm/glm-5.3 read, grep, find, write, edit Documentation from the actual diff — READMEs, docs, changelogs

All are autonomous (auto-exit: true) and carry their identity in the system prompt (system-prompt: append).

Custom agents

Place a .md file in .pi/agents/ (project) or ~/.pi/agent/agents/ (global). Discovery priority: project > global > package-bundled — a project-local file overrides a bundled agent with the same name.

---
name: my-agent
description: Does something specific
model: openrouter/z-ai/glm-5.3
thinking: medium
tools: read, edit, write, safe_bash, web_search
session-mode: lineage-only
auto-exit: true
---

You are a specialized agent that does X...

Frontmatter reference

Field Type Description
name string Agent name (used in agent: "my-agent")
description string Shown in subagents_list
model string Default model
thinking string minimal, low, medium, or high
tools string Strict tool allowlist. Built-ins: read, write, edit, bash, grep, find, ls. Extension-backed: web_search, web_fetch, safe_bash, video_extract, youtube_search, google_image_search. Only the extensions backing the listed tools are loaded into the child
subagent_agents string Comma-separated agent names this agent may spawn. Presence of this field grants the spawning toolset (subagent, subagent_message, subagents_list) and restricts spawn targets to the list. Omit it and the agent cannot spawn at all
skills string Comma-separated skill names to auto-load
session-mode string standalone (default), lineage-only, or fork — see below
system-prompt string append or replace: pass the body as the child's --append-system-prompt / --system-prompt. Omit and the body is prepended to the task prompt instead
auto-exit boolean Auto-shutdown when the agent finishes (see below)
interactive boolean Whether stall/recovery transitions wake the parent (see below)
cwd string Default working directory
disable-model-invocation boolean Hide from subagents_list; still spawnable by explicit name
cli string claude runs the agent via the Claude Code CLI instead of pi

session-mode

  • standalone — fresh session, no lineage link to the caller (default)
  • lineage-only — fresh session with parentSession linkage for discovery/fork UX, but no copied turns
  • fork — child session seeded with the caller's conversation context

auto-exit

With auto-exit: true, the session shuts down when the agent's turn ends — the agent just writes its final message and stops (there is no "done" tool). The last assistant message becomes the summary returned to the parent. Recommended for all autonomous agents.

Notes:

  • Manual input does not strand an auto-exit sub-agent. If a human types into the pane, the session still closes once that turn completes normally — only an escape/abort leaves it open.
  • Auto-exit is suppressed while work is in flight: the session parks as waiting instead of exiting when an ask_question is still unanswered, or when the agent's own child sub-agents are still running (a worker can stop after dispatching children and stays open until the last result returns).

interactive

Controls whether stalled/recovered status transitions send a steer message to the parent session. Defaults to the inverse of auto-exit: autonomous agents get stall pings; user-driven agents stay quiet (the user is already working in that pane — the widget still updates). Set explicitly to override.

Tool access control

Access is whitelist-only. Every sub-agent process is launched with --no-extensions (extension discovery disabled) and --tools <allowlist>; only the extensions backing the listed tools are loaded back in explicitly. There is no default toolset and no deny-list — an agent gets exactly what its frontmatter lists. The restriction survives resume via the loadout snapshot.

Spawns must name a known agent at every depth. A top-level session may spawn anything discoverable; a sub-agent may only spawn the agents in its subagent_agents list (enforced via PI_SUBAGENT_ALLOWED). There is no agentless spawn route, so a child can never escalate to a full-toolset profile by omitting its agent.

Extensions can register additional tools for sub-agents at runtime via registerToolExtension(name, path) on the __pi_interactive_subagents process global.

Role folders

cwd starts a sub-agent in a directory with its own config, so role-specific setups (CLAUDE.md, skills, extensions) apply:

project/
└── agents/
    ├── game-designer/   ← CLAUDE.md, .pi/…
    └── sre/             ← CLAUDE.md, .pi/…
subagent({ agent: "worker", cwd: "agents/sre", task: "Review the deployment pipeline" });

Set a per-agent default with cwd: in frontmatter.

Status widget & configuration

The widget tracks each sub-agent from a runtime activity snapshot written by the child: starting, active (turn/provider/tool work), waiting (open for input or another stage), stalled (no valid snapshot for too long), or running (fallback). Sub-agent sessions also show their own tools widget — toggle it with Ctrl+Alt+O. Completion messages expand with Ctrl+O.

Status display is configured via config.json in the extension directory (copy config.json.example; it's gitignored):

{
  "status": { "enabled": true }
}

Requirements

herdr   # then start pi from one of its panes

Acknowledgements

Forked from amosblomqvist/pi-interactive-subagents, the tmux fork of HazAT/pi-interactive-subagents, which originated the subagent architecture, the multi-multiplexer surface layer, and the status widget; its supervision features were inspired by RepoPrompt.

License

MIT