Skip to content

megamen32/agent-herder

v0.2.2MIT

Coordinate and supervise parent/child sessions across Claude, Codex, OpenCode, ZCode, Fast Agent, Hermes, and Qoder with MCP messaging, TTL coordination notes, session inspection, and autopilot.

Agent Herder

MCP control center for coding agents — and the missing inter-agent messenger.

Monitor, inspect, and coordinate AI sessions — and message them — from one MCP server: OpenCode, Claude Code, Codex CLI, Qoder, ZCode, Fast Agent, and existing ChatGPT conversations. Sessions keep living in their own harnesses; Agent Herder gives them a shared control plane, a shared presence ledger, and a shared inbox.

Русский · 简体中文

Agent Herder website →

Animated Agent Herder session lineage

Build from source

Use Node.js 22.12+ and Git. The package is not currently available from the public npm registry; build the public source instead:

git clone https://github.com/megamen32/agent-herder.git
cd agent-herder
npm ci
npm run build
AGENT_HERDER_WEB_PORT=18787 npm start

The command enables the loopback web server on port 18787. Open the web UI at http://127.0.0.1:18787/ and connect an MCP client using its Streamable HTTP server setting:

{
  "mcpServers": {
    "agent-herder": {
      "url": "http://127.0.0.1:18787/mcp"
    }
  }
}

Keep one server process per host; clients connect to that running instance.

Start the harness you want to observe first. For OpenCode, that means:

opencode serve

OpenCode 2.x servers serve their JSON API under /api behind Basic auth; Agent Herder detects that protocol automatically (OPENCODE_URL, plus OPENCODE_SERVER_PASSWORD when the server sets one) and keeps supporting older unprefixed servers. Messages reach a running OpenCode 2 turn natively through its inbox (delivery: steer), so active-turn coordination needs no plugin hook.

What it actually does

One control plane, three layers.

1. Observe — every session, every harness, one list

  • Running / idle / stopped / waiting sessions across OpenCode, Claude Code, Codex CLI, Qoder, ZCode, and Fast Agent.
  • Liveness you can trust: a hook-fed lifecycle registry observes real session events (start, turn start, turn end, session end) and beats the stale status that task indexes keep for interactive sessions. Recency heuristics are the fallback, observed state is the truth.
  • Parent/child lineage without guessing IDs, raw transcript export with a navigation card, worktree audits, model inventory.

2. Message — agents talk to agents (and to you)

  • send_message delivers into a target session with queue, steer, or sync semantics — and wakes it up. A parked ZCode session would otherwise never execute a queued prompt; Agent Herder resumes the target so the message actually runs.
  • fromSessionId / fromHarness wrap every delivery in a reply header: who sent this and the exact call to answer. No id hunting.
  • Idle interactive sessions that reject direct prompts are auto-resumed on delivery.
  • Unfinished turns survive an Agent Herder restart. This is a separate, opt-out feature from autopilot: it is enabled by default, records only a turn that actually started, and continues the same harness/session/model sequentially, including after the provider cache expires. Cache rollover and pin transfer default off; a new summarized session requires an explicit Autocontinue setting. Missing resume support never creates a replacement while rollover is disabled. Disable continuation globally with AGENT_HERDER_UNFINISHED_AUTOSTART=false or use the Web UI's separate Autocontinue master, harness, and per-session switches.
  • respond_permission answers tool-permission requests remotely — this is how headless agents get unstuck while nobody is watching.

Verified live: two headless ZCode sessions created, tasked with a conversation, exchanging multiple messages each through send_message, and finishing with CHAT-DONE — zero human input after the initial kick.

Screenshots

Live web UI against real workloads — several harnesses, dozens of parallel sessions, one board.

Session roster — every harness, one list Session roster: running agents across workspaces with autopilot toggles, durations, and a message composer per session.

Session detail — chat, autopilot, controls Session detail: conversation view, autopilot switch, stop/visualize controls, and a message composer.

Statistics — real activity patterns Statistics: 805 sessions sampled, 11.1k write events, harness and model mix, token coverage, and session-volume histograms measured from real coding sessions.

