docs(#1251): split MCP tool docs into docs/tools/ sub-mds by feature
This commit is contained in:
parent
5ec1306c7b
commit
78a00d1258
6 changed files with 350 additions and 268 deletions
|
|
@ -5,9 +5,8 @@ claude has access to in return.
|
|||
|
||||
## The loop
|
||||
|
||||
Each agent harness (`hive serve`, with role picked from `$HIVE_ROLE`
|
||||
— `"agent"` for sub-agents, `"manager"` for the manager — one
|
||||
binary, not two) runs:
|
||||
Each agent harness (`hive serve`, role set via `$HIVE_ROLE` — always
|
||||
`"agent"`, one binary) runs:
|
||||
|
||||
1. Long-poll `Recv` on its socket. The host-side broker
|
||||
(`broker.rs::recv_blocking_batch`) returns immediately if there's
|
||||
|
|
@ -292,115 +291,74 @@ The harness ships an embedded MCP server (rmcp 1.7). Claude launches
|
|||
it as a stdio child via `--mcp-config`. The hyperhive socket name is
|
||||
`hyperhive`, so the tools land in claude as `mcp__hyperhive__<tool>`.
|
||||
|
||||
### Sub-agent tools
|
||||
Tool access is gated by tool groups (`HIVE_TOOL_GROUPS`). The default
|
||||
preset (`AGENT_DEFAULT`) includes `messaging`, `meta`, `inbox`, and
|
||||
`execution`. Privileged groups (`lifecycle`, `approvals`, `scheduling`,
|
||||
`diagnostics`) are opt-in via the P3RM1SS10NS tab.
|
||||
|
||||
- `send(to, body, in_reply_to?)` — message a peer (logical agent
|
||||
name), another agent, or the operator (recipient `operator`,
|
||||
surfaces in the dashboard inbox). Use `to: "<parent>"` to
|
||||
address the agent's topology parent without knowing its label;
|
||||
the broker resolves the sentinel at delivery time (falls back
|
||||
to `operator` for root agents). Optional `in_reply_to: i64`
|
||||
links this message to a prior message id for thread rendering
|
||||
in the dashboard message flow and the per-agent inbox.
|
||||
- `recv(wait_seconds?, max?)` — drain inbox messages. Without
|
||||
`wait_seconds` (or with `0`) returns immediately, a cheap
|
||||
"anything pending?" peek. Positive value parks the turn up
|
||||
to that many seconds (cap 180) — incoming messages wake
|
||||
instantly, otherwise returns empty at the timeout. `max`
|
||||
(default 1, server-side cap 32) drains up to N popped rows
|
||||
in one round-trip; `wait_seconds` applies to the *first*
|
||||
message, then the call drains up to `max` total.
|
||||
- `ask(question, options?, multi?, ttl_seconds?, to?)` —
|
||||
surface a structured question. Same shape as the manager's;
|
||||
recipient defaults to the operator (dashboard) but can be set
|
||||
to a peer agent name via `to: "<agent>"`. Answer routes back
|
||||
to the asker's own inbox as `HelperEvent::QuestionAnswered`
|
||||
via `coord.notify_agent`. For peer questions the recipient
|
||||
sees a `HelperEvent::QuestionAsked` event and replies with
|
||||
`answer(id, answer)`.
|
||||
- `answer(id, answer)` — respond to a `question_asked` event
|
||||
routed to this agent. Authorisation is strict: only the
|
||||
declared target (or the operator via the dashboard) can
|
||||
answer.
|
||||
- `get_loose_ends()` — list everything still pending against
|
||||
this agent: unanswered questions it asked / was asked, plus
|
||||
reminders it scheduled. Each row carries an id + kind for
|
||||
### Core tools (always available)
|
||||
|
||||
**Messaging** (`messaging` group): `send(to, body, in_reply_to?)`,
|
||||
`recv(wait_seconds?, max?)`, `ask(question, options?, multi?,
|
||||
ttl_seconds?, to?)`, `answer(id, answer)`.
|
||||
|
||||
- `send` — message a peer (logical name) or the operator
|
||||
(`to: "operator"`). Use `to: "<parent>"` to address the topology
|
||||
parent without hardcoding the label; the broker resolves the
|
||||
sentinel at delivery time. Optional `in_reply_to: i64` links the
|
||||
message to a prior id for thread rendering.
|
||||
- `recv` — drain inbox. Without `wait_seconds` (or `0`) returns
|
||||
immediately. Positive value parks the turn up to that many seconds
|
||||
(cap 180) — incoming messages wake instantly. `max` (default 1, cap
|
||||
32) drains up to N rows; `wait_seconds` applies to the first, then
|
||||
drains up to `max` total.
|
||||
- `ask` — surface a structured question to the operator (default) or
|
||||
a peer agent (`to: "<agent>"`). Non-blocking — returns a question
|
||||
id; the answer arrives as a `question_answered` system event in the
|
||||
asker's inbox. `options` is advisory; `multi=true` renders as
|
||||
checkboxes; `ttl_seconds` auto-cancels with answer `[expired]`.
|
||||
- `answer` — respond to a `question_asked` event routed to this
|
||||
agent. Strict authorisation: only the declared target can answer.
|
||||
|
||||
**Inbox** (`inbox` group): `get_loose_ends()`,
|
||||
`cancel_loose_end(kind, id)`, `remind(message, delay_seconds? |
|
||||
at_unix_timestamp?)`, `request_next_turn()`.
|
||||
|
||||
- `get_loose_ends` — list pending questions (asked/owed) and
|
||||
scheduled reminders. Each row carries an id + kind for
|
||||
`cancel_loose_end`.
|
||||
- `cancel_loose_end(kind, id)` — withdraw a `question`
|
||||
(posts `[cancelled by <self>]` to unblock the asker), a
|
||||
`reminder` (hard-delete before fire), or (manager only) an
|
||||
`approval` (transitions to `Cancelled`; sub-agents refused with a
|
||||
clear error). Sub-agents may only cancel rows they own.
|
||||
- `remind(message, due)` — schedule a reminder that lands in
|
||||
this agent's own inbox at a future time (sender shows as
|
||||
`reminder`). Large payloads spill to
|
||||
`/agents/<self>/state/reminders/` with the inbox message a
|
||||
short pointer. Each agent's pending-reminder count is capped
|
||||
(default 50, override via `HIVE_REMIND_MAX_PENDING_PER_AGENT`);
|
||||
scheduling a new one fails if the cap is already hit.
|
||||
- `set_status(text)` — set a free-text status string visible on
|
||||
the operator dashboard. Persisted to
|
||||
`{state_dir}/hyperhive-status`; survives harness restarts. Pass
|
||||
an empty string to clear. Validated: must be a single line and
|
||||
≤ 200 Unicode characters; the server rejects multi-line or
|
||||
over-length text with a clear error.
|
||||
- `get_agent_meta(name?)` — fetch identity + status metadata for
|
||||
an agent: `{ name, role, hyperhive_rev, running, status_text,
|
||||
status_set_at, hive_name?, swarm_name? }`. Pass `name` to query
|
||||
a peer (e.g. check whether a sub-agent is idle before sending it
|
||||
work). Omit `name` to get your own identity stamp — replaces the
|
||||
previous `whoami` tool. `running` is `true` when the container is
|
||||
up. When `running` is `false` the host clears `status_text` /
|
||||
`status_set_at` (they would be stale snapshots from before the
|
||||
container stopped) before serving the response. Status fields are
|
||||
also `None` when the target has never called `set_status` or has
|
||||
cleared it. `hive_name` and `swarm_name` are present when
|
||||
`services.hyperhive.hiveName` / `services.hyperhive.swarmName`
|
||||
are configured on the host; omitted in single-hive deployments.
|
||||
- `request_next_turn()` — ask the harness to start another turn
|
||||
immediately after this one ends, even if the inbox is empty. Use for
|
||||
multi-turn tasks (long builds, sequential steps) where you want to
|
||||
continue without waiting for an external message. The next turn starts
|
||||
with `from: "self"` and `body: "continue"`. No-op if new inbox
|
||||
messages arrive before this turn ends. No args.
|
||||
- `run(cmd, timeout_secs?)` — submit a shell command for
|
||||
background execution (`sh -c <cmd>`). Returns a task ID immediately;
|
||||
the command runs asynchronously in a harness-managed tokio task. Stdout
|
||||
and stderr stream to `harness/bash-tasks/<id>.{out,err}`. When the
|
||||
task completes (or times out, or the process errors), the harness wakes
|
||||
the agent with a summary body — handle on a future turn. Optional
|
||||
`timeout_secs`: pass a value for a deadline, or omit for no timeout
|
||||
(runs until natural exit). Requires the `execution` tool group.
|
||||
Exposed as `mcp__bash__run`.
|
||||
- `status(id)` — poll the status of a task submitted with
|
||||
`run`. Returns status (`pending`/`running`/`done`/`timed_out`/
|
||||
`interrupted`), exit code, run duration, and the last 4 KiB of stdout
|
||||
and stderr (full output in the `.out`/`.err` files). Tasks marked
|
||||
`interrupted` had their process killed by a harness restart; a best-
|
||||
effort wake was still sent so the agent is not silently blocked.
|
||||
Exposed as `mcp__bash__status`.
|
||||
- `cancel_loose_end` — withdraw a `question` (posts `[cancelled by
|
||||
<self>]`) or hard-delete a `reminder`. Agents may only cancel rows
|
||||
they own.
|
||||
- `remind` — schedule a reminder in this agent's own inbox. Large
|
||||
payloads spill to `/agents/<self>/state/reminders/`. Pending count
|
||||
capped at 50 per agent (`HIVE_REMIND_MAX_PENDING_PER_AGENT`).
|
||||
- `request_next_turn` — ask the harness to start another turn
|
||||
immediately after this one ends, even if the inbox is empty.
|
||||
Next turn fires with `from: "self"` and `body: "continue"`.
|
||||
|
||||
**Agent lifecycle + config tools** (direct children only; requires
|
||||
`lifecycle` or `approvals` tool group):
|
||||
**Meta** (`meta` group): `set_status(text)`, `get_agent_meta(name?)`.
|
||||
|
||||
- `kill(name)`, `start(name)`, `restart(name)`, `update(name)` — manage
|
||||
a direct child sub-agent (graceful stop, start, stop+start, rebuild).
|
||||
No approval required. Topology-enforced: `name` must be a direct child
|
||||
per `topology.json`. Server rejects all other agent names. Requires
|
||||
`lifecycle` tool group.
|
||||
- `list_containers()` — list all descendant containers with running
|
||||
status. Topology-enforced (descendants only). Requires `lifecycle`
|
||||
tool group.
|
||||
- `request_init_config(name, description?)` — step 1 of spawning a new
|
||||
direct child agent. Queues an `InitConfig` approval; on operator
|
||||
approve, hive-c0re seeds the proposed config repo with a default
|
||||
`agent.nix` template. `name` must be a direct child. Topology-enforced.
|
||||
Fails if config already exists. Requires `approvals` tool group.
|
||||
- `request_apply_commit(agent, commit_ref, description?)` — step 2 of
|
||||
spawning a new direct child (or updating an existing child's config).
|
||||
Submit a commit sha from the child's proposed config repo for operator
|
||||
approval. `agent` must be a direct child. Topology-enforced. `commit_ref`
|
||||
must be a 7-40 char hex sha. Requires `approvals` tool group.
|
||||
- `set_status` — set a free-text status string visible on the
|
||||
dashboard. Single line, ≤ 200 chars. Persisted to
|
||||
`{state_dir}/hyperhive-status`. Pass `""` to clear.
|
||||
- `get_agent_meta` — fetch identity + status metadata for an agent:
|
||||
`{ name, hyperhive_rev, running, status_text, status_set_at,
|
||||
hive_name?, swarm_name? }`. Omit `name` to query self.
|
||||
|
||||
### Privileged tools (by tool group)
|
||||
|
||||
- **Bash execution** (`execution`) — background shell tasks. See
|
||||
[`docs/tools/bash.md`](tools/bash.md).
|
||||
- **Lifecycle + config** (`lifecycle`, `approvals`) — manage child
|
||||
agents, spawn new ones, apply config commits. See
|
||||
[`docs/tools/lifecycle.md`](tools/lifecycle.md).
|
||||
- **Scheduling + diagnostics** (`scheduling`, `diagnostics`) —
|
||||
scheduled prompts, `get_logs`. See
|
||||
[`docs/tools/scheduling.md`](tools/scheduling.md).
|
||||
- **Matrix MCP + extra servers** — `mcp__matrix__*` tools and
|
||||
per-agent extra MCP config. See
|
||||
[`docs/tools/matrix.md`](tools/matrix.md).
|
||||
|
||||
### Waking the agent from inside the container
|
||||
|
||||
|
|
@ -411,170 +369,22 @@ socket at `/run/hive/mcp.sock`. Two equivalent paths:
|
|||
- **Shell out to `hive wake --from <label> --body <text>`**
|
||||
(use `--body -` to read body from stdin). Already on the
|
||||
container's `PATH` since the harness binary is in
|
||||
`systemPackages`. Convenient for shell-script integrations.
|
||||
Works for both `agent` and `manager` roles.
|
||||
`systemPackages`. Convenient for shell-script integrations and
|
||||
co-process daemons (matrix bridge, webhook listeners, scrapers).
|
||||
|
||||
- **Speak the wire protocol directly** — JSON-line over the
|
||||
unix socket: `{"cmd":"wake","from":"matrix","body":"new dm
|
||||
from @alice"}\n`. Same shape any other AgentRequest uses;
|
||||
from @alice"}\n`. Same shape as any other `AgentRequest`;
|
||||
see `hive-sh4re::AgentRequest::Wake`.
|
||||
|
||||
The wake event lands in the broker as `{from:<label>,
|
||||
to:<agent>, body}`, which wakes whatever `recv` call the
|
||||
harness is currently blocked on. Next turn fires with the
|
||||
wake prompt formed from that message — claude sees "from:
|
||||
matrix" (or whatever label) and reacts.
|
||||
to:<agent>, body}`, waking whatever `recv` call the harness
|
||||
is currently blocked on. The next turn fires with the wake
|
||||
prompt formed from that message.
|
||||
|
||||
Identity = socket: anything that can connect to
|
||||
`/run/hive/mcp.sock` is implicitly trusted to inject these,
|
||||
which is fine because the bind-mount is the agent's own
|
||||
container only.
|
||||
|
||||
### Built-in matrix MCP (`mcp__matrix__*`)
|
||||
|
||||
When `hyperhive.matrix.enable = true` (default) and the host-level
|
||||
matrix tuwunel is configured, the harness auto-injects `hive-matrix-mcp`
|
||||
as a second stdio MCP server. Tools land as `mcp__matrix__<name>`:
|
||||
|
||||
- `send_message(room, body)` — send a markdown message; `room` accepts
|
||||
`!id:server` or `#alias:server`, daemon resolves either
|
||||
- `send_dm(user_id, body)` — send a direct message to a matrix user
|
||||
- `send_reaction(room, event_id, key)` — react to a message
|
||||
- `send_reply(room, event_id, body)` — threaded reply
|
||||
- `mark_read(room, event_id)` — advance the read receipt
|
||||
- `list_rooms()` — enumerate joined rooms
|
||||
(`{ id, canonical_alias, name, member_count }` per room)
|
||||
- `list_room_members(room)` — members of a room
|
||||
- `read_room(room, limit?)` — recent timeline events
|
||||
|
||||
The daemon (`hive-matrix-daemon`) holds the long-running matrix-sdk
|
||||
`Client` + sync loop; the stdio bridge (`hive-matrix-mcp`) is spawned
|
||||
per turn and forwards tool calls over `/run/hive-matrix.sock`. Both
|
||||
silently exit when `<state>/matrix-token` is absent (account not yet
|
||||
provisioned). Incoming room events wake the agent via `AgentRequest::Wake`
|
||||
with `from: "matrix"` and a teaser body
|
||||
(`[matrix] <sender> in <room>: <first-100c>…` where `<sender>` is
|
||||
the matrix user id and `<room>` is the alias or id as reported by
|
||||
the SDK).
|
||||
|
||||
### Extra MCP servers (per-agent)
|
||||
|
||||
Each agent's NixOS config can declare additional MCP servers via
|
||||
`hyperhive.extraMcpServers.<key> = { command, args, env,
|
||||
allowedTools }`. The module writes the map to
|
||||
`/etc/hyperhive/extra-mcp.json`; the harness reads it at boot and
|
||||
merges every entry into `--mcp-config` (under `mcpServers.<key>`)
|
||||
and `--allowedTools` (as `mcp__<key>__<pattern>`). The agent's
|
||||
flake.nix forwards every flake input to `agent.nix` as the
|
||||
`flakeInputs` module arg, so external MCP-server flakes are pulled
|
||||
in by adding them to `inputs.*` and referenced as
|
||||
`flakeInputs.<name>.packages.${pkgs.system}.default` — the
|
||||
resolved sha lands in the agent's own `flake.lock` and rolls up to
|
||||
meta's.
|
||||
|
||||
### Manager tools (in addition to send/recv)
|
||||
|
||||
- `request_init_config(name, description?)` — first step of a
|
||||
two-step spawn. Queues an `InitConfig` approval (≤9 char name);
|
||||
on operator approve, hive-c0re seeds the proposed config repo
|
||||
with a default `agent.nix` template and sends the manager a
|
||||
`HelperEvent::ConfigReady { agent }`. The manager then edits
|
||||
`agent.nix`, commits the changes, and calls `request_apply_commit`
|
||||
with the commit sha — the first ApplyCommit on a freshly-init'd
|
||||
config creates the container. Fails if a proposed repo for this
|
||||
name already exists. (The operator can also direct-spawn an empty
|
||||
agent from the dashboard's `◆ R3QU3ST SP4WN` button, which routes
|
||||
via `HostRequest::RequestSpawn`.) Also available to agents for direct
|
||||
children only (requires `approvals` tool group; see agent lifecycle
|
||||
tools section above).
|
||||
- `kill(name)` — graceful stop. No approval required. Also available to
|
||||
agents for direct children only (requires `lifecycle` tool group; see
|
||||
agent lifecycle tools section above).
|
||||
- `start(name)` — start a stopped sub-agent. No approval. Also available
|
||||
to agents for direct children only.
|
||||
- `restart(name)` — stop + start. No approval. Also available to agents
|
||||
for direct children only.
|
||||
- `update(name)` — rebuild (re-applies the current hyperhive flake
|
||||
+ agent.nix, restarts). No approval, idempotent. Manager calls
|
||||
this on receipt of a `needs_update` system event. Also available to
|
||||
agents for direct children only.
|
||||
- `request_apply_commit(agent, commit_ref)` — submit a config
|
||||
change for any agent (`root` for the manager's own config) for
|
||||
operator approval. Also available to agents for direct children only
|
||||
(requires `approvals` tool group; see agent lifecycle tools section
|
||||
above).
|
||||
- `request_update_meta_inputs(inputs?, description?)` — queue an
|
||||
approval to run `nix flake update [inputs...]` on the meta flake.
|
||||
Pass specific input names (e.g. `["bitburner-agent"]`) or omit
|
||||
for all. Returns immediately; lock update runs on operator
|
||||
approval. Does NOT trigger rebuilds — call `update(name)` on
|
||||
affected agents after approval resolves.
|
||||
- `ask(question, options?, multi?, ttl_seconds?, to?)` —
|
||||
surface a structured question to the operator (default) or a
|
||||
sub-agent (`to: "<agent>"`). Non-blocking — returns the
|
||||
queued question id; the answer arrives later as
|
||||
`HelperEvent::QuestionAnswered { id, question, answer,
|
||||
answerer }` in the asker's inbox. Options always render
|
||||
alongside a free-text fallback; `multi=true` renders options
|
||||
as checkboxes. `ttl_seconds` auto-cancels with answer
|
||||
`[expired]` (and `answerer: "ttl-watchdog"`) after the
|
||||
deadline (useful for time-sensitive decisions that become moot
|
||||
if no one has responded). The operator can also manually
|
||||
cancel with `[cancelled]` via the dashboard.
|
||||
- `answer(id, answer)` — respond to a `question_asked` event
|
||||
that was routed to the manager (a sub-agent did
|
||||
`ask(to: "manager", ...)`). Surfaces in the asker's inbox as
|
||||
the same `question_answered` event.
|
||||
- `get_logs(agent, lines?)` — fetch recent journal lines for a
|
||||
sub-agent container (diagnose MCP-registration failures,
|
||||
startup crashes, etc.). Pass the plain logical agent name;
|
||||
hive-c0re resolves the machine name (`h-<name>`, manager
|
||||
`root`). `lines` defaults to 50, host-capped at 500.
|
||||
- `request_schedule_prompt(targets, body, first_fire_at_unix, interval_seconds?, description?)` —
|
||||
queue an operator-approval for a scheduled prompt. On approve,
|
||||
`body` is fanned out to each `targets` agent at
|
||||
`first_fire_at_unix`; recurring if `interval_seconds` is set,
|
||||
one-shot otherwise. Even self-targeted schedules go through
|
||||
approval (use `remind` for unapproved self-wake). Long downtime
|
||||
fires once per recurring row on resume (catch-up clamp).
|
||||
- `edit_schedule(id, body?, description?, interval_seconds?, next_fire_at_unix?, targets_add?, targets_remove?)` —
|
||||
partial-update a schedule. Pass only the fields to
|
||||
change; absent fields are left alone. `targets_add` / `targets_remove`
|
||||
mutate the recipient list in the same transaction; re-adding a
|
||||
previously-cancelled target drops its tombstone + history (fresh
|
||||
start). Clearing a scalar (e.g. `interval_seconds: null`) flips
|
||||
recurring→one-shot. Refuses cancelled rows. Same authorization as
|
||||
`cancel_schedule`.
|
||||
- `cancel_schedule(id, targets?)` — cancel a schedule. Omit
|
||||
`targets` / pass empty to cancel the whole schedule; pass a list
|
||||
to cancel just those recipients (auto-cancels when every target
|
||||
is removed). Authorization: manager can cancel schedules it owns
|
||||
or any owned by a sub-agent in its topology subtree.
|
||||
- `fire_schedule_now(id)` — fire a scheduled prompt out of band.
|
||||
Runs the per-target fan-out once immediately. Recurring schedules
|
||||
keep their cadence (the manual fire is additive); one-shot
|
||||
schedules are consumed by the fire and cancelled afterwards. Same
|
||||
authorization rules as `cancel_schedule`.
|
||||
- `list_schedules()` — snapshot every schedule (active +
|
||||
cancelled-but-not-reaped): id, owner, body, per-target
|
||||
`last_fired_at` + `last_result`, `next_fire_at_unix`,
|
||||
`interval_seconds`. Use to look up an id before cancelling or to
|
||||
audit upcoming wake-ups across the swarm.
|
||||
- `remind` / `get_loose_ends` / `cancel_loose_end` / `set_status`
|
||||
/ `get_agent_meta` — same as the sub-agent tools above.
|
||||
`get_loose_ends` scopes to the manager's own items by default;
|
||||
pass `agent: "*"` for a hive-wide view, or `agent: "<name>"`
|
||||
to inspect one agent.
|
||||
`cancel_loose_end` may cancel any agent's row.
|
||||
|
||||
The boundary: lifecycle ops on *existing* direct children
|
||||
(`kill`/`start`/`restart`/`update`) are discretionary — no operator
|
||||
approval required (manager can do so for any sub-agent; agents can do so
|
||||
only for direct children with `lifecycle` tool group). Creating a new
|
||||
agent (`request_init_config` → `request_apply_commit` for the first sha)
|
||||
and changing any agent's config (`request_apply_commit`) still go through
|
||||
the approval queue (same topology scoping for agents: direct children only
|
||||
with `approvals` tool group).
|
||||
`/run/hive/mcp.sock` is implicitly trusted to inject these —
|
||||
the bind-mount is the agent's own container only.
|
||||
|
||||
### Authoritative state
|
||||
|
||||
|
|
@ -604,7 +414,7 @@ status hint moved to the wake prompt + UI header.
|
|||
`web_tools` tool group is enabled — see P3RM1SS10NS tab).
|
||||
- Denied by omission or `claude-settings.json` deny list: `Bash`,
|
||||
`Task`, `NotebookEdit`, `TodoWrite`.
|
||||
- Allowed MCP tools: as listed above per flavor.
|
||||
- Allowed MCP tools: as listed above (by tool group).
|
||||
|
||||
`Bash` is disallowed — shell execution goes through
|
||||
`mcp__bash__run` (background tasks with structured output +
|
||||
|
|
|
|||
Loading…
Reference in a new issue