# hive-runtime The layer an agent's turns are driven through: one `Runtime` interface (`run`, `compact`, `archive`, `canceller`, `choices`) with a backend per runtime. - **claude** — `claude --print` through the `hive-claude` crate's `InfiniteSession`. A pass-through: same spawn, same session handling, same errors. - **acp** — any [Agent Client Protocol](https://agentclientprotocol.com) agent, spawned from a command, args and env handed to it (`RuntimeSpec`, read from `HIVE_RUNTIME` / `HIVE_ACP_COMMAND` / `HIVE_ACP_ARGS` / `HIVE_ACP_ENV`). It knows no agent by name; which agent runs, and how it is configured, is decided in nix (`services.hyperhive.agent.runtime`, `services.hyperhive.agent.acp.*`). Both backends report a turn through `hive_claude::Sink` in claude's `stream-json` shape. The ACP backend translates `session/update` notifications into it (text and thought chunks as whole blocks, tool calls as `tool_use` + `tool_result`, MCP tools named `mcp____`), so the harness's stream consumers read either backend unchanged. Context usage comes from ACP `usage_update`. The crate depends on no hyperhive binary crate, so `hive-agent` and `hive-subagent-mcp` can both drive turns through it. ## ACP backend: what it needs from the agent - `mcpCapabilities.http` in its `initialize` response. The hyperhive tools are only served over HTTP, so an agent without it is refused at startup. - `loadSession`, to pick its session back up after a harness restart. Without it every restart starts a new session. ## ACP backend: stopping a turn A turn is stopped with `session/cancel`: by the `Canceller` handle, or by the idle watchdog once no `session/update` has arrived for `Config::idle_timeout`. An agent that has not answered the prompt 10s later is killed, and the next turn respawns it. A watchdog stop fails the turn with `AcpError::IdleTimeout` (`IdleKilled` if the agent was killed). This is the only way a provider error the agent retries without reporting it, such as an HTTP 429, ends the turn. ## ACP backend: compaction The same `CompactionPolicy` as the claude backend decides when: after a turn past the watermark, or on `compact` (the operator's `/compact`, the agent's `compact` tool). - If the agent advertises a `compact` command (`available_commands_update`), it is sent as the prompt `/compact` on the same session, as the ACP spec runs any advertised command. A proactive compaction runs the policy's checkpoint turn first, as on claude. - Otherwise the policy's checkpoint turn runs, then the session is archived, and the next turn starts a new one, carrying the system prompt again. - A `compact` command that fails, or sends nothing for 180s (the turn's idle window if that is shorter), is cancelled and handled as the case above; the checkpoint turn is not run a second time. So a compaction always leaves a smaller session behind, and a failed one is not retried on the next turn. ## ACP backend: model and effort Before each prompt, `Config::model` and then `Config::effort` are set on the session with `session/set_config_option`, as the value of its first `model` and `thought_level` config option. A value the session does not offer, or already holds, is not sent, so a claude alias such as `haiku` does nothing on an ACP agent. Model goes first because the effort levels on offer depend on it. The `Choices` handle (`Runtime::choices`) reads what the session offers now, including after a `config_option_update`. It is empty until a session is attached.