3. Coordinate — repo boards, only-new-information injections

Every workspace gets a coordination board keyed by the git repo that owns the touched files. A session editing across three repos appears on three boards.

  • Auto-reserve on file activity: harness hooks report each edited file; the board records who touches what. Conflicts with another agent's paths come back as a soft-lock warning before the edit lands.
  • Peers roster: on every file edit the hook may inject "other agents recently active in this repo, and how to contact them".
  • Task declaration: a session that has not declared what it is working on receives a one-line directive to publish a working note — so a pair of agents never trip over each other silently.
  • Session-end purge: when a session wraps up, its Stop hook drops its leases and presence from every board immediately. Dead agents disappear from rosters instead of haunting them until a TTL expires.
  • Injection dedup: every injection channel (turn-start notes, file-activity rosters, delivered messages) shares one per-session, per-board signature slot. A session only ever receives a block when the roster materially changed — TTL refreshes and id churn are invisible — or after a staleness window (AGENT_HERDER_INJECTION_RESHOW_MS, default 45 minutes) that covers context compaction.

Manual notes work too: coordination_note_create with a TTL, editable and deletable by the author, auto-pruned on expiry.

Supported harnesses

HarnessConnectionEnablement
OpenCodeHTTP API (auto-detects the v2 /api protocol and the legacy one); Autopilot from native turn events with the autopilot_set toolEnabled by default; run opencode serve
Claude CodeSDK/CLI, current and legacy session files, native /autopilot + Stop pluginEnabled by default
Codex CLINative app-server with CLI fallback, plugin Stop judgeEnabled by default
Qoder CLINative ACPSet ENABLE_QODER=true
ZCodeLocal stdio ZCode Protocol app-server, native Stop/SessionStart/UserPromptSubmit/PreToolUse/PostToolUse/SessionEnd hooksEnabled by default
ChatGPTBrowserClaw-owned ChatGPT pageExisting conversations are resumable sessions; no automatic chat creation
Fast AgentPersisted session home + CLI resume/sendSet ENABLE_FAST_AGENT=true and FAST_AGENT_HOME

Core MCP tools

GroupTools
Discoverlist_agents, agent_info, session_identity, audit_worktrees
Lineage and transcriptfind_parent, list_children, export_transcript
Named sessionscreate_session, new_or_resume (OpenCode, Codex, and ZCode); existing ChatGPT chats are addressed by sessionId or title + /home/roomhacker/.chatgpt with create=never
Controldeliver (activation policy + queue/sync), send_message, resume_agent, stop_agent; ChatGPT supports delivery/resume but not stop/create yet
Coordinationcoordination_note_create, coordination_note_list, coordination_note_get, coordination_note_update, coordination_note_delete
Permissions, models and quotasrespond_permission, set_permissions, list_models, change_model, model_quotas

model_quotas reads GLM Coding Plan usage from ANTHROPIC_AUTH_TOKEN (or ZAI_API_KEY / GLM_API_KEY), MiniMax Token Plan usage from MINIMAX_API_KEY, and Codex usage from the local Codex login. Missing or unavailable sources return unknown; values are never guessed. new_or_resume accepts an ordered fallbackModels list and switches only after a provider's specific quota rejection before message admission. Generic HTTP 429s, unknown or accepted admissions, and manual stops never start a second attempt.

Session identity

A session Agent Herder creates knows its own name, native id and workspace from its first turn: Herder publishes them into the session's own instructions (OpenCode 2 agent.herder.identity entry), so the agent can answer "who am I" and use the right authorSessionId for coordination notes without being told in the prompt. session_identity reads that identity for any session and, with announce=true, publishes it to a session created outside Herder. Harnesses without a native identity channel report that honestly instead of pretending.

ChatGPT resume semantics

Agent Herder treats an existing ChatGPT /c/... conversation on its one owned BrowserClaw page as a resumable session. ChatGPT does not have a filesystem working directory, so Herder uses the stable local identity directory /home/roomhacker/.chatgpt for named-session matching. Prefer the stable Herder sessionId when titles are duplicated.

