feat(#493): api-key backend support (useApiKey + backendEnvironmentFile)

This commit is contained in:
damocles 2026-08-26 22:22:47 +02:00 committed by mara
commit 535ba0c11c
6 changed files with 197 additions and 14 deletions

View file

@ -106,6 +106,60 @@ in
'';
};
options.hyperhive.useApiKey = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Authenticate this agent's `claude` invocations with an API key
(`ANTHROPIC_API_KEY`/`ANTHROPIC_BASE_URL`, e.g. OpenRouter) rather
than a Claude OAuth session. Sets `HIVE_USE_API_KEY=1`, which the
harness reads (`hive_agent::login::using_api_key`) to report
`LoginState::Online` at boot without checking `~/.claude/` an
api-key agent has no OAuth session to wait for, so it must never
park the turn loop expecting one. Also stamped into the consolidated
harness state file so hive-c0re's dashboard stops reading an empty
`~/.claude/` as "needs login" for this agent (see
`hive_c0re::container_view`'s `needs_login` computation).
Set this AND `hyperhive.backendEnvironmentFile` together this
option changes what the harness believes about its own login state,
the other actually supplies the credentials `claude` reads. Neither
is useful alone.
'';
};
options.hyperhive.backendEnvironmentFile = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/agents/myagent/state/openrouter.env";
description = ''
Path (outside the nix store) to a systemd `EnvironmentFile` loaded
by the harness service the mechanism for supplying
`ANTHROPIC_API_KEY`/`ANTHROPIC_BASE_URL` (or any other backend
credential `claude`/the harness reads from the environment) without
baking a secret into the nix store.
The file must use systemd `EnvironmentFile` syntax: one `KEY=value`
pair per line, no `export`, no shell quoting needed for simple
values. Example contents:
```
ANTHROPIC_API_KEY=sk-or-v1-...
ANTHROPIC_BASE_URL=https://openrouter.ai/api/v1
```
Place the file inside the agent's bind-mounted state dir (e.g.
`/agents/<name>/state/openrouter.env`) so it survives container
rebuilds; permissions should be `0600`, owned by the agent's unix
user. Loaded with a leading `-` (optional `EnvironmentFile`), so a
path that doesn't exist yet an operator setting this option
before creating the file, or a fresh host rebuild before state is
restored makes systemd skip it rather than refuse to start the
harness. See `hyperhive.useApiKey`'s doc for the option this one is
paired with.
'';
};
options.hyperhive.extraWebProxies = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = { };
@ -231,6 +285,11 @@ in
# reverse-proxies. See `hyperhive.extraWebProxies` option
# and `web_ui/proxy.rs::extra_proxy_service`.
HIVE_EXTRA_WEB_PROXIES = builtins.toJSON config.hyperhive.extraWebProxies;
}
// lib.optionalAttrs config.hyperhive.useApiKey {
# Tells the harness not to wait for a Claude OAuth session — see
# `hyperhive.useApiKey`'s own description for the full mechanism.
HIVE_USE_API_KEY = "1";
};
serviceConfig = {
ExecStart = "${config.hyperhive.packages.hive-agent}/bin/${binary}";
@ -246,6 +305,11 @@ in
RuntimeDirectory = "hive-config";
User = userName;
Group = userName;
}
// lib.optionalAttrs (config.hyperhive.backendEnvironmentFile != null) {
# See `hyperhive.backendEnvironmentFile`'s own description for
# the file shape and the leading-`-` rationale.
EnvironmentFile = "-${config.hyperhive.backendEnvironmentFile}";
};
};
};