`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.
97 lines
3.8 KiB
Markdown
97 lines
3.8 KiB
Markdown
# Lifecycle and approvals tools
|
|
|
|
Two tool groups govern agent lifecycle management and config changes.
|
|
The server scopes both to the caller's **own subtree** (topology-enforced
|
|
per `topology.json`: a child, a child's child, every agent below them —
|
|
plus the caller itself). No privileged class exists to belong to; the
|
|
root agent reaches every agent purely because the check is transitive and
|
|
everything sits under it.
|
|
|
|
## `lifecycle` tool group
|
|
|
|
No operator approval required. The caller's own subtree.
|
|
|
|
### `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 the caller's whole **subtree** with running status — children,
|
|
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
|
|
|
|
Config changes and new-agent spawns route through the operator
|
|
approval queue. Topology-enforced the same way.
|
|
|
|
### `request_init_config(name, description?)`
|
|
|
|
Step 1 of spawning a new sub-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 the operator **spawns** the agent (the dashboard `◆ R3QU3ST SP4WN`
|
|
button / `Spawn` approval, routed via `HostRequest::RequestSpawn`),
|
|
which creates the container from that config.
|
|
|
|
Subsequent config changes go through a **forge PR** on the agent's
|
|
`agent-configs/<name>` repo (queues a `MergeConfigPr` approval on
|
|
open/update — no MCP tool involved), not a tool call. See
|
|
`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.
|
|
`name` is ≤ 9 characters.
|
|
|
|
### `request_update_meta_inputs(inputs?, description?)`
|
|
|
|
Queue an approval to run `nix flake update [inputs...]` on the meta
|
|
flake. Pass specific input names (for example `["bitburner-agent"]`) or omit
|
|
/ pass `[]` for all inputs. Returns immediately; the lock update runs
|
|
on operator approval.
|
|
|
|
**Doesn't** trigger container rebuilds — call `update(name)` on affected
|
|
agents after the approval resolves.
|
|
|
|
## Boundary summary
|
|
|
|
| Operation | Requires approval? | Scope |
|
|
| --------------------------------------- | ------------------ | ---------------------------------- |
|
|
| `kill` / `start` / `restart` / `update` | No | Own subtree |
|
|
| `list_containers` | No | Own subtree, caller included |
|
|
| `request_init_config` | Yes (InitConfig) | Unused name, or one in own subtree |
|
|
| `request_update_meta_inputs` | Yes (MetaUpdate) | Meta flake (global) |
|
|
|
|
## See also
|
|
|
|
- [`docs/agent-lifecycle/approvals.md`](../agent-lifecycle/approvals.md) — full approval flow, kinds,
|
|
helper events (`config_ready`, `approval_resolved`), flake.lock
|
|
validation.
|