resume_agent with a message and deliver(..., create=never) reopen the existing conversation on the same owned page, write to its composer, and continue that conversation. The adapter does not create a new ChatGPT conversation when a named target is missing. working=true maps to Herder running; otherwise the conversation is idle.

For ChatGPT data access there are two complementary transports: the token driver in chatgpt-cdp-mcp is the fast backend/session-token read path, while BrowserClaw/CDP is the mutation/UI path used for resume and delivery. Both can read; the distinction is transport capability, not a global ChatGPT read-only limitation.

Operationally, the current Mac app is named BrowserOS neo (bundle id com.browseros.BrowserClaw), not the older BrowserClaw display name. Agent Herder reaches it through the localhost-only SSH tunnel 127.0.0.1:39479 → Mac 127.0.0.1:9010; internal Mac BrowserClaw ports may change. If the Mac is sitting at loginwindow, macOS cannot start the GUI browser from SSH. Herder retries ChatGPT adapter activation periodically, so once the user GUI session is available and BrowserOS neo starts, ChatGPT sessions appear without restarting Herder.

Architecture notes

  • Singleton daemon. One Agent Herder process per host holds the state and serves the web UI plus MCP over HTTP (AGENT_HERDER_WEB_PORT, default loopback 18787). Clients connect directly to /mcp using Streamable HTTP. The plugin defaults to http://127.0.0.1:18787/mcp; it starts no process. Fleet nodes use their own local port 18789: configure their client or installed plugin URL as http://127.0.0.1:18789/mcp. On Macs, 18787 can be an existing forward to100 and must not be used as the local node URL. The stdio bridge remains available only for explicit legacy consumers; it is not the Agent Herder default.
  • ZCode adapter. Talks the native ZCode Protocol app-server (length- framed channel protocol, zcode-agent / zcode-task namespaces), and attributes every protocol call to the right workspace (workspaceKey).
  • ZCode plugin (integrations/zcode/agent-herder-autopilot): native hooks for SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop, and SessionEnd — feeding lifecycle and file-activity events — plus the autopilot Stop judge (continue the session, ask the human via a durable choice registry, or wrap up and purge).
  • Codex plugin (.codex-plugin): native Stop judge with the same continue-or-notify contract.
  • Claude Code autopilot is packaged under .claude-plugin/: /autopilot toggles the exact current session, the native Stop hook asks the shared AI judge to continue or finish, and ambiguous decisions appear as NoticePlace/web buttons. See the autopilot guide.

Requirements

  • Node.js 22+ and npm.
  • At least one supported harness installed and available in PATH.
  • OPENAI_API_KEY for Codex when the Codex app-server requires it.

Configuration

The common switches are:

