Watch
0
0
Fork
You've already forked hyperhive
0

document reading and editing an agent's agents.md through the swarm

docs/swarm/README.md gets the routes, the revision, the apply semantics
and the stopped-agent behaviour; the persistence doc points there from
the AGENTS.md entry. The swarm-controller, swarm-controller-api and
swarmctl READMEs and the repo map in AGENTS.md list the new bodies and
routes. docs/tools/swarmctl-cli.md is regenerated for
`swarmctl agent agents-md`, whose help text loses two passive phrasings
vale flags.
This commit is contained in:
atlas 2026-10-18 03:37:27 +02:00 • committed by mara
commit 9add99838c
8 changed files with 124 additions and 13 deletions

View file

@ -276,7 +276,10 @@ Under `/var/lib/hyperhive/agents/<name>/`:
`agents_md_migrate::run` renames a `state/CLAUDE.md` to `AGENTS.md`
when no `AGENTS.md` exists. When both exist it renames neither and
logs an error naming both paths: claude loads only `CLAUDE.md` while
one exists in its cwd or above.
one exists in its cwd or above. The harness also publishes the file
to the swarm, which reads that copy, and applies the git diffs the
swarm sends to edit it. This file stays the only copy that counts:
[`docs/swarm/README.md`](../swarm/README.md#an-agents-agentsmd).
- `harness/` — harness-internal ephemeral state; not intended for
agent consumption. Bind-mounted to `/agents/<name>/harness`
inside the container (`$HYPERHIVE_HARNESS_DIR`). Contents:

View file

@ -278,13 +278,19 @@ The third thing an agent publishes is its **icon**, the same SVG its own
`GET /icon` serves. It goes into the `agent-icons` KV bucket under the key
`<agent>`, with no hive in it, so the swarm can show the icon of an agent that's
stopped or has moved hives. The queue grants the agent's own credential
`$KV.agent-icons.<agent>` and no other key. The harness writes once per start,
because a config change reaches an agent by restarting its container. An agent
with no icon deletes its key. Swarm-side, `GET /api/agents/<name>/icon` serves
`$KV.agent-icons.<agent>` and no other key of that bucket. The harness writes
once per start, because a config change reaches an agent by restarting its
container. An agent with no icon deletes its key. Swarm-side,
`GET /api/agents/<name>/icon` serves
the stored bytes, and 404 means the agent has no icon. swarm-ui's agent cards
load it as an `<img>` and show the dimmed hyperhive mark for an agent without
one, as the hive dashboard does.
The fourth is its **`AGENTS.md`**, which goes into the `agents-md` bucket under
the key `<agent>`, writable by the agent's own credential alone
(`$KV.agents-md.<agent>`). The swarm reads that copy and edits the file through
the agent; [An agent's AGENTS.md](#an-agents-agentsmd) has the details.
The queue also limits what an agent may **subscribe** to, because agents are the
least trusted clients on the queue. An agent's own queue credential, which its
subagent daemon also presents, may subscribe to its reply inbox
@ -309,6 +315,41 @@ no replies, so every request it makes times out.
</details>
### An agent's AGENTS.md
The file in the agent's state dir, `state/AGENTS.md`, is the only copy that
counts, and only the agent writes it: itself, or its harness applying an edit
from the swarm. No hive is in either path.
**Reading.** The harness publishes the file's text and its revision, the git
blob id that `git hash-object` prints for it, at start, within ten seconds of
any change, and straight after an edit it applied. An agent with no `AGENTS.md`
publishes `""`. `GET /api/agents/<name>/agents-md` answers `{content, revision}`
from that copy, so it works while the agent isn't running. A 404 means the agent
hasn't published one: its harness hasn't run since it began to.
**Editing.** `PUT /api/agents/<name>/agents-md` takes `{base_revision, diff}`.
The diff is a unified diff that names `a/AGENTS.md` and `b/AGENTS.md`, made
against the text at `base_revision`. swarm-controller sends it as a request on
the agent's command subject `$SWARM.control.<name>`, as it sends a cancel. The
harness refuses it when the file isn't at `base_revision`. Otherwise it runs
`git apply --check` and then `git apply` on a copy of the file, and writes the
result over the file only when both pass:
| Status | Meaning |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| 200 | applied; the body is `{revision}`, the file's new revision |
| 409 | the file isn't at `base_revision` any more; nothing applied, and `revision` in the body is the one it's at |
| 422 | `git apply` refused the diff, or it touches a file other than `AGENTS.md`; `detail` carries git's message, and the file stays as it was |
| 503 | the agent isn't running or isn't connected to the queue |
| 504 | the harness didn't answer within ten seconds, so whether the edit applied is unknown |
| 500 | the harness couldn't read or write the file or run git, or the queue failed the request |
An edit needs the agent running, and a read of a stopped agent shows the text
it last published. A harness older than this route doesn't know the command and
drops it unanswered, which reads as a 504. `swarmctl agent agents-md get` and
`apply` call the two routes.
### Swarm-wide forge objects
The controller also keeps the forge objects that are one per swarm, not

View file

@ -16,6 +16,9 @@ This document contains the help content for the `swarmctl` command-line program.
* [`swarmctl agent permissions get`↴](#swarmctl-agent-permissions-get)
* [`swarmctl agent permissions set`↴](#swarmctl-agent-permissions-set)
* [`swarmctl agent permissions clear`↴](#swarmctl-agent-permissions-clear)
* [`swarmctl agent agents-md`↴](#swarmctl-agent-agents-md)
* [`swarmctl agent agents-md get`↴](#swarmctl-agent-agents-md-get)
* [`swarmctl agent agents-md apply`↴](#swarmctl-agent-agents-md-apply)
* [`swarmctl schedule`↴](#swarmctl-schedule)
* [`swarmctl schedule add`↴](#swarmctl-schedule-add)
* [`swarmctl schedule list`↴](#swarmctl-schedule-list)
@ -71,6 +74,7 @@ Manage agents across the swarm
* `mint-forge-token` — Check one agent's forge token, and mint it if it's missing or stale
* `inference` — Show the model, effort, subagent models and subagent cap the swarm sets for an agent, or change the model, effort and subagent models
* `permissions` — Show or change the permissions the swarm grants an agent
* `agents-md` — Show an agent's AGENTS.md, or edit it with a diff
@ -274,6 +278,61 @@ Clear the agent's permissions, so the default applies again
## `swarmctl agent agents-md`
Show an agent's AGENTS.md, or edit it with a diff.
`get` shows the copy the agent last published, so it works while the agent isn't running. `apply` hands the diff to the agent, which applies it to the file with `git apply`; it needs the agent running.
**Usage:** `swarmctl agent agents-md <COMMAND>`
###### **Subcommands:**
* `get` — Print an agent's AGENTS.md on stdout, and its revision on stderr
* `apply` — Apply a unified diff to an agent's AGENTS.md
## `swarmctl agent agents-md get`
Print an agent's AGENTS.md on stdout, and its revision on stderr
**Usage:** `swarmctl agent agents-md get [OPTIONS] <AGENT>`
###### **Arguments:**
* `<AGENT>` — Agent name
###### **Options:**
* `--controller-socket <PATH>` — swarm-controller's unix socket.
Supplied by the nix module that installs this binary, from the same `socketPath` option the daemon binds; falls back to `SWARM_CONTROLLER_SOCKET`.
## `swarmctl agent agents-md apply`
Apply a unified diff to an agent's AGENTS.md.
The diff names `a/AGENTS.md` and `b/AGENTS.md`, as `diff -u a/AGENTS.md b/AGENTS.md` writes it. The agent refuses it when the file is no longer at `--base`, or when it doesn't apply, and leaves the file as it was.
**Usage:** `swarmctl agent agents-md apply [OPTIONS] --base <REVISION> <AGENT> <DIFF_FILE>`
###### **Arguments:**
* `<AGENT>` — Agent name
* `<DIFF_FILE>` — The file holding the diff
###### **Options:**
* `--base <REVISION>` — The revision you made the diff against, as `get` printed it. It's the git blob id of that text, so `git hash-object` of the unedited file prints it too
* `--controller-socket <PATH>` — swarm-controller's unix socket.
Supplied by the nix module that installs this binary, from the same `socketPath` option the daemon binds; falls back to `SWARM_CONTROLLER_SOCKET`.
## `swarmctl schedule`
Manage scheduled prompts.