prompts+docs: the lifecycle tools reach the whole subtree, not just direct children
`require_descendant` (`socket_server/mod.rs:666`) authorises
kill/start/restart/update/get_logs with `topology::is_descendant_of` — the
caller's whole subtree, itself included. That has been true since `53b4e752`
(#1865), whose message says "a parent owns its whole subtree; the root covers
every agent as a consequence, no positional privilege", and two tests pin it
(`is_descendant_of_in_grandchild`, `is_descendant_of_in_self_is_true`).
The prose never followed. The four lifecycle tool descriptions, their
`// IMPORTANT:` comments, `docs/tools/lifecycle.md`, the tools README,
hive-agent-mcp's README and the system prompt every agent is rendered from all
still said "direct children only" — while `list_containers`, four tools away in
the same file, said "direct children + their subtrees".
`lifecycle.md` also taught the model #1865 deleted: "Privileged agents (for
example ruth) may operate on any sub-agent — the topology scope applies to all
others." There is no privileged class to belong to; ruth reaches every agent
because the check is transitive and everything sits under it.
Same drift on the state-query side: `resolve_agent_state_target` is
subtree-scoped by the same commit, so `get_loose_ends`' argument doc, the
`QueryAgentState` capability doc and `docs/turn-loop/mcp.md` were all telling a
parent it needs a capability to read a grandchild's threads.
Two smaller corrections found on the way:
* `list_containers` returns the caller itself. `is_descendant_of` is true for
`candidate == ancestor` and `handle_list_descendants` filters the topology
with it; called from a leaf agent it answers one row, that agent.
* `request_init_config` accepts any unused name — the requester becomes its
parent — or an existing agent already in the caller's subtree, not "a direct
child". The editing surface is narrower than the guard, though: only direct
children's config repos are bind-mounted, so re-seeding deeper in the subtree
leaves no local copy to edit. `lifecycle.md` now says so.
The prompt's other stale claim, the dead `request_apply_commit`, is #4226 and
was fixed independently by damocles in #4227 while this was being gated. This
branch keeps only the scope wording on that line.
Closes #4225.
This commit is contained in:
parent
7135931722
commit
0a80f21003
10 changed files with 93 additions and 66 deletions
|
|
@ -38,9 +38,9 @@ debug agent behavior.
|
||||||
- **[forge-cli](forge-cli.md)** — the exhaustive, autogenerated
|
- **[forge-cli](forge-cli.md)** — the exhaustive, autogenerated
|
||||||
flag-by-flag reference for `hive-forge`, kept in lockstep with the
|
flag-by-flag reference for `hive-forge`, kept in lockstep with the
|
||||||
binary by CI the same way `hivectl-cli.md` is.
|
binary by CI the same way `hivectl-cli.md` is.
|
||||||
- **[lifecycle](lifecycle.md)** — kill/start/restart/update for an
|
- **[lifecycle](lifecycle.md)** — kill/start/restart/update for the
|
||||||
agent's own direct children, plus the approval-gated config-change
|
agents in a caller's own subtree, plus the approval-gated
|
||||||
tools.
|
config-change tools.
|
||||||
- **[matrix](matrix.md)** — the matrix MCP tool surface
|
- **[matrix](matrix.md)** — the matrix MCP tool surface
|
||||||
(`mcp__matrix__*`) for agents with a matrix account, multiple
|
(`mcp__matrix__*`) for agents with a matrix account, multiple
|
||||||
accounts per agent, and declaring extra MCP servers generally.
|
accounts per agent, and declaring extra MCP servers generally.
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
# Lifecycle and approvals tools
|
# Lifecycle and approvals tools
|
||||||
|
|
||||||
Two tool groups govern agent lifecycle management and config changes.
|
Two tool groups govern agent lifecycle management and config changes.
|
||||||
The server scopes both to **direct children only** (topology-enforced: it
|
The server scopes both to the caller's **own subtree** (topology-enforced
|
||||||
rejects any name that's not a direct child of the calling
|
per `topology.json`: a child, a child's child, every agent below them —
|
||||||
agent per `topology.json`). Privileged agents (for example ruth) may operate
|
plus the caller itself). No privileged class exists to belong to; the
|
||||||
on any sub-agent — the topology scope applies to all others.
|
root agent reaches every agent purely because the check is transitive and
|
||||||
|
everything sits under it.
|
||||||
|
|
||||||
## `lifecycle` tool group
|
## `lifecycle` tool group
|
||||||
|
|
||||||
No operator approval required. Direct children only.
|
No operator approval required. The caller's own subtree.
|
||||||
|
|
||||||
### `kill(name)`
|
### `kill(name)`
|
||||||
|
|
||||||
|
|
@ -31,17 +32,19 @@ to `needs_update` system events.
|
||||||
|
|
||||||
### `list_containers()`
|
### `list_containers()`
|
||||||
|
|
||||||
List all **descendant** containers (children + their subtrees) with
|
List the caller's whole **subtree** with running status — children,
|
||||||
running status. Topology-scoped to descendants only.
|
their children, every agent below them. The calling agent is part of its
|
||||||
|
own subtree, so it appears in its own listing; a leaf agent gets a
|
||||||
|
one-row answer naming itself.
|
||||||
|
|
||||||
## `approvals` tool group
|
## `approvals` tool group
|
||||||
|
|
||||||
Config changes and new-agent spawns route through the operator
|
Config changes and new-agent spawns route through the operator
|
||||||
approval queue. Direct children only (topology-enforced).
|
approval queue. Topology-enforced the same way.
|
||||||
|
|
||||||
### `request_init_config(name, description?)`
|
### `request_init_config(name, description?)`
|
||||||
|
|
||||||
Step 1 of spawning a new direct child agent. Queues an `InitConfig`
|
Step 1 of spawning a new sub-agent. Queues an `InitConfig`
|
||||||
approval; on operator approve, hive-c0re seeds the proposed config
|
approval; on operator approve, hive-c0re seeds the proposed config
|
||||||
repo at `/agents/<name>/config/agent.nix` with a default template and
|
repo at `/agents/<name>/config/agent.nix` with a default template and
|
||||||
delivers a `config_ready` system event. Then edit `agent.nix`, commit,
|
delivers a `config_ready` system event. Then edit `agent.nix`, commit,
|
||||||
|
|
@ -54,6 +57,17 @@ Subsequent config changes go through a **forge PR** on the agent's
|
||||||
open/update — no MCP tool involved), not a tool call. See
|
open/update — no MCP tool involved), not a tool call. See
|
||||||
`docs/agent-lifecycle/approvals.md`.
|
`docs/agent-lifecycle/approvals.md`.
|
||||||
|
|
||||||
|
`name` must be either unused — in which case the caller becomes its
|
||||||
|
parent on approval — or an agent already in the caller's subtree whose
|
||||||
|
config is being re-seeded. The server refuses a name that exists outside
|
||||||
|
that subtree, so one agent can't hijack another's.
|
||||||
|
|
||||||
|
Only **direct** children's config repos are bind-mounted into a parent's
|
||||||
|
container, though (`bind_child_agent_dirs`, driven by
|
||||||
|
`topology::children_of`). The server accepts re-seeding an agent further
|
||||||
|
down the subtree, and that still leaves the caller without a local copy
|
||||||
|
to edit afterwards.
|
||||||
|
|
||||||
Fails if a proposed config repo for `name` already exists.
|
Fails if a proposed config repo for `name` already exists.
|
||||||
`name` is ≤ 9 characters.
|
`name` is ≤ 9 characters.
|
||||||
|
|
||||||
|
|
@ -69,12 +83,12 @@ agents after the approval resolves.
|
||||||
|
|
||||||
## Boundary summary
|
## Boundary summary
|
||||||
|
|
||||||
| Operation | Requires approval? | Scope |
|
| Operation | Requires approval? | Scope |
|
||||||
| --------------------------------------- | ------------------ | --------------------- |
|
| --------------------------------------- | ------------------ | ---------------------------------- |
|
||||||
| `kill` / `start` / `restart` / `update` | No | Direct children |
|
| `kill` / `start` / `restart` / `update` | No | Own subtree |
|
||||||
| `list_containers` | No | All descendants |
|
| `list_containers` | No | Own subtree, caller included |
|
||||||
| `request_init_config` | Yes (InitConfig) | New direct child only |
|
| `request_init_config` | Yes (InitConfig) | Unused name, or one in own subtree |
|
||||||
| `request_update_meta_inputs` | Yes (MetaUpdate) | Meta flake (global) |
|
| `request_update_meta_inputs` | Yes (MetaUpdate) | Meta flake (global) |
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,9 @@ at_unix_timestamp?)`.
|
||||||
external MCP daemons (for example running bash tasks from
|
external MCP daemons (for example running bash tasks from
|
||||||
`hive-bash-daemon`). Each row carries an id + kind for
|
`hive-bash-daemon`). Each row carries an id + kind for
|
||||||
`cancel_loose_end`. Omit `agent` to list your own threads. Pass
|
`cancel_loose_end`. Omit `agent` to list your own threads. Pass
|
||||||
`agent: "<name>"` to inspect a direct child agent (always accessible
|
`agent: "<name>"` to inspect any agent in your subtree — a child, a
|
||||||
per topology enforcement); non-children require the
|
child's child, every agent below them (always accessible per topology
|
||||||
|
enforcement); a name outside the subtree requires the
|
||||||
`query_agent_state` capability. The `"*"` hive-wide query isn't
|
`query_agent_state` capability. The `"*"` hive-wide query isn't
|
||||||
available on the agent socket.
|
available on the agent socket.
|
||||||
- `cancel_loose_end` — hard-delete a `reminder`, cancel a pending
|
- `cancel_loose_end` — hard-delete a `reminder`, cancel a pending
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ would hit. HTTP is the sole transport; there is no stdio mode here.
|
||||||
|
|
||||||
This is where the core hyperhive tool surface lives: `send`, `recv`,
|
This is where the core hyperhive tool surface lives: `send`, `recv`,
|
||||||
`remind`, `get_loose_ends`, `set_status`,
|
`remind`, `get_loose_ends`, `set_status`,
|
||||||
`get_agent_meta`, lifecycle (`kill`/`start`/`restart`/`update` on
|
`get_agent_meta`, lifecycle (`kill`/`start`/`restart`/`update` on the
|
||||||
direct children), scheduling, and the approval-request tools. Reach
|
agent's own subtree), scheduling, and the approval-request tools. Reach
|
||||||
for this crate when you're adding or changing a built-in tool rather
|
for this crate when you're adding or changing a built-in tool rather
|
||||||
than an `extraMcpServers` add-on — those are separate stdio bridges
|
than an `extraMcpServers` add-on — those are separate stdio bridges
|
||||||
(see `hive-bash-mcp`, `hive-matrix-mcp`) that dial the harness socket
|
(see `hive-bash-mcp`, `hive-matrix-mcp`) that dial the harness socket
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,8 @@ pub struct CancelLooseEndArgs {
|
||||||
#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
|
#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
|
||||||
pub struct AgentGetLooseEndsArgs {
|
pub struct AgentGetLooseEndsArgs {
|
||||||
/// Whose loose ends to list. Omit (or `null`) for your own. You may
|
/// Whose loose ends to list. Omit (or `null`) for your own. You may
|
||||||
/// also pass a direct child agent's name without any extra capability.
|
/// also pass the name of any agent in your subtree — a child, a child's
|
||||||
|
/// child, and so on down — without any extra capability.
|
||||||
/// Pass any other agent name to inspect their threads — requires the
|
/// Pass any other agent name to inspect their threads — requires the
|
||||||
/// `query_agent_state` capability; without it the request is rejected
|
/// `query_agent_state` capability; without it the request is rejected
|
||||||
/// with an error. The `"*"` hive-wide value is not available on the
|
/// with an error. The `"*"` hive-wide value is not available on the
|
||||||
|
|
|
||||||
|
|
@ -560,11 +560,12 @@ impl AgentServer {
|
||||||
|
|
||||||
// IMPORTANT: this tool is only available when the `lifecycle` tool group
|
// IMPORTANT: this tool is only available when the `lifecycle` tool group
|
||||||
// is granted to this agent. hive-c0re enforces the topology check
|
// is granted to this agent. hive-c0re enforces the topology check
|
||||||
// server-side: the call is rejected unless `name` is a direct child.
|
// server-side: the call is rejected unless `name` is in the caller's
|
||||||
|
// subtree.
|
||||||
#[tool(
|
#[tool(
|
||||||
description = "Restart a direct child sub-agent container (stop + start). \
|
description = "Restart a sub-agent container (stop + start). Only succeeds if `name` \
|
||||||
Only succeeds if `name` is a direct child of this agent in the topology \
|
is somewhere in this agent's subtree — a child, a child's child, and so on down \
|
||||||
tree — the server enforces this. No approval required."
|
the topology tree — which the server enforces. No approval required."
|
||||||
)]
|
)]
|
||||||
async fn restart(&self, Parameters(args): Parameters<RestartArgs>) -> String {
|
async fn restart(&self, Parameters(args): Parameters<RestartArgs>) -> String {
|
||||||
let log = format!("{args:?}");
|
let log = format!("{args:?}");
|
||||||
|
|
@ -583,11 +584,14 @@ impl AgentServer {
|
||||||
|
|
||||||
// IMPORTANT: this tool is only available when the `lifecycle` tool group
|
// IMPORTANT: this tool is only available when the `lifecycle` tool group
|
||||||
// is granted to this agent. hive-c0re enforces the topology check
|
// is granted to this agent. hive-c0re enforces the topology check
|
||||||
// server-side: the call is rejected unless `name` is a direct child.
|
// server-side: the call is rejected unless `name` is in the caller's
|
||||||
#[tool(description = "Stop a direct child sub-agent container (graceful). \
|
// subtree.
|
||||||
Only succeeds if `name` is a direct child of this agent in the topology \
|
#[tool(
|
||||||
tree — the server enforces this. No approval required. \
|
description = "Stop a sub-agent container (graceful). Only succeeds if `name` \
|
||||||
State dir is kept; recreating the agent reuses prior config + credentials.")]
|
is somewhere in this agent's subtree — a child, a child's child, and so on down \
|
||||||
|
the topology tree — which the server enforces. No approval required. \
|
||||||
|
State dir is kept; recreating the agent reuses prior config + credentials."
|
||||||
|
)]
|
||||||
async fn kill(&self, Parameters(args): Parameters<KillArgs>) -> String {
|
async fn kill(&self, Parameters(args): Parameters<KillArgs>) -> String {
|
||||||
let log = format!("{args:?}");
|
let log = format!("{args:?}");
|
||||||
let name = args.name.clone();
|
let name = args.name.clone();
|
||||||
|
|
@ -602,12 +606,14 @@ impl AgentServer {
|
||||||
|
|
||||||
// IMPORTANT: this tool is only available when the `lifecycle` tool group
|
// IMPORTANT: this tool is only available when the `lifecycle` tool group
|
||||||
// is granted to this agent. hive-c0re enforces the topology check
|
// is granted to this agent. hive-c0re enforces the topology check
|
||||||
// server-side: the call is rejected unless `name` is a direct child.
|
// server-side: the call is rejected unless `name` is in the caller's
|
||||||
|
// subtree.
|
||||||
#[tool(
|
#[tool(
|
||||||
description = "Rebuild a direct child sub-agent: re-applies the current hyperhive \
|
description = "Rebuild a sub-agent: re-applies the current hyperhive flake + agent.nix \
|
||||||
flake + agent.nix and restarts the container. Only succeeds if `name` is a direct \
|
and restarts the container. Only succeeds if `name` is somewhere in this agent's \
|
||||||
child of this agent in the topology tree — the server enforces this. \
|
subtree — a child, a child's child, and so on down the topology tree — which the \
|
||||||
No approval required. Idempotent — use when a child needs its config reapplied."
|
server enforces. No approval required. Idempotent — use when an agent needs its \
|
||||||
|
config reapplied."
|
||||||
)]
|
)]
|
||||||
async fn update(&self, Parameters(args): Parameters<UpdateArgs>) -> String {
|
async fn update(&self, Parameters(args): Parameters<UpdateArgs>) -> String {
|
||||||
let log = format!("{args:?}");
|
let log = format!("{args:?}");
|
||||||
|
|
@ -625,11 +631,12 @@ impl AgentServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// IMPORTANT: this tool is only available when the `lifecycle` tool group
|
// IMPORTANT: this tool is only available when the `lifecycle` tool group
|
||||||
// is granted to this agent. Returns all topological descendants of the
|
// is granted to this agent. Returns the calling agent's whole subtree,
|
||||||
// calling agent with their running status.
|
// itself included, with running status.
|
||||||
#[tool(
|
#[tool(
|
||||||
description = "List all containers that are topological descendants of this agent \
|
description = "List this agent's whole subtree — children, their children, and so on \
|
||||||
(direct children + their subtrees). Requires the `lifecycle` tool group. \
|
down — with running status. The calling agent is part of its own subtree, so it \
|
||||||
|
appears in the listing too. Requires the `lifecycle` tool group. \
|
||||||
Returns every known descendant regardless of running state — check the `running` \
|
Returns every known descendant regardless of running state — check the `running` \
|
||||||
field to distinguish live from stopped containers. Ordered by topology depth \
|
field to distinguish live from stopped containers. Ordered by topology depth \
|
||||||
(parents before children), then alphabetically within each tier."
|
(parents before children), then alphabetically within each tier."
|
||||||
|
|
@ -705,20 +712,20 @@ impl AgentServer {
|
||||||
|
|
||||||
// IMPORTANT: this tool is only available when the `approvals` tool group
|
// IMPORTANT: this tool is only available when the `approvals` tool group
|
||||||
// is configured for the agent (`HIVE_TOOL_GROUPS` contains `approvals`).
|
// is configured for the agent (`HIVE_TOOL_GROUPS` contains `approvals`).
|
||||||
// hive-c0re performs a topology check server-side: only direct children
|
// hive-c0re performs a topology check server-side: an unused `name` is
|
||||||
// of the calling agent are accepted; all other names are rejected.
|
// accepted from any caller (the requester becomes its parent); an existing
|
||||||
#[tool(
|
// agent is accepted only from inside the caller's subtree.
|
||||||
description = "Create a brand-new direct child agent's config repo and queue an \
|
#[tool(description = "Create a new agent's config repo and queue an \
|
||||||
`InitConfig` approval for the operator to review. Requires the `approvals` tool \
|
`InitConfig` approval for the operator to review. Requires the `approvals` tool \
|
||||||
group. `name` must be a direct child of this agent in the topology tree. Fails if a \
|
group. `name` must be either unused — in which case you become its parent — or an \
|
||||||
config repo for that child already exists. This tool **creates the repo** and \
|
agent already in your subtree, whose config you are re-seeding. Fails if a \
|
||||||
|
config repo for that agent already exists. This tool **creates the repo** and \
|
||||||
nothing else: on approval hive-c0re seeds it with a default `agent.nix`, and \
|
nothing else: on approval hive-c0re seeds it with a default `agent.nix`, and \
|
||||||
approving the follow-up `Spawn` creates the container. \
|
approving the follow-up `Spawn` creates the container. \
|
||||||
Every config change — the child's first one included — goes through a PR on its \
|
Every config change — the child's first one included — goes through a PR on its \
|
||||||
config repo, made from a clone you take yourself, reviewed + approved by the \
|
config repo, made from a clone you take yourself, reviewed + approved by the \
|
||||||
operator. `/agents/<name>/config` is a **read-only copy** for reading a config, \
|
operator. `/agents/<name>/config` is a **read-only copy** for reading a config, \
|
||||||
never an editing surface."
|
never an editing surface.")]
|
||||||
)]
|
|
||||||
async fn request_init_config(
|
async fn request_init_config(
|
||||||
&self,
|
&self,
|
||||||
Parameters(args): Parameters<RequestInitConfigArgs>,
|
Parameters(args): Parameters<RequestInitConfigArgs>,
|
||||||
|
|
@ -746,10 +753,13 @@ impl AgentServer {
|
||||||
|
|
||||||
// IMPORTANT: this tool is only available when the `lifecycle` tool group
|
// IMPORTANT: this tool is only available when the `lifecycle` tool group
|
||||||
// is granted to this agent. hive-c0re enforces the topology check
|
// is granted to this agent. hive-c0re enforces the topology check
|
||||||
// server-side: the call is rejected unless `name` is a direct child.
|
// server-side: the call is rejected unless `name` is in the caller's
|
||||||
#[tool(description = "Start a stopped direct child sub-agent container. \
|
// subtree.
|
||||||
Only succeeds if `name` is a direct child of this agent in the topology \
|
#[tool(
|
||||||
tree — the server enforces this. No approval required.")]
|
description = "Start a stopped sub-agent container. Only succeeds if `name` \
|
||||||
|
is somewhere in this agent's subtree — a child, a child's child, and so on down \
|
||||||
|
the topology tree — which the server enforces. No approval required."
|
||||||
|
)]
|
||||||
async fn start(&self, Parameters(args): Parameters<StartArgs>) -> String {
|
async fn start(&self, Parameters(args): Parameters<StartArgs>) -> String {
|
||||||
let log = format!("{args:?}");
|
let log = format!("{args:?}");
|
||||||
let name = args.name.clone();
|
let name = args.name.clone();
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ Tools (hyperhive surface). Full signature + behavior for each comes from the too
|
||||||
|
|
||||||
- **Inbox / messaging** (always available): `mcp__hyperhive__recv`, `mcp__hyperhive__ack_until`, `mcp__hyperhive__send`, `mcp__hyperhive__get_loose_ends`, `mcp__hyperhive__cancel_loose_end`, `mcp__hyperhive__mark_todos_done`, `mcp__hyperhive__remind`, `mcp__hyperhive__set_status`, `mcp__hyperhive__get_agent_meta`. One habit worth internalizing beyond the tool descriptions themselves: prefer ending the turn over repeatedly polling `recv` when idle (only turn-boundaries observe in-container todo wakes — bash-task completions, matrix unread, forge activity — and ending the turn is also your checkpoint). For a large todo backlog (`get_loose_ends` caps at 40 rows), clear reviewed ids in bulk with `mark_todos_done` rather than cancelling one at a time — there's no blind range-clear, only ids you've actually looked at.
|
- **Inbox / messaging** (always available): `mcp__hyperhive__recv`, `mcp__hyperhive__ack_until`, `mcp__hyperhive__send`, `mcp__hyperhive__get_loose_ends`, `mcp__hyperhive__cancel_loose_end`, `mcp__hyperhive__mark_todos_done`, `mcp__hyperhive__remind`, `mcp__hyperhive__set_status`, `mcp__hyperhive__get_agent_meta`. One habit worth internalizing beyond the tool descriptions themselves: prefer ending the turn over repeatedly polling `recv` when idle (only turn-boundaries observe in-container todo wakes — bash-task completions, matrix unread, forge activity — and ending the turn is also your checkpoint). For a large todo backlog (`get_loose_ends` caps at 40 rows), clear reviewed ids in bulk with `mark_todos_done` rather than cancelling one at a time — there's no blind range-clear, only ids you've actually looked at.
|
||||||
- **Extra MCP tools** (some agents only): `mcp__<server>__<tool>` — agent-specific (matrix client, scraper, db connector, etc.) declared in your `agent.nix` under `hyperhive.extraMcpServers`. First-class tools, already operator-approved at deploy time.
|
- **Extra MCP tools** (some agents only): `mcp__<server>__<tool>` — agent-specific (matrix client, scraper, db connector, etc.) declared in your `agent.nix` under `hyperhive.extraMcpServers`. First-class tools, already operator-approved at deploy time.
|
||||||
- **Lifecycle** (_requires `lifecycle` tool group_, direct children only, no approval needed): `restart`, `kill`, `start`, `update`, `list_containers`.
|
- **Lifecycle** (_requires `lifecycle` tool group_, your own subtree — children, their children, and so on down, no approval needed): `restart`, `kill`, `start`, `update`, `list_containers`.
|
||||||
- **Approvals** (_requires `approvals` tool group_, queues an operator approval): `request_init_config`, `request_update_meta_inputs`.
|
- **Approvals** (_requires `approvals` tool group_, queues an operator approval): `request_init_config`, `request_update_meta_inputs`.
|
||||||
- **Scheduling** (_requires `scheduling` tool group_): `request_schedule_prompt` (queues an approval), `cancel_schedule`, `fire_schedule_now`, `edit_schedule`, `list_schedules` (these four don't need approval — you can manage schedules you own or that a sub-agent in your subtree owns).
|
- **Scheduling** (_requires `scheduling` tool group_): `request_schedule_prompt` (queues an approval), `cancel_schedule`, `fire_schedule_now`, `edit_schedule`, `list_schedules` (these four don't need approval — you can manage schedules you own or that a sub-agent in your subtree owns).
|
||||||
- **Diagnostics**: `get_logs` (_requires `diagnostics` tool group_), `get_host_journal` (_requires `read_host_journal` capability_).
|
- **Diagnostics**: `get_logs` (_requires `diagnostics` tool group_), `get_host_journal` (_requires `read_host_journal` capability_).
|
||||||
|
|
@ -13,7 +13,7 @@ Need new packages, env vars, or other NixOS config for yourself? You can't edit
|
||||||
|
|
||||||
Your config repo is mounted **read-only** at `/agents/{label}/config/` — `agent.nix` plus whatever extra files define you (declared packages, env vars, MCP servers). Read it to see exactly what defines you before asking for a change, so you can point at the precise file and line.
|
Your config repo is mounted **read-only** at `/agents/{label}/config/` — `agent.nix` plus whatever extra files define you (declared packages, env vars, MCP servers). Read it to see exactly what defines you before asking for a change, so you can point at the precise file and line.
|
||||||
|
|
||||||
Approval boundary: lifecycle ops on _existing_ direct children (`kill`, `start`, `restart`) are at your discretion — no operator approval needed (requires `lifecycle` tool group). _Creating_ a new agent starts with `request_init_config` (requires `approvals` tool group), then the operator spawns it from the dashboard. _Changing_ any agent's config is not a tool call at all — it's a forge PR on the agent's `agent-configs/<name>` repo, which queues a `MergeConfigPr` approval on open/update. The operator only signs off on changes; you run the day-to-day.
|
Approval boundary: lifecycle ops on _existing_ agents in your subtree (`kill`, `start`, `restart`) are at your discretion — no operator approval needed (requires `lifecycle` tool group). _Creating_ a new agent starts with `request_init_config` (requires `approvals` tool group), then the operator spawns it from the dashboard. _Changing_ any agent's config is not a tool call at all — it's a forge PR on the agent's `agent-configs/<name>` repo, which queues a `MergeConfigPr` approval on open/update. The operator only signs off on changes; you run the day-to-day.
|
||||||
|
|
||||||
Messages from sender `system` are hyperhive helper events (JSON body, `event` field discriminates): `approval_resolved`, `container_crash`, `needs_update`. Use these to react to lifecycle changes:
|
Messages from sender `system` are hyperhive helper events (JSON body, `event` field discriminates): `approval_resolved`, `container_crash`, `needs_update`. Use these to react to lifecycle changes:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -698,10 +698,10 @@ fn require_group(agent: &str, group: &str, action: &str) -> Option<Response> {
|
||||||
/// Topology guard for `request_init_config`, which may legitimately target a
|
/// Topology guard for `request_init_config`, which may legitimately target a
|
||||||
/// child that does not exist *yet* (seeding a brand-new sub-agent's config
|
/// child that does not exist *yet* (seeding a brand-new sub-agent's config
|
||||||
/// repo). The caller may act on a
|
/// repo). The caller may act on a
|
||||||
/// `target` that is EITHER already its direct child (re-init / config
|
/// `target` that is EITHER already in its subtree (re-init / config
|
||||||
/// update of an existing child) OR brand-new (absent from the topology
|
/// update of an agent it owns) OR brand-new (absent from the topology
|
||||||
/// tree — the requester becomes its parent). A name that already
|
/// tree — the requester becomes its parent). A name that already
|
||||||
/// belongs to a *different* parent (or is a root agent) is refused so
|
/// exists outside the caller's subtree is refused so
|
||||||
/// one agent can't hijack another's sub-tree.
|
/// one agent can't hijack another's sub-tree.
|
||||||
///
|
///
|
||||||
/// Also re-runs the agent-name format check (a traversal / malformed name
|
/// Also re-runs the agent-name format check (a traversal / malformed name
|
||||||
|
|
|
||||||
|
|
@ -193,10 +193,10 @@ pub enum Request {
|
||||||
},
|
},
|
||||||
/// *(privileged)* List every schedule in the queue.
|
/// *(privileged)* List every schedule in the queue.
|
||||||
ListSchedules,
|
ListSchedules,
|
||||||
/// List all containers that are topological descendants of the calling
|
/// List the calling agent's subtree — children, their children, and so
|
||||||
/// agent (direct children + their subtrees). Scoped to the caller's
|
/// on down, plus the caller itself, which is part of its own subtree.
|
||||||
/// subtree; gated by the `lifecycle` tool group. The result includes all
|
/// Gated by the `lifecycle` tool group. The result includes every known
|
||||||
/// known descendants regardless of whether the container is currently
|
/// member regardless of whether the container is currently
|
||||||
/// running — use `running` to distinguish.
|
/// running — use `running` to distinguish.
|
||||||
ListDescendants,
|
ListDescendants,
|
||||||
/// *(privileged)* Fire a scheduled prompt out of band immediately.
|
/// *(privileged)* Fire a scheduled prompt out of band immediately.
|
||||||
|
|
|
||||||
|
|
@ -215,11 +215,12 @@ pub enum Capability {
|
||||||
/// MCP tool `get_host_journal` is only registered in the harness
|
/// MCP tool `get_host_journal` is only registered in the harness
|
||||||
/// when this capability is present.
|
/// when this capability is present.
|
||||||
ReadHostJournal,
|
ReadHostJournal,
|
||||||
/// Agent can query non-child agents via `GetLooseEnds`,
|
/// Agent can query agents outside its own subtree via `GetLooseEnds`,
|
||||||
/// `CountPendingReminders`, and `ReminderRollup` on the agent
|
/// `CountPendingReminders`, and `ReminderRollup` on the agent
|
||||||
/// socket. Without this capability, targeting a non-child agent is
|
/// socket. Without this capability, targeting an agent outside the
|
||||||
/// rejected with an error (direct children are always accessible
|
/// caller's subtree is rejected with an error (the caller itself and
|
||||||
/// without any capability). The `"*"` hive-wide value is not
|
/// every descendant are always accessible without any capability).
|
||||||
|
/// The `"*"` hive-wide value is not
|
||||||
/// available on the agent socket even with this capability — use the
|
/// available on the agent socket even with this capability — use the
|
||||||
/// manager socket for swarm-wide scans.
|
/// manager socket for swarm-wide scans.
|
||||||
QueryAgentState,
|
QueryAgentState,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue