302 lines
13 KiB
Markdown
302 lines
13 KiB
Markdown
# Agent config knobs
|
|
|
|
Optional per-agent knobs the meta flake wires into the container from
|
|
`services.hyperhive.agents.<name>`, read at boot or per turn by the harness.
|
|
Absent means the default. (The claude spawn + compaction themselves live in
|
|
[claude-invocation](claude-invocation.md).)
|
|
|
|
## Reference docs (`hyperhive.docs.enable`)
|
|
|
|
```nix
|
|
hyperhive.docs.enable = true; # default: false (true for the manager agent)
|
|
```
|
|
|
|
Makes the hyperhive `docs/` tree available inside the container at a nix
|
|
store path read from `$HIVE_DOCS_DIR`, and injects a single pointer
|
|
sentence into the agent's system prompt so it knows the docs exist and
|
|
where to find them. The tree is served by `claude --add-dir` so the full
|
|
markdown is readable during every turn.
|
|
|
|
Enabled by default only for the root/manager agent (`nix/templates/ruth.nix`). Any
|
|
agent can opt in by adding the line above to its `agent.nix`.
|
|
|
|
The `docs/` source is a narrow flake input (`hyperhive-docs`) tracked
|
|
separately from the main `hyperhive` flake so editing docs re-locks only
|
|
that input — not every agent's container gets rebuilt on a doc-only change.
|
|
|
|
## Agent icon
|
|
|
|
```nix
|
|
hyperhive.icon = ./icon.svg; # default: null (falls back to shared hyperhive logo)
|
|
```
|
|
|
|
Path to an SVG file used as this agent's visual identity — shown in
|
|
the per-agent page header, as the page favicon, and uploaded to the
|
|
agent's Forgejo profile avatar (via the `forge-avatar-sync` boot
|
|
unit) and Matrix profile avatar (set by `hive-matrix-daemon` over its
|
|
live Client). Commit the SVG next to `agent.nix` in the config repo
|
|
and reference it as a relative path.
|
|
|
|
When `null` (the default), the agent falls back to the shared
|
|
hyperhive branding mark. The harness serves whichever icon is active
|
|
at `GET /icon` on the per-agent web port.
|
|
|
|
## `user.passwordlessSudo`
|
|
|
|
```nix
|
|
hyperhive.user.passwordlessSudo = true; # default
|
|
```
|
|
|
|
Grants the per-agent unix user passwordless `sudo` (`NOPASSWD: ALL`).
|
|
Enabled by default so claude's shell tools work for operations that
|
|
need root inside the container (`systemctl`, package managers in dev
|
|
shells, etc.) — the agent user gets root explicitly via `sudo` rather
|
|
than running as root itself.
|
|
|
|
Set to `false` for agents that should be strictly unprivileged.
|
|
Any tool invocation that needs root then fails loudly with the standard
|
|
sudo rejection rather than silently succeeding — easier to audit.
|
|
|
|
`hyperhive.user.uid`, `hyperhive.user.gid`, and
|
|
`hyperhive.user.name` are the companion options; see
|
|
`docs/agent-hierarchy.md` — "Harness systemd unit shape" for the full
|
|
`user.*` surface.
|
|
|
|
## Dashboard links
|
|
|
|
```nix
|
|
hyperhive.dashboardLinks = [
|
|
{ label = "Stats"; icon = "📊"; url = "http://localhost:9001/stats"; }
|
|
{ label = "Scratchpad"; url = "http://localhost:8080"; }
|
|
];
|
|
```
|
|
|
|
Declares extra navigation links that appear in the per-agent page
|
|
header alongside the built-in forge / config / container links. Each
|
|
entry has:
|
|
|
|
| Field | Required | Description |
|
|
|-------|----------|-------------|
|
|
| `label` | yes | Display text shown in the icon strip tooltip and meta-nav. |
|
|
| `url` | yes | Absolute URL — may include a different port (the dashboard renders it as a plain anchor). |
|
|
| `icon` | no | Emoji or short glyph prefix. Defaults to empty string. |
|
|
|
|
The list is written to `<state>/hyperhive-dashboard-links.json` by a
|
|
one-shot systemd unit at container boot. The harness's own web UI
|
|
(`agent_links` in `hive-agent/src/web_ui/state.rs`) reads the file on
|
|
each `/api/state` snapshot and appends the entries to the per-agent
|
|
nav as `kind = External` links — no `hive-c0re` / operator-dashboard
|
|
involvement, and no code change needed to pick up a new entry.
|
|
Omitting the option (default empty) produces no extra links.
|
|
|
|
## Custom static files
|
|
|
|
```nix
|
|
hyperhive.frontend.extraFiles = {
|
|
"games/bitburner" = {
|
|
source = ./bitburner-dist; # path relative to agent.nix
|
|
# target defaults to attribute name: "games/bitburner"
|
|
};
|
|
"my-page" = {
|
|
source = ./my-page.html;
|
|
target = "my-page.html"; # explicit override
|
|
};
|
|
};
|
|
```
|
|
|
|
Layers additional files over the default per-agent web UI dist. Each
|
|
attribute defines one overlay entry:
|
|
|
|
- **`source`** — a Nix path (file or directory) copied into the merged
|
|
static tree. Evaluated at nix build time; the resulting derivation is
|
|
pointed at by `HIVE_STATIC_DIR`.
|
|
- **`target`** — destination path within the merged tree, used as both
|
|
the served URL prefix (`/<target>/…`) and the on-disk layout.
|
|
Defaults to the attribute name. Forward slashes create nested layouts
|
|
(`"games/bitburner"` serves at `/games/bitburner/…`).
|
|
|
|
Constraints: `target` must start with an alphanumeric or `_` and
|
|
contain only alphanumerics, `_`, `.`, `/`, `-`. `..` segments are
|
|
rejected by a config assertion. The merge step refuses to overwrite
|
|
files already present in the default dist — pick a target name that
|
|
does not collide with existing paths (`static/`, `index.html`, etc.).
|
|
|
|
The default dist ships at `hyperhive.frontend.dist` (the
|
|
`hyperhive-frontend` package output, read-only). To replace the
|
|
entire UI rather than layer on top, override `frontend.dist` directly.
|
|
|
|
## Connectivity overrides
|
|
|
|
Two `hyperhive.forge.*` / `hyperhive.matrix.*` options override where
|
|
the per-agent daemons connect. Both rarely need changing on a standard
|
|
single-host deploy, but are useful for multi-hive or custom-network
|
|
setups.
|
|
|
|
```nix
|
|
hyperhive.forge.url = "http://forge.example:3000"; # default: null
|
|
hyperhive.matrix.url = "https://matrix.example"; # default: null
|
|
```
|
|
|
|
**`hyperhive.forge.url`** — base URL of the Forgejo instance. Used by
|
|
a one-shot boot unit (`tea-login`) that writes `~/.config/tea/config.yml`
|
|
directly from the agent's `forge-token`, so `tea` and `hive-forge`
|
|
work without an interactive auth step. The unit is a no-op when
|
|
`forge-token` is absent. Override when the agent should connect to a
|
|
Forgejo on a different host or port (e.g. a swarm peer's forge).
|
|
Validated: must be an `http://` or `https://` URL, or `null`.
|
|
|
|
**Defaults to `null`, meaning "no forge" — not a guessed address.** A
|
|
loopback default would only ever be correct when the forge shares the
|
|
agent's network namespace, and inside a container `localhost` is the
|
|
agent itself, so the default was a value that built fine and then talked
|
|
to the wrong machine. With `null` the `tea-login` and `forge-avatar-sync`
|
|
units are not generated at all: an absent integration rather than a
|
|
misdirected one. You do not normally set this — hive-c0re renders the
|
|
host's real forge URL into every agent, and refuses to write a meta
|
|
flake without one, so `null` only survives where the agent modules are
|
|
evaluated outside a hive.
|
|
|
|
**`hyperhive.matrix.url`** — homeserver URL used by
|
|
`hive-matrix-daemon` when connecting via the matrix-sdk. hive-c0re
|
|
writes it into every agent at deploy time as the gateway-routed
|
|
`chat.<swarm-domain>` URL, so isolated agents can reach the homeserver.
|
|
Override per-agent when an agent should talk to a different homeserver
|
|
— for example a remote hive's tuwunel reached over a VPN, or an
|
|
external Matrix server for a federation-only agent.
|
|
|
|
**Defaults to `null`, meaning "no matrix" — same reasoning as
|
|
`forge.url` above** (a loopback default would resolve inside the
|
|
agent's own netns to the agent itself, not the homeserver). With
|
|
`null` the daemon has no homeserver and no-ops exactly as it does
|
|
without a token. The hive only forwards `HIVE_MATRIX_URL` when it
|
|
actually has a matrix vhost to name, so `null` survives where a hive
|
|
runs no homeserver, or where the agent modules are evaluated outside a
|
|
hive.
|
|
|
|
## Claude Code plugins
|
|
|
|
The harness installs Claude Code plugins before the serve loop opens.
|
|
Three per-agent `agent.nix` options control this:
|
|
|
|
```nix
|
|
hyperhive.claudeMarketplaces = [ # default
|
|
"anthropics/claude-plugins-official"
|
|
"${hyperhive.packages.claude-plugins}" # hive's own local marketplace, registered as `hyperhive`
|
|
];
|
|
hyperhive.claudePlugins = [ # default
|
|
"skill-creator@claude-plugins-official"
|
|
"base@hyperhive"
|
|
];
|
|
hyperhive.claudePluginsAutoUpdate = false; # default
|
|
```
|
|
|
|
- **`claudeMarketplaces`** — list of marketplace sources passed to
|
|
`claude plugin marketplace add <source>`. Defaults to Anthropic's
|
|
official marketplace plus hyperhive's own `claude-plugins` nix
|
|
package (see `nix/packages/claude-plugins.nix`) — a local-path
|
|
marketplace registered under the name `hyperhive`, so a hive-authored
|
|
skill needs no forge repo or git remote to ship. Override or extend
|
|
to add custom marketplaces. Idempotent — re-adding an existing
|
|
source is a no-op.
|
|
- **`claudePlugins`** — list of plugin specs passed to
|
|
`claude plugin install <spec>`. Each spec is installed on every boot
|
|
(`install` is expected to be idempotent); failures log a warning but
|
|
do not abort boot. Defaults to Anthropic's `skill-creator` (so every
|
|
agent can author, refine, and evaluate its own skills) plus
|
|
hyperhive's own `base` plugin — skills that apply to every agent
|
|
regardless of role (currently just `state-hygiene`) — all without
|
|
any per-agent wiring.
|
|
|
|
> Both plugin lists follow ordinary NixOS list-option semantics: a
|
|
> per-agent definition **replaces** the default, it does not extend it.
|
|
> An agent that sets `claudePlugins` and still wants the defaults has
|
|
> to list `skill-creator@claude-plugins-official` and `base@hyperhive`
|
|
> explicitly alongside its own entries — likewise for the two default
|
|
> entries in `claudeMarketplaces`.
|
|
- **`claudePluginsAutoUpdate`** — when `true`, runs
|
|
`claude plugin marketplace update` before installing plugins to pull
|
|
the latest index. Disabled by default to keep boot times short and
|
|
plugin versions pinned.
|
|
|
|
## `cargo.shortMessages`
|
|
|
|
```nix
|
|
hyperhive.cargo.shortMessages = true; # default
|
|
```
|
|
|
|
When enabled (the default), the harness injects a `cargo` shell
|
|
function into `/etc/hyperhive/bash-env.sh` that transparently appends
|
|
`--message-format short` to compile subcommands (`build`, `check`,
|
|
`clippy`, `test`, `run`, `doc`, `bench`, `install`, `rustc`, `fix`).
|
|
This suppresses the per-crate progress lines that flood the response
|
|
window, leaving only warnings and errors.
|
|
|
|
The function handles `+toolchain` selectors (`cargo +nightly build`)
|
|
and passes through cleanly when `--message-format` is already present.
|
|
Non-compile subcommands (`new`, `add`, third-party `cargo-*`) are
|
|
left untouched.
|
|
|
|
Set to `false` for agents that parse cargo's JSON output
|
|
programmatically and do not pass `--message-format json` themselves.
|
|
|
|
## API-key backend (`useApiKey` / `backendEnvironmentFile`)
|
|
|
|
```nix
|
|
hyperhive.useApiKey = true; # default: false
|
|
hyperhive.backendEnvironmentFile =
|
|
"/agents/myagent/harness/openrouter.env"; # default: null
|
|
hyperhive.model = "anthropic/claude-3.5-sonnet"; # provider-specific model string
|
|
```
|
|
|
|
Runs this agent's `claude` against an API-key backend (e.g. OpenRouter)
|
|
instead of a Claude subscription via OAuth. Two options, paired — each
|
|
is a no-op without the other:
|
|
|
|
- **`useApiKey`** tells the harness itself not to wait for a Claude OAuth
|
|
session: at boot, `LoginState::from_dir` reports `Online` without
|
|
checking `~/.claude/` (`hive_agent::login::using_api_key`, reads
|
|
`HIVE_USE_API_KEY`), and the fact is stamped into the consolidated
|
|
harness state file so the operator dashboard also stops reading this
|
|
agent's empty `~/.claude/` as "needs login". An api-key agent that hits
|
|
a real 401 (the key itself is bad) still surfaces `needs_login` — only
|
|
the boot-time "have I ever logged in" check is bypassed, not the
|
|
auth-failure path.
|
|
- **`backendEnvironmentFile`** points at an operator-managed file
|
|
(outside the nix store, one `KEY=value` per line, systemd
|
|
`EnvironmentFile` syntax) supplying the credentials `claude` itself
|
|
reads from the environment — typically `ANTHROPIC_API_KEY` and
|
|
`ANTHROPIC_BASE_URL`. Loaded as an *optional* `EnvironmentFile`
|
|
(leading `-`), so setting the option before the file exists doesn't
|
|
strand the harness at boot.
|
|
|
|
Provision the file once, out of band (never through nix — an API key in
|
|
the store is world-readable and travels with the flake closure):
|
|
|
|
```sh
|
|
# on the host, once per agent that should use an api-key backend
|
|
sudo install -m 0600 -o root /dev/stdin \
|
|
/var/lib/hyperhive/agents/<name>/harness/openrouter.env <<KEYS
|
|
ANTHROPIC_BASE_URL=https://openrouter.ai/api/v1
|
|
ANTHROPIC_API_KEY=sk-or-...
|
|
KEYS
|
|
```
|
|
|
|
The file lives in the agent's bind-mounted **harness** dir, not `state/`
|
|
— `harness/` survives container rebuilds exactly like `state/` does, but
|
|
(unlike `state/`) is never bind-mounted into a parent agent's container
|
|
(see `docs/persistence.md`'s "Parent access to child state"), so an API
|
|
key placed here is reachable by nothing but this agent and the host.
|
|
|
|
⚠️ Verified end-to-end against OpenRouter has not happened as of this
|
|
writing — `ANTHROPIC_BASE_URL` support in the shipped Claude CLI is
|
|
documented behavior, not something this hive has run a live turn
|
|
against yet. Tool use, streaming, and MCP all need to keep working
|
|
through a non-Anthropic base URL; treat the first real agent on this
|
|
path as the actual verification, not this doc.
|
|
|
|
Switching an already-provisioned OAuth agent to `useApiKey` leaves
|
|
`~/.claude/credentials.json` in place but unused — harmless, not
|
|
cleaned up automatically. Cost shape also changes: subscription pricing
|
|
→ per-request billing with no built-in monthly cap, worth knowing before
|
|
pointing a busy agent at a metered backend.
|
|
|