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
|
|
@ -354,6 +354,8 @@ docs/
|
||||||
web-ui/agent.md (header, terminal, composer,
|
web-ui/agent.md (header, terminal, composer,
|
||||||
inbox, live view, per-agent endpoints, stats)
|
inbox, live view, per-agent endpoints, stats)
|
||||||
turn-loop.md claude invocation, wake prompt, MCP tool surface
|
turn-loop.md claude invocation, wake prompt, MCP tool surface
|
||||||
|
tools/ per-group tool docs (bash.md, lifecycle.md,
|
||||||
|
scheduling.md, matrix.md)
|
||||||
approvals.md approval flow, manager policy, helper events
|
approvals.md approval flow, manager policy, helper events
|
||||||
persistence.md sqlite dbs, retention, state dir layout
|
persistence.md sqlite dbs, retention, state dir layout
|
||||||
terminal-rendering.md per-agent terminal row taxonomy (as built)
|
terminal-rendering.md per-agent terminal row taxonomy (as built)
|
||||||
|
|
|
||||||
49
docs/tools/bash.md
Normal file
49
docs/tools/bash.md
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
# Bash execution tools (`execution` tool group)
|
||||||
|
|
||||||
|
Background shell execution via `hive-bash-mcp`. Tools land as
|
||||||
|
`mcp__bash__<tool>` (the MCP server name is `bash`, not `hyperhive`).
|
||||||
|
Enabled for any agent whose tool groups include `execution` — the
|
||||||
|
default preset (`AGENT_DEFAULT`) includes it.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
### `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).
|
||||||
|
|
||||||
|
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` — set when done
|
||||||
|
- run duration
|
||||||
|
- 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`.
|
||||||
|
|
||||||
|
## Namespace note
|
||||||
|
|
||||||
|
`run` and `status` live in the `bash` MCP server, not `hyperhive`. So
|
||||||
|
the tool names in claude are `mcp__bash__run` and `mcp__bash__status`.
|
||||||
|
The `Bash` built-in tool is blocked — all shell execution goes through
|
||||||
|
this structured path so tasks get task-id tracking and structured output.
|
||||||
|
|
||||||
|
## Tool whitelist cross-reference
|
||||||
|
|
||||||
|
`mcp__bash__run` and `mcp__bash__status` are unconditionally in
|
||||||
|
`--allowedTools` whenever the harness spawns claude (they are not
|
||||||
|
gated by the `execution` group at the `--allowedTools` level — the
|
||||||
|
group only gates whether the MCP server registers the tools at all).
|
||||||
91
docs/tools/lifecycle.md
Normal file
91
docs/tools/lifecycle.md
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
# Lifecycle and approvals tools
|
||||||
|
|
||||||
|
Two tool groups govern agent lifecycle management and config changes.
|
||||||
|
Both are scoped to **direct children only** (topology-enforced: the
|
||||||
|
server rejects any name that is not a direct child of the calling
|
||||||
|
agent per `topology.json`). Privileged agents (e.g. ruth) may operate
|
||||||
|
on any sub-agent — the topology scope applies to all others.
|
||||||
|
|
||||||
|
## `lifecycle` tool group
|
||||||
|
|
||||||
|
No operator approval required. Direct children only.
|
||||||
|
|
||||||
|
### `kill(name)`
|
||||||
|
|
||||||
|
Graceful stop. Container state is preserved; recreating the agent
|
||||||
|
reuses prior config and credentials.
|
||||||
|
|
||||||
|
### `start(name)`
|
||||||
|
|
||||||
|
Start a stopped sub-agent.
|
||||||
|
|
||||||
|
### `restart(name)`
|
||||||
|
|
||||||
|
Stop + start in one call.
|
||||||
|
|
||||||
|
### `update(name)`
|
||||||
|
|
||||||
|
Rebuild: re-applies the current hyperhive flake + `agent.nix`,
|
||||||
|
then restarts. Idempotent — safe to call repeatedly. Used in response
|
||||||
|
to `needs_update` system events.
|
||||||
|
|
||||||
|
### `list_containers()`
|
||||||
|
|
||||||
|
List all **descendant** containers (children + their subtrees) with
|
||||||
|
running status. Topology-scoped to descendants only.
|
||||||
|
|
||||||
|
## `approvals` tool group
|
||||||
|
|
||||||
|
Config changes and new-agent spawns route through the operator
|
||||||
|
approval queue. Direct children only (topology-enforced).
|
||||||
|
|
||||||
|
### `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 at `/agents/<name>/config/agent.nix` with a default template and
|
||||||
|
delivers a `config_ready` system event. Then edit `agent.nix`, commit,
|
||||||
|
and call `request_apply_commit` with the commit sha — the first
|
||||||
|
`ApplyCommit` on a freshly-init'd config creates the container.
|
||||||
|
|
||||||
|
Fails if a proposed config repo for `name` already exists.
|
||||||
|
`name` is ≤ 9 characters. The operator can also spawn an empty agent
|
||||||
|
via the dashboard `◆ R3QU3ST SP4WN` button, which routes via
|
||||||
|
`HostRequest::RequestSpawn`.
|
||||||
|
|
||||||
|
### `request_apply_commit(agent, commit_ref, description?)`
|
||||||
|
|
||||||
|
Step 2 of spawning (or updating an existing child's config). Submit a
|
||||||
|
commit sha from the child's proposed config repo for operator
|
||||||
|
approval. On approve, hive-c0re rebuilds the container with the
|
||||||
|
pinned commit.
|
||||||
|
|
||||||
|
`commit_ref` must be a 7-40 char hex sha (branch/tag names are
|
||||||
|
rejected — the approval pins the exact commit). `agent` must be a
|
||||||
|
direct child. Topology-enforced.
|
||||||
|
|
||||||
|
### `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
|
||||||
|
/ pass `[]` for all inputs. Returns immediately; the lock update runs
|
||||||
|
on operator approval.
|
||||||
|
|
||||||
|
Does NOT trigger container rebuilds — call `update(name)` on affected
|
||||||
|
agents after the approval resolves.
|
||||||
|
|
||||||
|
## Boundary summary
|
||||||
|
|
||||||
|
| Operation | Requires approval? | Scope |
|
||||||
|
|---|---|---|
|
||||||
|
| `kill` / `start` / `restart` / `update` | No | Direct children |
|
||||||
|
| `list_containers` | No | All descendants |
|
||||||
|
| `request_init_config` | Yes (InitConfig) | New direct child only |
|
||||||
|
| `request_apply_commit` | Yes (ApplyCommit) | Direct children |
|
||||||
|
| `request_update_meta_inputs` | Yes (MetaUpdate) | Meta flake (global) |
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
- [`docs/approvals.md`](../approvals.md) — full approval flow, kinds,
|
||||||
|
helper events (`config_ready`, `approval_resolved`), flake.lock
|
||||||
|
validation.
|
||||||
62
docs/tools/matrix.md
Normal file
62
docs/tools/matrix.md
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
# Matrix MCP tools and extra MCP servers
|
||||||
|
|
||||||
|
## Built-in matrix MCP (`mcp__matrix__*`)
|
||||||
|
|
||||||
|
When `hyperhive.matrix.enable = true` 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>`:
|
||||||
|
|
||||||
|
### Messaging
|
||||||
|
|
||||||
|
- `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_reply(room, event_id, body)` — threaded reply to a specific
|
||||||
|
event
|
||||||
|
- `send_reaction(room, event_id, key)` — react to a message with an
|
||||||
|
emoji key
|
||||||
|
|
||||||
|
### Reading
|
||||||
|
|
||||||
|
- `read_room(room, limit?)` — recent timeline events
|
||||||
|
- `list_rooms()` — enumerate joined rooms
|
||||||
|
(`{ id, canonical_alias, name, member_count }` per room)
|
||||||
|
- `list_room_members(room)` — members of a room
|
||||||
|
|
||||||
|
### Receipts
|
||||||
|
|
||||||
|
- `mark_read(room, event_id)` — advance the read receipt
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
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>…`).
|
||||||
|
|
||||||
|
See [`docs/matrix.md`](../matrix.md) for the homeserver setup,
|
||||||
|
provisioning flow, and federation config.
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
`allowedTools` defaults to `["*"]`, which expands to
|
||||||
|
`mcp__<key>__*` (every tool from that server auto-approved). Restrict
|
||||||
|
to specific tool names when you want finer control.
|
||||||
68
docs/tools/scheduling.md
Normal file
68
docs/tools/scheduling.md
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
# Scheduling and diagnostics tools
|
||||||
|
|
||||||
|
## `scheduling` tool group
|
||||||
|
|
||||||
|
Scheduled prompts fan a message body out to one or more agent inboxes
|
||||||
|
at a future time, optionally recurring. All scheduling ops go through
|
||||||
|
the operator approval queue (even self-targeted schedules — use
|
||||||
|
`remind` for unapproved self-wake). Authorization for read/cancel/edit
|
||||||
|
ops: you can act on schedules you own or any owned by a sub-agent in
|
||||||
|
your topology subtree.
|
||||||
|
|
||||||
|
### `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 agent in `targets` at
|
||||||
|
`first_fire_at_unix` (Unix timestamp). Recurring when `interval_seconds`
|
||||||
|
is set, one-shot otherwise.
|
||||||
|
|
||||||
|
Catch-up clamp: if hive-c0re is down across multiple intervals, only
|
||||||
|
ONE delayed fire happens on resume (per recurring schedule). The
|
||||||
|
skipped-cycle count surfaces in the per-target `last_result` for
|
||||||
|
audit.
|
||||||
|
|
||||||
|
### `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 and starts fresh. Clearing
|
||||||
|
`interval_seconds` to null flips recurring → one-shot. Refuses
|
||||||
|
cancelled rows (terminal state).
|
||||||
|
|
||||||
|
### `cancel_schedule(id, targets?)`
|
||||||
|
|
||||||
|
Cancel a schedule. Omit `targets` / pass empty to cancel the whole
|
||||||
|
schedule; pass a list to cancel just those recipients (the schedule
|
||||||
|
auto-cancels when every target is removed).
|
||||||
|
|
||||||
|
### `fire_schedule_now(id)`
|
||||||
|
|
||||||
|
Fire a scheduled prompt out of band immediately. Recurring schedules
|
||||||
|
keep their cadence — the manual fire is additive. One-shot schedules
|
||||||
|
are consumed by the manual fire and cancelled afterwards.
|
||||||
|
|
||||||
|
### `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.
|
||||||
|
|
||||||
|
## `diagnostics` tool group
|
||||||
|
|
||||||
|
### `get_logs(agent, lines?)`
|
||||||
|
|
||||||
|
Fetch recent journal lines for a sub-agent container. Useful for
|
||||||
|
diagnosing MCP-registration failures, startup crashes, plugin install
|
||||||
|
errors, or any harness issue you can't see from inside the container.
|
||||||
|
|
||||||
|
Pass the plain logical agent name (e.g. `"gui"`) — hive-c0re resolves
|
||||||
|
the machine name (`h-<name>`). `lines` defaults to 50, host-capped at 500.
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
- `remind` (no-approval self-wake path) — documented in
|
||||||
|
[`docs/turn-loop.md`](../turn-loop.md).
|
||||||
|
- [`docs/approvals.md`](../approvals.md) — approval flow for
|
||||||
|
`request_schedule_prompt`.
|
||||||
|
|
@ -5,9 +5,8 @@ claude has access to in return.
|
||||||
|
|
||||||
## The loop
|
## The loop
|
||||||
|
|
||||||
Each agent harness (`hive serve`, with role picked from `$HIVE_ROLE`
|
Each agent harness (`hive serve`, role set via `$HIVE_ROLE` — always
|
||||||
— `"agent"` for sub-agents, `"manager"` for the manager — one
|
`"agent"`, one binary) runs:
|
||||||
binary, not two) runs:
|
|
||||||
|
|
||||||
1. Long-poll `Recv` on its socket. The host-side broker
|
1. Long-poll `Recv` on its socket. The host-side broker
|
||||||
(`broker.rs::recv_blocking_batch`) returns immediately if there's
|
(`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
|
it as a stdio child via `--mcp-config`. The hyperhive socket name is
|
||||||
`hyperhive`, so the tools land in claude as `mcp__hyperhive__<tool>`.
|
`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
|
### Core tools (always available)
|
||||||
name), another agent, or the operator (recipient `operator`,
|
|
||||||
surfaces in the dashboard inbox). Use `to: "<parent>"` to
|
**Messaging** (`messaging` group): `send(to, body, in_reply_to?)`,
|
||||||
address the agent's topology parent without knowing its label;
|
`recv(wait_seconds?, max?)`, `ask(question, options?, multi?,
|
||||||
the broker resolves the sentinel at delivery time (falls back
|
ttl_seconds?, to?)`, `answer(id, answer)`.
|
||||||
to `operator` for root agents). Optional `in_reply_to: i64`
|
|
||||||
links this message to a prior message id for thread rendering
|
- `send` — message a peer (logical name) or the operator
|
||||||
in the dashboard message flow and the per-agent inbox.
|
(`to: "operator"`). Use `to: "<parent>"` to address the topology
|
||||||
- `recv(wait_seconds?, max?)` — drain inbox messages. Without
|
parent without hardcoding the label; the broker resolves the
|
||||||
`wait_seconds` (or with `0`) returns immediately, a cheap
|
sentinel at delivery time. Optional `in_reply_to: i64` links the
|
||||||
"anything pending?" peek. Positive value parks the turn up
|
message to a prior id for thread rendering.
|
||||||
to that many seconds (cap 180) — incoming messages wake
|
- `recv` — drain inbox. Without `wait_seconds` (or `0`) returns
|
||||||
instantly, otherwise returns empty at the timeout. `max`
|
immediately. Positive value parks the turn up to that many seconds
|
||||||
(default 1, server-side cap 32) drains up to N popped rows
|
(cap 180) — incoming messages wake instantly. `max` (default 1, cap
|
||||||
in one round-trip; `wait_seconds` applies to the *first*
|
32) drains up to N rows; `wait_seconds` applies to the first, then
|
||||||
message, then the call drains up to `max` total.
|
drains up to `max` total.
|
||||||
- `ask(question, options?, multi?, ttl_seconds?, to?)` —
|
- `ask` — surface a structured question to the operator (default) or
|
||||||
surface a structured question. Same shape as the manager's;
|
a peer agent (`to: "<agent>"`). Non-blocking — returns a question
|
||||||
recipient defaults to the operator (dashboard) but can be set
|
id; the answer arrives as a `question_answered` system event in the
|
||||||
to a peer agent name via `to: "<agent>"`. Answer routes back
|
asker's inbox. `options` is advisory; `multi=true` renders as
|
||||||
to the asker's own inbox as `HelperEvent::QuestionAnswered`
|
checkboxes; `ttl_seconds` auto-cancels with answer `[expired]`.
|
||||||
via `coord.notify_agent`. For peer questions the recipient
|
- `answer` — respond to a `question_asked` event routed to this
|
||||||
sees a `HelperEvent::QuestionAsked` event and replies with
|
agent. Strict authorisation: only the declared target can answer.
|
||||||
`answer(id, answer)`.
|
|
||||||
- `answer(id, answer)` — respond to a `question_asked` event
|
**Inbox** (`inbox` group): `get_loose_ends()`,
|
||||||
routed to this agent. Authorisation is strict: only the
|
`cancel_loose_end(kind, id)`, `remind(message, delay_seconds? |
|
||||||
declared target (or the operator via the dashboard) can
|
at_unix_timestamp?)`, `request_next_turn()`.
|
||||||
answer.
|
|
||||||
- `get_loose_ends()` — list everything still pending against
|
- `get_loose_ends` — list pending questions (asked/owed) and
|
||||||
this agent: unanswered questions it asked / was asked, plus
|
scheduled reminders. Each row carries an id + kind for
|
||||||
reminders it scheduled. Each row carries an id + kind for
|
|
||||||
`cancel_loose_end`.
|
`cancel_loose_end`.
|
||||||
- `cancel_loose_end(kind, id)` — withdraw a `question`
|
- `cancel_loose_end` — withdraw a `question` (posts `[cancelled by
|
||||||
(posts `[cancelled by <self>]` to unblock the asker), a
|
<self>]`) or hard-delete a `reminder`. Agents may only cancel rows
|
||||||
`reminder` (hard-delete before fire), or (manager only) an
|
they own.
|
||||||
`approval` (transitions to `Cancelled`; sub-agents refused with a
|
- `remind` — schedule a reminder in this agent's own inbox. Large
|
||||||
clear error). Sub-agents may only cancel rows they own.
|
payloads spill to `/agents/<self>/state/reminders/`. Pending count
|
||||||
- `remind(message, due)` — schedule a reminder that lands in
|
capped at 50 per agent (`HIVE_REMIND_MAX_PENDING_PER_AGENT`).
|
||||||
this agent's own inbox at a future time (sender shows as
|
- `request_next_turn` — ask the harness to start another turn
|
||||||
`reminder`). Large payloads spill to
|
immediately after this one ends, even if the inbox is empty.
|
||||||
`/agents/<self>/state/reminders/` with the inbox message a
|
Next turn fires with `from: "self"` and `body: "continue"`.
|
||||||
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`.
|
|
||||||
|
|
||||||
**Agent lifecycle + config tools** (direct children only; requires
|
**Meta** (`meta` group): `set_status(text)`, `get_agent_meta(name?)`.
|
||||||
`lifecycle` or `approvals` tool group):
|
|
||||||
|
|
||||||
- `kill(name)`, `start(name)`, `restart(name)`, `update(name)` — manage
|
- `set_status` — set a free-text status string visible on the
|
||||||
a direct child sub-agent (graceful stop, start, stop+start, rebuild).
|
dashboard. Single line, ≤ 200 chars. Persisted to
|
||||||
No approval required. Topology-enforced: `name` must be a direct child
|
`{state_dir}/hyperhive-status`. Pass `""` to clear.
|
||||||
per `topology.json`. Server rejects all other agent names. Requires
|
- `get_agent_meta` — fetch identity + status metadata for an agent:
|
||||||
`lifecycle` tool group.
|
`{ name, hyperhive_rev, running, status_text, status_set_at,
|
||||||
- `list_containers()` — list all descendant containers with running
|
hive_name?, swarm_name? }`. Omit `name` to query self.
|
||||||
status. Topology-enforced (descendants only). Requires `lifecycle`
|
|
||||||
tool group.
|
### Privileged tools (by tool group)
|
||||||
- `request_init_config(name, description?)` — step 1 of spawning a new
|
|
||||||
direct child agent. Queues an `InitConfig` approval; on operator
|
- **Bash execution** (`execution`) — background shell tasks. See
|
||||||
approve, hive-c0re seeds the proposed config repo with a default
|
[`docs/tools/bash.md`](tools/bash.md).
|
||||||
`agent.nix` template. `name` must be a direct child. Topology-enforced.
|
- **Lifecycle + config** (`lifecycle`, `approvals`) — manage child
|
||||||
Fails if config already exists. Requires `approvals` tool group.
|
agents, spawn new ones, apply config commits. See
|
||||||
- `request_apply_commit(agent, commit_ref, description?)` — step 2 of
|
[`docs/tools/lifecycle.md`](tools/lifecycle.md).
|
||||||
spawning a new direct child (or updating an existing child's config).
|
- **Scheduling + diagnostics** (`scheduling`, `diagnostics`) —
|
||||||
Submit a commit sha from the child's proposed config repo for operator
|
scheduled prompts, `get_logs`. See
|
||||||
approval. `agent` must be a direct child. Topology-enforced. `commit_ref`
|
[`docs/tools/scheduling.md`](tools/scheduling.md).
|
||||||
must be a 7-40 char hex sha. Requires `approvals` tool group.
|
- **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
|
### 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>`**
|
- **Shell out to `hive wake --from <label> --body <text>`**
|
||||||
(use `--body -` to read body from stdin). Already on the
|
(use `--body -` to read body from stdin). Already on the
|
||||||
container's `PATH` since the harness binary is in
|
container's `PATH` since the harness binary is in
|
||||||
`systemPackages`. Convenient for shell-script integrations.
|
`systemPackages`. Convenient for shell-script integrations and
|
||||||
Works for both `agent` and `manager` roles.
|
co-process daemons (matrix bridge, webhook listeners, scrapers).
|
||||||
|
|
||||||
- **Speak the wire protocol directly** — JSON-line over the
|
- **Speak the wire protocol directly** — JSON-line over the
|
||||||
unix socket: `{"cmd":"wake","from":"matrix","body":"new dm
|
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`.
|
see `hive-sh4re::AgentRequest::Wake`.
|
||||||
|
|
||||||
The wake event lands in the broker as `{from:<label>,
|
The wake event lands in the broker as `{from:<label>,
|
||||||
to:<agent>, body}`, which wakes whatever `recv` call the
|
to:<agent>, body}`, waking whatever `recv` call the harness
|
||||||
harness is currently blocked on. Next turn fires with the
|
is currently blocked on. The next turn fires with the wake
|
||||||
wake prompt formed from that message — claude sees "from:
|
prompt formed from that message.
|
||||||
matrix" (or whatever label) and reacts.
|
|
||||||
|
|
||||||
Identity = socket: anything that can connect to
|
Identity = socket: anything that can connect to
|
||||||
`/run/hive/mcp.sock` is implicitly trusted to inject these,
|
`/run/hive/mcp.sock` is implicitly trusted to inject these —
|
||||||
which is fine because the bind-mount is the agent's own
|
the bind-mount is the agent's own container only.
|
||||||
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).
|
|
||||||
|
|
||||||
### Authoritative state
|
### Authoritative state
|
||||||
|
|
||||||
|
|
@ -604,7 +414,7 @@ status hint moved to the wake prompt + UI header.
|
||||||
`web_tools` tool group is enabled — see P3RM1SS10NS tab).
|
`web_tools` tool group is enabled — see P3RM1SS10NS tab).
|
||||||
- Denied by omission or `claude-settings.json` deny list: `Bash`,
|
- Denied by omission or `claude-settings.json` deny list: `Bash`,
|
||||||
`Task`, `NotebookEdit`, `TodoWrite`.
|
`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
|
`Bash` is disallowed — shell execution goes through
|
||||||
`mcp__bash__run` (background tasks with structured output +
|
`mcp__bash__run` (background tasks with structured output +
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue