docs: move the agent tool docs to 4-implementation/agent-tools
This commit is contained in:
parent
df8a82bc33
commit
aa227a95c1
1 changed files with 94 additions and 83 deletions
91
docs/4-implementation/agent-tools/bash.md
Normal file
91
docs/4-implementation/agent-tools/bash.md
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# Bash execution tools
|
||||
|
||||
For the operator: this page covers the daemon as deployed and what the tools do
|
||||
around the edges. How an agent calls them is in the tools' own MCP descriptions.
|
||||
|
||||
Background shell execution via `hive-bash-daemon`. Tools land as
|
||||
`mcp__bash__<tool>` (the MCP server name is `bash`, not `hyperhive`).
|
||||
`nix/agent-modules/mcp.nix` registers bash into `services.hyperhive.agent.extraMcpServers`
|
||||
by default (`lib.mkDefault`, with `allowedTools = ["*"]`) — an `agent.nix`
|
||||
can override or drop the entry, so this is a default, not an
|
||||
unconditional grant. Even where the entry is present, the server is only
|
||||
actually rendered into an agent's claude config when the agent also
|
||||
holds the **`execution`** permission: `extra_server_required_permission` in
|
||||
`hive-agent/src/mcp_config.rs` suppresses it entirely without that
|
||||
permission, so an agent lacking `execution` gets no `mcp__bash__*` tools at
|
||||
all, not just an unused grant. The harness rewrites the config each turn,
|
||||
so a change applies at the next one. See "Relationship to the
|
||||
`execution` permission" below.
|
||||
|
||||
## Tools
|
||||
|
||||
Each tool's parameters and return values are in its own MCP description, which
|
||||
is what an agent reads at call time. This section says what the tools do around
|
||||
the edges.
|
||||
|
||||
- **`run`** submits a shell command (through `bash`) as a background task. Its
|
||||
stdout and stderr stream to `harness/bash-tasks/<id>.{out,err}`. When the
|
||||
task finishes, times out or its process errors, it surfaces as a todo in the
|
||||
agent's loose-ends, with the exit code and a pointer to the captured output.
|
||||
`run` waits up to 3 seconds (30 at most) for a result before it returns; a
|
||||
result delivered that way makes no todo. A caller-chosen `name` replaces the
|
||||
generated id. The daemon accepts the name again once its task has finished,
|
||||
and rejects it while the task is still pending or running.
|
||||
- **`status`** polls a task: its state (`pending`, `running`, `done`,
|
||||
`timed_out`, `interrupted` or `killed`), the exit code, the run time and the last
|
||||
4 KiB of each stream. A call that sees a finished task clears its completion
|
||||
todo, since the agent already has the result; in a narrow race both can still
|
||||
appear. A task marked `interrupted` had its process killed by a harness
|
||||
restart, and a best-effort todo is still made so the agent isn't blocked
|
||||
silently.
|
||||
- **`kill`** stops a running or pending task and returns without waiting. The
|
||||
completion surfaces as a todo like any other. It signals the task's whole
|
||||
process group, so children the shell started stop too: SIGINT by default,
|
||||
SIGKILL with `force`. The daemon cancels a task still pending before it
|
||||
starts, and the task ends as `killed`.
|
||||
|
||||
## Namespace note
|
||||
|
||||
`run` and `status` live in the `bash` MCP server, not `hyperhive`. The
|
||||
tool names in claude are `mcp__bash__run` and `mcp__bash__status`.
|
||||
hyperhive blocks the `Bash` built-in tool — all shell execution goes through
|
||||
this structured path so tasks get task-id tracking and structured output.
|
||||
|
||||
## Architecture
|
||||
|
||||
`hive-bash-daemon` is a single long-running process (one per agent
|
||||
container, systemd service in `nix/agent-modules/mcp.nix`) — no stdio
|
||||
bridge. It owns subprocess management, output file writing, todo delivery
|
||||
on the harness's in-agent socket, **and** serves the `run`/`status`/`kill`
|
||||
MCP tools directly over streamable-http on `services.hyperhive.agent.mcp.bashHttpPort`
|
||||
(declared in `services.hyperhive.agent.extraMcpServers.bash` as `{ type = "http"; url =
|
||||
...; }`). Same shape as the built-in `hyperhive` surface (`hive-mcp-http`)
|
||||
— claude reconnects to the stable URL every turn instead of respawning a
|
||||
stdio child, so there's no per-turn MCP re-registration race and no
|
||||
round-trip socket hop for tool calls.
|
||||
|
||||
### Completion as a todo (loose-ends v2)
|
||||
|
||||
When a bash task changes state, `hive-bash-daemon` upserts a single keyed
|
||||
todo (`key = task id`) on the harness's in-agent socket (`HIVE_AGENT_SOCKET`)
|
||||
— "running" at start, then the completion summary when it finishes. The
|
||||
summary change signals the harness turn loop directly (in-process, no broker
|
||||
round-trip), so the harness drives a turn for the agent to handle it via
|
||||
`get_loose_ends`, then clears the todo with `cancel_loose_end(kind: "todo", id: N)` (dials the
|
||||
in-container socket directly — no bash task involved, so clearing doesn't
|
||||
spawn another todo). Same mechanism the matrix daemon uses for
|
||||
unread rooms. An inline `wait_seconds` / `status` observation that already
|
||||
delivered the result instead clears the keyed todo, so no redundant
|
||||
loose-end follows.
|
||||
|
||||
## Relationship to the `execution` permission
|
||||
|
||||
`Permission::Execution` (in `Permission::DEFAULT`) is the real gate on bash:
|
||||
`extra_server_required_permission` (in `hive-agent/src/mcp_config.rs`)
|
||||
controls whether the `bash` MCP server reaches the agent's claude
|
||||
config at all, suppressing every `mcp__bash__*` tool
|
||||
when absent — not just leaving them unused. Its own `tools()` returns
|
||||
`&[]`: `mcp__bash__run`/`status`/`kill` live on the separate `bash` MCP
|
||||
server that `extra_server_required_permission` gates, not on the
|
||||
`mcp__hyperhive__*` allowlist `tools()` builds. Removing `execution`
|
||||
from an agent's permissions **does** remove bash availability.
|
||||
Loading…
Reference in a new issue