hyperhive/docs/tools/subagent.md

4.6 KiB

Subagent tools

Spawns nested headless claude sessions via hive-subagent-daemon. Tools land as mcp__subagent__<tool> (the MCP server name is subagent, not hyperhive). Shipped default-on for every agent today — nix/agent-modules/mcp.nix always injects subagent into hyperhive.extraMcpServers (with allowedTools = ["*"]), same as bash. The operator's own framing: shipped default-on for now, expected to become a real opt-in capability later (not built yet).

See the base:claude-subagents skill for when to reach for this (mechanical, bounded batches) versus doing the work inline.

Tools

start(name, prompt_file, model?, trigger?)

Start a fresh subagent session under name, running in the background. Returns as soon as the process is confirmed running — not once it finishes.

  • name — session display name: claude's own --name/--resume session title, and this daemon's tracking key while the process is alive. [a-z0-9-], max 63 chars. Reusable once a prior session under that name has finished; refused while one is still running.
  • prompt_file — path to a file passed as --append-system-prompt-file, the subagent's actual task instructions. A file, not an inline string, to avoid ARG_MAX on a large recipe.
  • model--model for the subagent's own claude invocation. Omit for claude's own default.
  • trigger — written to the subagent's stdin as its first turn's prompt. Defaults to a generic "carry out your instructions" nudge.

A prior finished session under the same name is archived first (renamed .jsonl.archived, not deleted) — a real fresh start, not a silent resume of old history.

Exposed as mcp__subagent__start.

continue(name, prompt, model?)

Give an existing named session a new turn — whether that means "the previous turn finished, here's a follow-up instruction" or "the daemon restarted, reattaching to a session that survived it independently." Returns as soon as confirmed running, same as start. Refused for a name with no session on disk at all, or one currently running.

  • name — the existing session's name (from a prior start).
  • prompt — the new turn's prompt.
  • model--model for this turn; doesn't have to match whatever start used.

Exposed as mcp__subagent__continue.

interrupt(name, force?)

Signal name's currently-running process. Only works while it's actually running — there's no queued/pending state to cancel pre-emptively.

  • force: false (default) — SIGINT, letting claude shut down cleanly if it's mid-response.
  • force: true — SIGKILL.

Exposed as mcp__subagent__interrupt.

Always runs with --dangerously-skip-permissions --strict-mcp-config (no --mcp-config override — a safety property, not a knob).

Checking on a subagent

There's no status tool. A subagent's own claude session — not a parallel log this daemon writes — is the record of what it did; read that the same way you'd catch up on any other agent, by asking it directly (continue with a prompt). The daemon pushes exactly one todo per session lifetime: when a turn finishes, its completion summary lands via get_loose_ends like any other producer's todo. continue on a name that's still running is refused (with that as the tell it's still going) rather than queuing behind it.

Architecture

hive-subagent-daemon (own crate, hive-subagent-mcp) is independent of hive-bash-daemon — a subagent spawns a full nested claude process, a materially heavier capability than a bash command, worth its own deployable/restartable unit. Own systemd unit, own streamable-http listener on hyperhive.mcp.subagentHttpPort.

No task files. The daemon's only state is an in-memory map of currently-running processes (name -> Cancel), live only as long as the process is — a restart stops whatever's running rather than adopting it. The durable record of a subagent's existence is claude's own on-disk session, found again by name via hive_claude::SessionStore; that's what continue reattaches to, restart or not.

No mid-turn compaction. Built on hive_claude::Claude::spawn + RunningClaude::wait directly, not InfiniteSession::run — the latter has no cancel handle to reach in from the outside, which is what would make interrupt a no-op. The trade: a turn that overflows the context window surfaces as a plain error instead of self-healing via reactive compaction. Subagents are meant to be bounded, single-batch work (see the base:claude-subagents skill), not sessions long-lived enough to need in-place compaction — a real follow-up if that assumption stops holding.