# Agent archetypes An archetype is a named agent setup: settings to create the agent with, and a NixOS module its container runs. The swarm UI's create form lists the archetypes the swarm knows. Picking one fills the form's permissions, resource caps and inference fields from it, and you can still change each field before you create the agent. An agent created from an archetype has no `agent-configs/` repo of its own. The swarm's `internal/meta` flake builds it from the archetype's module, so every agent of that archetype runs the same configuration. To change what it runs, change the archetype. Picking "none" creates a custom agent, with its own config repo. ## The built-in archetypes The hyperhive flake ships these: | archetype | what it sets | | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `reviewer` | permissions `messaging`, `inbox`, `execution`: the default set without `meta`. With `execution` it can run `hive-forge`, `git` and other commands. | | `android-dev` | installs `android-tools` (`adb`, `fastboot`), Gradle and a JDK; default permissions. | ## Where an archetype comes from A flake declares archetypes in its `hyperhiveArchetypes` output: ```nix hyperhiveArchetypes.reviewer = { module = { }; meta = { description = "Reviews what it is sent."; permissions = [ "messaging" "inbox" "execution" ]; limits = { memory_max = "4G"; }; inference = { effort = "high"; }; }; }; ``` - `meta` is plain data: no derivation, no path, no function. The swarm evaluates `meta` alone. - Every archetype needs a `description`. `permissions`, `limits` and `inference` are optional and take the shapes `POST /api/agents` takes. The swarm ignores other keys in `meta`. - `module` is a NixOS module for the agent's container. The meta flake imports it into each agent created from the archetype. Today the swarm reads one flake: the hyperhive source the [builder](builder.md)'s host runs, so only the built-ins appear. The meta flake has one archetype source too, its own `hyperhive` input, and refuses an archetype from any other source name. ## How the list stays current 1. swarm-controller asks the builder for the list on the queue subject `$SWARM.builder.archetypes` once the queue connects, and every 10 minutes after that. 2. The builder evaluates the `meta` of each `hyperhiveArchetypes` entry on its own hyperhive and nixpkgs sources, and answers with the JSON or the last lines `nix` printed: ```sh nix eval --json #hyperhiveArchetypes \ --apply 'builtins.mapAttrs (_: a: a.meta)' ``` 3. The controller checks each archetype the way `POST /api/agents` checks its settings and stores the result in the `agent-archetypes` KV bucket, under the key `hyperhive`, when it differs from the stored one. The list leaves out an archetype that fails the check, and its name and reason go into the record's `refused` map and the controller's journal. 4. `GET /api/archetypes` answers from that record, and the create form lists from it. A builder host redeploy can change the list. The next pass, within 10 minutes, picks it up. When no builder answers, the controller keeps the stored list and logs a warning on each pass. A swarm with no builder enabled shows no archetype select. The stored value: ```json { "source": "/nix/store/…-hyperhive-flake-source", "archetypes": { "reviewer": { "description": "…", "permissions": ["messaging", "inbox", "execution"] } }, "refused": { "broken": "limits: …" } } ``` ## Creating an agent from an archetype The create form sends the picked archetype as `archetype` on `POST /api/agents`, `{ "source": "hyperhive", "name": "reviewer" }`. The controller refuses with 400 an archetype the stored list doesn't hold, then: 1. stores the choice in the `agent-archetype` KV bucket, keyed by agent name, next to the agent's permissions, caps and inference; 2. queues the creation graph without `CreateRepo`, `AddRepoMember` and `InitAgentConfigRepo`. Identity, forge user, docs read, the mints and the wanted state stay, and the deploy waits on those alone. Destroying the agent deletes its key. Every hive may read any key of the bucket (`$JS.API.DIRECT.GET.KV_agent-archetype.>`) and write none; only the controller writes it. Deploy `swarm-nats-auth` before the hives: every provision reads the agent's key, and a hive whose queue connection predates the grant gets a refused read, so its `Provision` nodes fail until it reconnects. swarm-controller renders `internal/meta`'s `flake.nix` with the `hive-meta-flake` crate, and reads each agent's archetype from the `agent-archetype` bucket to do so. For an archetype agent the render: - adds no `agent-` input and reads no config repo, and lists the agent as `mkAgent { …; archetype = { source = "hyperhive"; name = ""; }; }`; - makes `mkAgent` import `hyperhive.hyperhiveArchetypes..module` in place of the agent's own flake, and set `HIVE_ARCHETYPE` in the harness environment. The hive builds from `internal/meta` alone. It reads the agent's key when it provisions the agent and on every rebuild, and keeps the last value read in `/var/lib/hyperhive/swarm-agent-archetypes.json`. It takes the head of `internal/meta` only when that `flake.nix` lists the agent at the archetype it has now. When the read fails, a rebuild keeps the stored value. For an archetype agent the hive also: - seeds no `proposed` or `applied` repo; - ignores the `rev` of a swarm deploy request; - mounts an empty `/agents//config/`. The agent's system prompt says it has no config repo and names its archetype. The module comes from the `hyperhive` input that `internal/meta` pins, not from the hive's own. When that pin predates the archetype, the agent's build fails with `this hive's hyperhive input has no archetype ; update that input`. Update the `hyperhive` pin in `internal/meta` to fix it.