Skip to content

Latest commit

 

History

History
139 lines (108 loc) · 30.9 KB

backend-setup.md

File metadata and controls

139 lines (108 loc) · 30.9 KB

Agent backend setup

Hive validates backend names in src/pkg/config and launches CLIs in src/pkg/agent/manager.go. backend: selects the runtime for an agent; inference backends are covered separately in inference-backends.md. The acceptance bar for adding a new CLI backend, and which support tier it lands in, is in backend-support-tiers.md. That policy also defines the metering requirement for budget-gated hives and the deprecation path when upstream CLI drift breaks a backend.

CLI backends

Backend Binary launched by the Go manager Auth / setup Notes
claude claude Install Claude Code and log in once. Hive launches with --dangerously-skip-permissions; inference routes add --bare --settings. The per-agent reasoning_effort (low|medium|high|xhigh|max, settable in hive config and the dashboard - see agent-configuration.md) is passed as --effort <v> since #8377; unset means no flag and Claude Code's own default. AGENT_REASONING_EFFORT is the contributor-relay spelling of the same control. Advisory/issue modes add disallowed GitHub MCP tools. Every mode also denies host-state commands — privilege escalation (sudo/pkexec/doas/su) and boot/deployment tools (rpm-ostree/bootc/ostree/grubby/bootctl/efibootmgr) — because the tmux path runs unconfined on the operator's host (#4918). Set HIVE_CLAUDE_DANGEROUSLY_ALLOW_HOST_STATE=1 only when you intentionally want an agent to manage host state.
litellm claude Not a separate CLI: it launches the claude binary pointed at a LiteLLM proxy via ANTHROPIC_BASE_URL. Set HIVE_LITELLM_ENDPOINT (and HIVE_LITELLM_API_KEY if the proxy requires one); no separate login. Inherits claude's confinement posture — just contribute-hive litellm local uses Claude Code's native OS sandbox. The dashboard's /contribute page also offers this backend under four flavor names — see LiteLLM flavors on /contribute.
copilot copilot Install GitHub Copilot CLI and authenticate with GitHub. On a hive, use the Login button on a copilot agent's dashboard card: it runs a GitHub device-flow login (POST /api/copilot-auth/start, pkg/dashboard/copilot_auth.go) and stores the token durably at /data/copilot-user-token, shared by every copilot agent on that hive. COPILOT_GITHUB_TOKEN is honored as an env-var alternative. Hive also probes Copilot model entitlements live (your plan's /models on the account's API host), so the model picker only offers models your subscription can actually use. Launched with --no-auto-update --allow-all; write tools are denied by mode when needed. Copilot is a CLI backend, not a Model Gateway — it will not appear under Governor Config → Model Gateways (see inference-backends.md).
gemini gemini Install Gemini CLI and configure its normal auth/API key. Supported by the server-side manager; Hive launches gemini and passes --model when a model is configured.
goose goose Install Goose from its canonical upstream and configure provider/model (GOOSE_PROVIDER, GOOSE_MODEL, or goose configure). Hive launches goose run -s and appends --model when set.
pi goose in the Go manager; pi in contributor scripts Contributor mode requires AGENT_MODEL=provider/model plus that provider's official credential variable or ~/.pi/agent/auth.json. In the server-side manager, backendBinary("pi") maps to Goose. Contributor Pi supports interactive and headless (--print --mode json) delivery. No generic Pi key/provider variable exists.
pi + Kiro goose in the Go manager; pi in contributor scripts Set KIRO_API_KEY and use the Pi Kiro provider model id shape, for example AGENT_MODEL=kiro-api-key/claude-opus-5:high. Hive forwards KIRO_API_KEY into contributor containers and the dashboard's pi model picker includes common kiro-api-key/* IDs as a non-authoritative fallback. This is the supported Kiro path for now instead of a first-class kiro-cli backend: Kiro's stable unattended/trust/login CLI contract is not verified in Hive, while pi + pi-kiro-api is already the adopter-proven path. Quota headroom remains separate from the anthropic pool until the Kiro quota work in #8726 lands.
bob bob Provide HIVE_BOB_API_KEY or /secrets/bob_api_key for pods; contributor mode requires BOBSHELL_API_KEY. Hive uses API-key auth headlessly and accepts the Bob license at launch.
codex codex Install @openai/codex and run codex login --device-auth for subscription/OAuth auth. The CLI stores credentials in CODEX_HOME/auth.json (default ${HOME}/.codex/auth.json); API-key mode can use CODEX_API_KEY/OPENAI_API_KEY or a populated auth file, but it is not required for subscription users. Hive gives each agent its own CODEX_HOME and probes auth.json for OAuth tokens/API-key state (or API-key env presence). Contributor mode keeps --ask-for-approval on-request, grants the exact HIVE_WORKSPACE_DIR tree with --add-dir, and defaults approvals_reviewer to auto_review so an unattended task never waits on the contributor. The --sandbox value is resolved at launch rather than fixed (#6653): workspace-write wherever bubblewrap can actually create the user namespace it needs — local mode, and containers started with a relaxed seccomp profile — and danger-full-access only inside the contributor container when that namespace is denied, where the container is already the boundary and asking for a nested one failed every command. Override with HIVE_CODEX_APPROVAL_POLICY/HIVE_CODEX_SANDBOX_MODE/HIVE_CODEX_APPROVALS_REVIEWER, or set HIVE_CODEX_DANGEROUSLY_BYPASS_APPROVALS_AND_SANDBOX=1 only when you intentionally want the old bypass posture. AGENT_REASONING_EFFORT is passed to Codex as -c model_reasoning_effort="..." on the contributor-relay path; server-launched agents use the per-agent reasoning_effort config field (minimal|low|medium|high|xhigh) the same way since #6163.
aider contributor scripts launch aider; the server-side Go manager does not launch it Install Aider and configure its provider/API key normally for contributor mode. Not supported as a server-side agent backend in this branch: config accepts the name, but backendBinary("aider") returns unknown backend: aider, so a pod agent will not start. Use contributor mode for Aider.
agy agy Install the Antigravity CLI (brew install --cask antigravity-cli) and run agy once to sign in interactively with a Google account. There is no API-key mode. agy persists OAuth state under ~/.gemini (oauth_creds.json with a refresh token, google_accounts.json, alongside the antigravity-cli/ state dir) — just contribute-hive agy stages that whole directory into the container, though whether a staged credential actually re-authenticates an unattended agy has not been confirmed end-to-end (agy's binary also links an OS-keyring client, so some auth paths may need a running Secret Service the container does not provide). No OS-level sandbox of its own (same posture as goose/bob/pi/aider — see sandbox-isolation.md). Container mode is the only mode with any host boundary and is supported: src/Dockerfile.contributor installs the agy binary from Google's published, checksummed release tarball (#5048; it did not before). Local mode refuses to launch agy without HIVE_AGY_DANGEROUSLY_RUN_UNCONFINED=1. Hub-managed agy agents default to Hive's headless shim: the tmux pane stays at a shell prompt and each kick runs one agy turn through hive agy-turn, so the upstream interactive TUI wake loop in google-antigravity/antigravity-cli#945 is not resident between or during turns. The runner sends the prompt to agy on stdin (--input-format stream-json, so no argv size limit) and resumes the agent's own conversation by id (--conversation), recorded in a per-launch file; -c is not used because all agents share one agy conversation store. A restart, or clear_on_kick, starts a new conversation. The pane shows assistant text and one line per tool call. Set HIVE_AGY_LAUNCH_MODE=interactive (or tui) on the hive process only when you explicitly need the old attachable TUI. Both modes pass --dangerously-skip-permissions (same contract as claude, or agy blocks on a per-tool approval prompt nobody is attached to answer). When a model is configured the manager appends --model <m> --effort <e>: agy requires --effort alongside --model and otherwise ignores the model entirely. An unrecognised model is not fatal — agy warns and falls back to its own default. Since #6163 the effort is the agent's per-agent reasoning_effort (low|medium|high, settable in hive config and the dashboard - see agent-configuration.md) when it is a value agy accepts; anything else (unset, or codex-only values like xhigh) falls back to low, the default agy itself uses. AGENT_REASONING_EFFORT is the contributor-relay spelling of the same control. Headless (agy -p) is verified on a host that has already signed in; whether it works unattended in a fresh container is unverified, which is also why agy stays out of just contribute-k8s's headless-pod allowlist — a pod cannot complete the interactive sign-in even once. agy also exits 2 if the working directory does not resolve, where some other backends tolerate it. agy 1.1.22's own --sandbox flag is not a local OS boundary — see config/backends.conf's "no confinement mechanism" section for why.
opencode opencode Install the opencode CLI (opencode.ai/docs) and run opencode auth login; the credential is written to ~/.local/share/opencode/auth.json. Provider-agnostic (75+ providers) — the model provider is configured in opencode's own config/auth, not in Hive, so AGENT_MODEL is passed through as provider/model on the relay path (e.g. export AGENT_MODEL=anthropic/claude-sonnet-4-6). Contributor relay only; headless mode only. Dispatches through opencode run "<prompt>" --auto under CONTRIBUTOR_MODE=headless; there is no interactive-tmux wiring for opencode, so CONTRIBUTOR_MODE=interactive does not apply to it. backend_perm_flag maps opencode to --auto, opencode's unattended auto-approve flag. Confinement note: opencode has no OS-enforced filesystem sandbox of its own. just contribute-hive opencode local narrows it with a host-state command deny-list only (via opencode's own permission.bash config, the same command family the claude deny-list covers) — a floor, not a sandbox boundary. Container mode is the default and the stronger boundary. See sandbox-isolation.md for the full per-backend matrix. Set HIVE_OPENCODE_DANGEROUSLY_ALLOW_HOST_STATE=1 to drop the deny-list. Not yet in just contribute-k8s's headless-pod allowlist: whether the auth credential supports unattended use in a fresh pod is unverified, so it currently runs headless only on a host that has already signed in (same posture as agy).
kilo kilo Install @kilocode/cli (pinned via KILO_CLI_VERSION in src/Dockerfile.contributor, currently 7.5.6) and set credentials as environment values only — KILO_AUTH_CONTENT or KILO_CONFIG_CONTENT, or KILO_API_KEY (optional KILO_ORG_ID). No Kilo config directory is mounted; the Justfile's PROVIDER_ENV_ARGS mechanism forwards these four variables to the container by name, so the values themselves never appear in the container runtime's argv. Contributor relay only; headless mode only (CONTRIBUTOR_MODE=headless; no interactive-tmux wiring). Dispatches through kilo run "<prompt>" --auto (optional --model provider/model). backend_perm_flag maps kilo to --auto, kilo's unattended auto-approve flag. Confinement note: kilo has no OS-enforced sandbox and no command deny-list floor in config/backends.conf — --auto approves prompts, it is not a boundary. Local mode therefore refuses to launch kilo without HIVE_KILO_DANGEROUSLY_RUN_UNCONFINED=1, the same #4918 refusal gate as goose/agy/bob/pi/aider (unlike opencode, no host-state denylist exists for it — whether kilo honors an OPENCODE_PERMISSION-style config is unverified). Treat it as fully unconfined, same posture as goose/bob/pi/aider (see sandbox-isolation.md). Kilo is intentionally excluded from just contribute-k8s's headless-pod allowlist (HEADLESS_BACKENDS="claude litellm copilot codex goose"), pending independent credential and confinement verification.
openhands openhands Install the OpenHands CLI on the host: uv tool install openhands --python 3.12 (PyPI package openhands, MIT; docs.openhands.dev). Credentials are environment values: LLM_API_KEY, optional LLM_BASE_URL (OpenAI-compatible gateway), and the model as AGENT_MODEL=provider/model (any litellm model id, forwarded to the CLI as LLM_MODEL); alternatively run openhands once interactively, which persists them under ~/.openhands/settings.json (OPENHANDS_PERSISTENCE_DIR overrides the directory). Contributor relay only; headless mode only (CONTRIBUTOR_MODE=headless; no interactive-tmux wiring). Dispatches through openhands --headless -t "<prompt>" --always-approve --override-with-envs. --always-approve is OpenHands' unattended auto-approve flag (headless mode forces it regardless); --override-with-envs is required because the CLI otherwise ignores LLM_* environment variables in favour of its persisted settings. OpenHands has no --model flag, so hive never passes one. Confinement note: the bare openhands binary runs the agent directly on the host with no sandbox, allowlist, or deny-list hive can wire (OpenHands' Docker sandbox exists only behind openhands serve/Agent Canvas, which have no one-shot task shape), so local mode refuses to launch without HIVE_OPENHANDS_DANGEROUSLY_RUN_UNCONFINED=1 — the same #4918 refusal gate as goose/agy/bob/pi/aider/kilo/omp. Not in the contributor image (src/Dockerfile.contributor is Debian bookworm with Python 3.11; OpenHands needs 3.12), so container mode needs a derived image with the CLI installed (the launcher forwards LLM_API_KEY/LLM_BASE_URL/LLM_MODEL and mounts a staged copy of ~/.openhands when settings.json exists), and openhands is excluded from just contribute-k8s's headless-pod allowlist. Status: upstream marks the OpenHands CLI repository as no longer actively maintained in favour of Agent Canvas; the CLI is still published (1.16.0 at the time of wiring) and this backend is T3 experimental.
muse muse Install Muse Code with `curl -fsSL https://dev.meta.ai/install.sh bash for host use. Both images install muse instead from its release manifest, pinned by version and per-arch SHA-256 (MUSE_VERSION/MUSE_SHA256_*insrc/Dockerfileandsrc/Dockerfile.contributor) — the public installer is deliberately not used in a build, because its launcher resolves the release at runtime and verifies a checksum only when the server volunteers one. Note the binary is ~250-265 MB per arch, the largest CLI layer in either image. Authenticate with export META_API_KEY=..., or run muse login/muse auth set --api-key-stdin, which writes ~/.config/muse/auth.json; muse documents META_API_KEYas always taking priority over the account login. Set the model withexport AGENT_MODEL=—GET https://api.meta.ai/v1/models` returns the catalog. Query that endpoint from the machine that will actually run muse: the catalog is caller-dependent. Measured 2026-09-08 with one and the same key, a workstation saw seven ids (including muse-spark-1.3-contributor) while a container in AWS saw only four — muse-image-1.0, muse-spark-1.2-contributor, muse-spark-1.2, muse-spark-1.1. Requesting a model the caller cannot see fails at task time with model `…` does not exist or you lack access. Note also that muse does not reliably reject a bad model id up front: with a wholly invalid id, the prompt hi completed normally and exited 0 (3/3 trials) while say ok exited 1 — so a mistyped or unentitled model can pass a trivial smoke test and only fail on real work. Verify the id against the catalog rather than against a test run. AGENT_REASONING_EFFORT maps to --reasoning-effort (`none
omp omp Hub agents: install Oh My Pi in the hive image (the hub src/Dockerfile now carries the same pinned/checksummed OMP_VERSION layer as the contributor image) and sign in per agent/provider under that agent's durable /data/home/agents/<name>/.omp/agent state. The dashboard offers omp as a method, discovers models with omp models --json, and keeps each model's thinking levels as the only valid reasoning_effort values. Contributor mode: install Oh My Pi and sign in once on the host (run omp, complete its provider setup, quit). omp keeps that sign-in under ~/.omp/agent — config.yml plus the agent.db SQLite store whose auth_credentials rows hold each provider's OAuth record or API key; there is no auth.json — and container mode stages an allowlist of that directory into the throwaway CLI staging copy, keeping only the selected provider's credential rows (AGENT_MODEL=provider/model, otherwise the providers config.yml's modelRoles name), the same least-privilege rule as pi (#7678). A provider API key exported in your shell (ANTHROPIC_API_KEY, OPENAI_API_KEY, …) is forwarded as well. just contribute-setup omp reports which providers are signed in and which the container will receive; if none is, the container opens on omp's setup wizard and the relay waits at it (a sign-in completed there is discarded with the container). The preflight verifies the binary and the stored credentials' presence only: no generic probe proves authentication. OAuth refresh and the staged copy (#7922): OAuth refresh tokens are single-use, so a container that refreshed its staged copy left the host's row holding a revoked token — omp on the host then failed to refresh, and every later launch staged the dead row, which omp reports as No API key found for <provider> before falling back to any provider that still lists a model (on the observed host, an unreachable local ollama) while the relay kept reporting the selected model. Two guards now cover this: just contribute-hive omp writes the container's newer credential row back into ~/.omp/agent/agent.db every HIVE_OMP_CREDENTIAL_SYNC_SECONDS (default 300; 0 for exit-only) while the container runs and once more when it exits (bin/omp-backend.js --sync-back — only the selected provider's existing row, only its credential columns, only when strictly newer; config.yml and other rows never travel back), and --stage/--describe refuse to launch on a row omp has marked disabled_cause, printing the cause and pointing at omp → /login on the host. A container killed mid-run can still lose a refresh since its last timer pass; if omp on the host then reports a refresh failure, sign in again there. Two containers running from one host store at the same time still race each other's refreshes; give each its own sign-in. Contributor relay interactive mode only. Hive starts ordinary omp --model <id> in its prepared tmux cwd, with no fabricated permission flag. OMP is excluded from the TTY-less K8s allowlist until its one-shot invocation, exit semantics, fresh-pod credentials, and Hive completion contract are demonstrated. OMP exposes no verified local sandbox or deny-list, so local mode refuses unless HIVE_OMP_DANGEROUSLY_RUN_UNCONFINED=1; container mode is the supported boundary, and the contributor image ships a pinned, checksummed omp (OMP_VERSION in src/Dockerfile.contributor, #7661) so just contribute-hive omp runs without an omp on the host.

LiteLLM flavors on /contribute

The dashboard's /contribute page lists four options that are UI flavors of the litellm backend, not separate backends: OpenRouter (Claude Code + your key), vLLM (self-hosted), llm-d (self-hosted), and watsonx.ai (IBM Granite + your key). The generated commands for all four say contribute-setup litellm — the Justfile only accepts litellm (#6821) — and the flavors differ only in the environment exports placed before that command:

/contribute flavor HIVE_LITELLM_ENDPOINT Extra exports
OpenRouter https://openrouter.ai/api/v1 HIVE_LITELLM_API_KEY (your OpenRouter key); pick any OpenRouter model ID via the Model field (exported as AGENT_MODEL)
vLLM (self-hosted) http://your-vllm-host:8000/v1 HIVE_LITELLM_API_KEY only if your server needs one
llm-d (self-hosted) http://your-llm-d-host:8000/v1 HIVE_LITELLM_API_KEY only if your endpoint needs one
watsonx.ai https://us-south.ml.cloud.ibm.com/ml/gateway/v1 HIVE_LITELLM_API_KEY (IBM Cloud API key) and WATSONX_PROJECT_ID. watsonx auth is an IAM-minted JWT, not a raw bearer key — your local Claude-Code setup or a small local proxy handles the token exchange.

Everything in the litellm row above applies to all four: the binary launched is claude, the confinement posture is claude's, and the flavor names sit inside the headless K8s allowlist only because they resolve to litellm before the allowlist check.

Do not confuse the watsonx.ai flavor with the bob backend. The watsonx.ai flavor is the watsonx.ai inference gateway (an OpenAI-compatible endpoint serving IBM Granite models) reached through Claude Code + LiteLLM. bob is IBM's watsonx Code Assistant CLI — a separate coding CLI with its own auth (HIVE_BOB_API_KEY/BOBSHELL_API_KEY, see the bob row above).

Backends excluded from the headless K8s allowlist

just contribute-k8s runs backends in a TTY-less pod and only permits the backends in its HEADLESS_BACKENDS allowlist, currently claude litellm copilot codex goose (the contribute-k8s HEADLESS_BACKENDS allowlist in the Justfile). agy, opencode, kilo, muse, omp, and openhands are deliberately excluded: their credentials are not verified for unattended use in a fresh pod. OMP additionally remains interactive-only until the contributor relay's one-shot invocation, meaningful exit status, and completion contract are proven end to end.

If you need one of the excluded backends, either choose a supported headless backend, or run it attended on the container or local path (just contribute-hive <backend>), where an operator can complete an interactive sign-in once. Tracking issue: #5406. Whether these backends can run headless at all remains an open question, so the allowlist is a deliberate gate rather than an oversight.

IBM Bob headless setup

backend: bob launches IBM bobshell (bob), the IBM watsonx Code Assistant CLI. In a Hive pod or contributor container it must use API-key auth: the default IBMid/W3ID browser SSO flow opens a browser and waits on a localhost callback, which a headless pod cannot satisfy, then times out after about three minutes. Hive checks for a key before launch and parks the agent with an actionable error instead of burning that timeout.

Configure the key in one of these ways:

governor:
  bob:
    api_key_env: HIVE_BOB_API_KEY       # hive-side env var name
    api_key_file: /secrets/bob_api_key  # mounted Secret path

Defaults are already wired: Hive consults /secrets/bob_api_key, then /data/secrets/bob_api_key (where the dashboard's Governor → Bob tab stores a key), then the HIVE_BOB_API_KEY environment variable. Use the dashboard tab when you do not have cluster Secret access; it writes the key to the PVC-backed /data/secrets/bob_api_key and relaunches parked bob agents. The value is injected into bob as BOBSHELL_API_KEY, and Hive launches bob with the hidden-but-supported --auth-method api-key flag plus full approval/trust flags for unattended operation. Store only the location in YAML, never the key value.

Contributor relay containers use the same bobshell package, but contributor-mode scripts expect BOBSHELL_API_KEY in the container environment when AGENT_BACKEND=bob.

The dashboard Test key probe intentionally sends User-Agent: bobshell. IBM's edge has been observed to block generic Go/curl user agents with an HTML 403 before the request reaches bob auth, while the bobshell UA returns the real backend verdict. If you reproduce a key test manually, use that UA or treat a generic-UA 403 as an inconclusive edge block, not proof that the key is invalid.

Goose upstream and unattended operation

Goose's canonical repository and releases are now aaif-goose/goose, following Goose's move from Block to the Agentic AI Foundation. Hive tracks that Goose upstream as an independent CNCF project; this is not AAIF membership, hosting, or endorsement. Both Hive images and src/scripts/cli-pin-bump.sh use that release source; the version and per-architecture SHA256 pins remain in the Dockerfiles.

See Running Goose unattended at scale with Hive for headless invocation, environment-key credentials, and the local unconfined refusal gate. Goose upstream tracking and the documentation contribution gate are covered in the landscape.

Contributor relay image

src/Dockerfile.contributor builds the ClankeR image used by just contribute-hive. It installs Claude Code, Copilot, Codex, Bob, Goose, Pi, gh, Go, tmux, and the relay scripts. src/compose-contributor.yaml runs that image with your local Hive config and selected backend. It mounts ${HOME}/.config/hive, ${HOME}/.claude, and ${HOME}/.config/claude-code read-only, then reads the registered HIVE_HUB and HIVE_REGISTRATION_TOKEN from ${HOME}/.config/hive/contributor.env inside the container.

AGENT_BACKEND=claude just contribute-hive
AGENT_BACKEND=goose GOOSE_PROVIDER=anthropic GOOSE_MODEL=claude-sonnet-4-6 just contribute-hive
AGENT_BACKEND=pi AGENT_MODEL=openai/gpt-5 OPENAI_API_KEY=... CONTRIBUTOR_MODE=headless just contribute-hive
AGENT_BACKEND=litellm HIVE_LITELLM_ENDPOINT=https://litellm.example.com just contribute-hive

AGENT_BACKEND selects the CLI, AGENT_MODEL optionally pins the model, and CONTRIBUTOR_MODE defaults to interactive (tmux with a TTY). For Pi, AGENT_MODEL is required and must be the canonical provider/model token; this is a contributor preference, not task routing or assignment state. The same token is used for initial launch, restart, reconnect evidence, and headless execution. For Codex, agy, muse and Claude Code, AGENT_REASONING_EFFORT optionally pins the reasoning effort (each backend's own accepted set; see the table above). CONTRIBUTOR_MODE=headless is reserved for one-shot/no-TTY task delivery.

Pi credentials remain in the selected provider's official environment variable (OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, and so on) or Pi's ~/.pi/agent/auth.json. Hive never maps a generic PI_API_KEY, never puts a credential value in argv, passes only the selected provider's variables into its contributor container, and removes unrelated providers from the ephemeral auth/models profile mounted there. Readiness is deliberately staged: pi_binary, pi_configuration, pi_authentication, and pi_invocation appear in relay capability/status JSON. A present key or auth-file entry reports configured_unverified; only a successful real invocation advances authentication to verified and invocation to succeeded, because pi --version plus a non-empty key is not authentication proof.

Headless Pi cancellation is bounded: revocation terminates the active child and fences its late exit from completing a newer task generation. Interactive Pi still uses tmux delivery and is not cancellation-conformance-proven.

Both contributor modes are unattended from Codex's perspective: Hive may deliver work when nobody is watching the tmux pane. The default automatic reviewer evaluates only actions that already cross the sandbox boundary. It does not widen that boundary, and the dangerous no-sandbox mode remains opt-in. Where the sandbox resolves to danger-full-access — the contributor container whose runtime denies user namespaces (#6653) — there is no boundary left for Codex to ask about, so the reviewer simply never fires; the container itself is what bounds the agent there. A denied or timed-out automatic review returns to Codex; in headless mode a non-zero terminal result is reported to Hive with a bounded, token-redacted diagnostic rather than waiting for input.

just contribute-check <backend> runs a read-only preflight before registration. It checks that the chosen CLI exists and that obvious auth prerequisites are present.

Secrets

Store secret values outside hive.yaml. YAML should contain env var names or key-file paths, not keys. The dashboard and config save path rewrite YAML, so a literal secret in YAML would be persisted in plaintext.