VariableDefaultPurpose
ENABLE_OPENCODEtrueEnable the OpenCode adapter
ENABLE_CLAUDEtrueEnable the Claude Code adapter
ENABLE_CODEXtrueEnable the Codex adapter
ENABLE_QODERfalseEnable the Qoder ACP adapter
ENABLE_ZCODEtrueEnable the local ZCode app-server adapter
ENABLE_FAST_AGENTfalseEnable the read-only persisted fast-agent observer
OPENCODE_URLhttp://127.0.0.1:4096OpenCode server URL
CODEX_TRANSPORTapp-serverCodex native transport or cli fallback
ZCODE_SERVER_NODE / ZCODE_SERVER_ENTRY~/.zcode/server/… when presentZCode stdio app-server runtime
ZCODE_BIN / ZCODE_ARGSzcode / ["app-server"]Fallback command when the bundled server entrypoint is unavailable
ZCODE_TASKS_INDEX_DB~/.zcode/v2/tasks-index.sqliteCross-workspace discovery source for ZCode sessions
AGENT_HERDER_COORDINATION_NOTES~/.local/state/agent-herder/coordination-notes.jsonShared coordination board store
AGENT_HERDER_INJECTION_RESHOW_MS2700000Re-inject unchanged rosters after this staleness window
AGENT_HERDER_AUTO_TTL_SECONDS60Auto-reserved file-activity lease TTL
AGENT_HERDER_UNFINISHED_RECONCILE_INTERVAL_MS60000Local reconciliation interval for proven interrupted turns; recovery does not invoke MiniMax
AGENT_HERDER_UNFINISHED_UNKNOWN_TTL_CHECK_MS240000Candidate delay when the provider/model cache TTL is unknown
AGENT_HERDER_UNFINISHED_MAX_TTL_CHECK_MS600000Maximum candidate delay for documented long-TTL models such as current Codex GPT-5.6+
AGENT_HERDER_UNFINISHED_CACHE_MARGIN_MS60000Safety margin subtracted from short cache TTLs before classification
AGENT_HERDER_UNFINISHED_RESUMES_PER_CYCLE8Bounded parallel continuation admissions per cycle; all resumed workloads still share the server-100 user-slice budget
AGENT_HERDER_UNFINISHED_INVENTORY_HOURS48Inventory window for explicit audit; does not authorize native recovery
AGENT_HERDER_UNFINISHED_EVIDENCE_MESSAGES200Maximum recent semantic messages read per session before fair shared-budget packing; the first user goal and latest user/model tail are always retained
AGENT_HERDER_UNFINISHED_BATCH_MAX_TOKENS16384Per-request output ceiling for planning and reconciliation; chunk size scales with this budget (32 sessions at the default, 16 at 8192)
AGENT_HERDER_UNFINISHED_BATCH_CONCURRENCY3Maximum simultaneous planner calls, capped at three; managed server-100 uses one to preserve shared provider capacity
CODEX_APP_SERVER_SOCKET—Join the existing managed Codex daemon through its Unix WebSocket endpoint so Desktop and Herder share native thread/turn control
AGENT_HERDER_UNFINISHED_JUDGE_ANTHROPIC_BASE_URLhttps://api.minimax.io/anthropicDirect MiniMax Anthropic-compatible classifier endpoint; avoids an extra gateway hop
AGENT_HERDER_UNFINISHED_JUDGE_PROTOCOL / AGENT_HERDER_UNFINISHED_JUDGE_BASE_URL / AGENT_HERDER_UNFINISHED_JUDGE_TOKEN_FILEanthropic / provider default / —Select an OpenAI-compatible direct judge and load its credential from an operator-owned file without copying it into tracked configuration
AGENT_HERDER_UNFINISHED_JUDGE_MODELMiniMax-M3.1-FlashDefault classifier model; the Web UI runtime selection overrides it and reads MINIMAX_API_KEY from the protected service environment
AGENT_HERDER_UNFINISHED_BATCH_TIMEOUT_MS600000Timeout for explicit semantic audit; its result cannot authorize recovery
AGENT_HERDER_UNFINISHED_BATCH_SESSIONS_PER_REQUESTderived from output limit, up to 32Optional independent cap for sessions in one semantic-planner request; keeps evidence batches small when a forced-thinking provider needs a larger output allowance
AGENT_HERDER_UNFINISHED_JUDGE_REASONING_EFFORTprovider defaultOptional OpenAI-compatible reasoning effort (low, high, or max); use low for bounded JSON classification on forced-thinking GLM models
AGENT_HERDER_UNFINISHED_JUDGE_ENABLEDtrueEnable MiniMax for explicit semantic audit only, not crash recovery
AGENT_HERDER_CODEX_STATE_CACHE_MS60000Share one persisted Codex rollout scan across dashboard, observation, and recovery callers
AGENT_HERDER_CACHE_HANDOFF_ENABLEDtrueMake cache handoff available; replacement also requires the persisted rolloverExpiredCache opt-in, which defaults off
AGENT_HERDER_HANDOFF_MODELMiniMax-M3.1-FlashDirect MiniMax model used only to summarize stale sessions; Fast Agent is the fallback when MINIMAX_API_KEY is absent
AGENT_HERDER_CACHE_TTL_MINUTES{}JSON exact overrides such as {"zcode:provider/model":30}; unknown provider TTLs are never guessed
AGENT_HERDER_UNFINISHED_DISCOVERY_IDLE_MS60000Explicit inventory audit delay; crash recovery does not scan unfinished tasks
AGENT_HERDER_WEB_PORT—Serve the web UI + MCP over HTTP (singleton daemon mode)
AGENT_HERDER_HTTP_TOKEN—Required when the web host is non-loopback
AGENT_HERDER_TRANSCRIPT_ARCHIVE_DIR.agent-herder/transcriptsRelative archive path inside the MCP process CWD

Autocontinue restores only interrupted native turns in the same session. Its crash-recovery path consumes durable, correlated failure evidence and never starts replacement chats. When the durable Autopilot policy enables Codex or ZCode, its 48-hour LLM inventory also becomes a background, same-ID backlog sweep for only those harnesses; each unfinished chat resumes separately. With Autopilot disabled, explicit inventory audit remains read-only.

Web settings expose failure and disconnect recovery independently, plus a separate opt-in stalled-turn timeout. Normal completion, running sessions, human input/approval, human stops, non-retryable admissions and native Codex subagent threads block recovery. See crash recovery for details.

The chat toolbar is capability-aware: every supported harness shows Autopilot, and harnesses with proven same-session crash recovery also show Autocontinue. Codex and ZCode therefore expose both independent controls. Both global settings remain available from the automation menu, and exact-session switches live in the session inspector.

For remote ZCode sessions, Autocontinue also recognizes the durable SSH-loss tuple: the remote task index still says running, while the newest root turn ended as cancelled and no explicit human-stop receipt exists. This remains a same-ID recovery and does not invoke the LLM. Autopilot separately judges normally completed work and the 48-hour backlog.

Organize current chats

The bundled chat-triage skill keeps current Codex and ZCode tasks visible and removes only proven completed or superseded pins. It joins explicit owning parents, children, and replacement aliases rather than deduplicating titles. A bounded Python planner holds unknown, active, queued, or incomplete scope and requires replacement pin readback before removing an original pin. Cleanup preserves conversations and does not start or stop sessions.

Codex plugin installations discover the skill automatically. For a source installation, run python3 skills/chat-triage/scripts/install.py to add the Codex skill and ZCode /chat-triage command without changing autopilot hooks. Native pin capabilities vary; the skill documents supported desktop/adapter routes and reports a precise blocker when a route is unavailable.

Develop locally

npm ci
npm test
npm run build
npm run inspect

The managed singleton entrypoint is dist/index.js. Connect harnesses to its HTTP /mcp endpoint; do not launch it once per client. The legacy dist/http-mcp-stdio.js shim is optional and is not in the default plugin wiring.

Advanced: web UI and persistent ACP

The optional web UI runs on loopback:

export AGENT_HERDER_WEB_PORT=8787
npm start

Open http://127.0.0.1:8787/. For a persistent ACP profile, set ACP_AGENT_COMMAND, ACP_AGENT_ARGS as a JSON array, and ACP_AGENT_PROFILE before starting the server. Set AGENT_HERDER_WEB_PORT to the loopback upstream expected by your reverse proxy (the managed agent.bezrabotnyi.com deployment uses 18787). The matching user-service template is deploy/systemd/agent-herder.service.

The managed server-100 service has a measured steady working set of roughly 170 MiB and a 1 GiB soft / 2 GiB hard RAM control-plane budget. Persistent adapter app servers, interactive sessions, MCP descendants, and health jobs run in independent transient systemd scopes, so their memory cannot throttle the supervisor that observes and resumes them. Failed native turns are resumed on the same session/model with bounded exponential backoff (three attempts by default); Herder never forks or switches providers during automatic recovery. The transient scopes still inherit server-100's outer per-workload and UID guards. Run no more than one heavy suite per agent and raise budgets only from fresh measurements while preserving the host reserve documented by ServersAdministartion.

