hyperhive/docs/tools/lifecycle.md
atlas 0a80f21003 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.
2026-09-11 15:23:50 +02:00

3.8 KiB

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