The server-100 continuity drop-in is session-continuity.conf. It joins the existing managed Codex daemon and limits MiniMax planning to one request with a 4096-token output reservation (eight sessions per chunk). On 2026-10-05 the same tiny API probe returned overloaded_error at 16384 and succeeded at 8192 and 4096; the production planner also returned a validated small plan after the numeric confidence contract was clarified. Global input packing and coverage validation remain enforced.

New automated sessions have a separate web setting, Запуск новых сессий, and GET/PUT /api/automation/launch-policy. Its persisted allowlist, preferred harness and per-harness models control each automated launch. Missing or invalid policy fails closed; an empty allowlist disables launch. The current operator selection is Codex/ZCode, preferred Codex, using the selected native models. This policy does not change existing-session continuation toggles or switch a running chat to another harness.

The same policy holds optional projectRoutes: an ordered harness list per canonical project root, with an optional per-route model override. A route is used only for an explicitly configured project; every other project keeps the default launch path. Herder advances down the list only after a definite pre-admission failure (unavailable, quota_exhausted, pre_admission_rejected). An accepted launch and an unknown admission both stop the chain, so a semantic repair failure, a pending human answer or an ambiguous admission can never produce a second executor. POST /api/automation/project-launch is the single consumer that performs the launch: it walks the route, records every attempt with a stable native input id in project-launch-attempts.json, and reports the selected harness plus a human-readable routing reason. When the project already has a live session on another harness it returns mode: "handoff_required" for the caller to use the existing context-preserving handoff; it never clones a running session silently.

Restart continuation settings are available at GET/PUT /api/session-autostart and GET/PUT/DELETE /api/session-autostart/sessions/{harness}/{sessionId}. PUT /api/session-autostart persists recoverOnFailure, recoverOnDisconnect, watchdogEnabled and timeout controls. Omitted recovery flags preserve existing settings for older clients. Stored cache-rollover preferences are preserved but cannot authorize a replacement chat from crash recovery. Herder-created Codex, ZCode, and OpenCode sessions receive native full access before their first task. Existing manual sessions retain their permission policy; outstanding requests still wait for the user. Completed assessments remain closed while semantic evidence is unchanged, including across terminal events and status/title/time changes. New user work reopens assessment; a stopped snapshot alone does not authorize a prompt. Autocontinue and Autopilot are separate top-level Web UI settings and never toggle each other. The independent durable state lives under AGENT_HERDER_AUTOPILOT_STATE_DIR by default. Recovery is sequential, retries three times with persisted exponential backoff, never forks or changes the model/provider, and emits a Russian health.degraded Notice Place incident only after the retry budget is exhausted.

FAQ

Does Agent Herder replace my coding agent? No. It connects your MCP client to the sessions owned by OpenCode, Claude Code, Codex, Qoder, ZCode, or Fast Agent — and adds the messenger layer between them.

Do agents need the herder MCP to receive messages? No. Delivery goes through the harness itself (native prompt injection). The herder MCP on the agent side is only needed to send and to manage notes.

How do unattended sessions get tool access? Herder requests native full access at creation: ZCode uses yolo, Codex uses approvalPolicy: never with danger-full-access, and OpenCode uses a per-session allow-all ruleset. This applies to new Herder-created sessions. Existing manually created sessions keep their policy and can still require respond_permission.

Does export_transcript load everything into the model? No. It writes the raw source to a CWD-scoped archive and returns only the permanent navigation card.

Can I use only one harness? Yes. Disable adapters you do not run with the ENABLE_* variables.

License

MIT

BrowserOS neo 0.49.3.1 currently bundles BrowserClaw server 0.0.26 (migrations through m0013). On 2026-09-08 the local BrowserClaw DB had m0014–m0016 applied by a newer server while those migration files were absent from 0.0.26, causing the embedded server to exit and proxy 9010 to return 503. After backing up the DB, the three empty/new schema changes were rolled back (skills, skill_runs, skill_run_marks, and empty tasks.task_summary), preserving historical sessions/dispatches; PRAGMA integrity_check returned ok. DB backup: /Users/roomhacker/.gptadmin/file-backups/browserclaw-db-20260908-052917.