Agent Configuration
A hive agent is a long-running AI worker — a CLI session the hive keeps alive in tmux, kicks on a cadence with a work prompt, and watches for stalls, rate limits, and login expiry. An agent’s configuration is YAML entry under agents: in hive.yaml: it names the agent, picks the engine that powers it (a subscription CLI or a self-hosted inference endpoint), and declares how it behaves. Everything else — cadences, models, pins, ACMM level — layers on top.
Start with a name, a method, and a model. Add the rest when the agent needs it.
The smallest agent that works
agents:
scanner:
backend: copilot
model: claude-sonnet-4-6
That is a complete, valid agent. Defaults fill in the rest at load time:
enabled: true(unless you explicitly writeenabled: false)clear_on_kick: true— the session context is cleared before each kickidandroledefault to the agent’s name (scanner)bead_role: worker,beads_dir: /data/beads/scanner- Well-known names (
scanner,ci-maintainer,architect,supervisor,sec-check,quality,guide,strategist,outreach) also get a default emoji, color, aliases, and lane keywords, so a barescanner:entry already shows up in the dashboard as 🔍 with sensible triage keywords.
You almost never write a full roster by hand: applying an ACMM level (below) generates for you, and the dashboard edits it live.
Where configuration lives
Hive’s config is layered, and the layering is the point: a file’s location says who owns the setting.
/etc/hive/hive.yaml ← ConfigMap seed (Kubernetes) or bind mount (Docker/LXC).
│ The operator/platform layer. Re-seeded on every pod
│ boot; authoritative for acmm_level and hub.is_public.
├── /data/hive.yaml.dashboard ← Dashboard overlay on the PVC. Every save from the
│ dashboard UI lands here, secret-free, and is merged
│ over the ConfigMap seed at the next boot. Wins for
│ everything except the two ConfigMap-owned keys.
├── /data/agent-configs/ ← <name>.yaml per dashboard-managed agent
│ (created, imported, or generated by an ACMM pack).
│ Merged over the agents: map at load time.
├── /data/hive.yaml.bak ← Rolling disaster-recovery backup. Never edit;
│ the entrypoint restores from it if the seed is lost.
├── /data/secrets/ ← Secret VALUES written by the dashboard (writable PVC).
│ /secrets/ ← Secret VALUES from Kubernetes Secret mounts (read-only).
└── /data/policies/agents/ ← Kick templates and per-agent policy Markdown.
Read the tree top to bottom and you can answer “who set this?” for any value:
- The platform owns the seed. In Kubernetes, an init container re-copies the ConfigMap to
/etc/hive/hive.yamlon every boot. The entrypoint then merges the dashboard overlay over it — but the ConfigMap stays authoritative for the hub/admin-managed keys (acmm_level,hub.is_public). - You (via the dashboard) own the overlay. Every dashboard save writes
/data/hive.yaml.dashboard, so a LiteLLM endpoint or agent tweak survives pod restarts and upgrades. - Secrets never enter YAML.
hive.yamlstores env var names (api_key_env) and key file paths (api_key_file) — never key values. Values live in/data/secrets/(dashboard-entered) or/secrets/(Kubernetes Secret mounts). BecauseConfig.Save()writes the whole config back to disk, a key value in YAML would be persisted in plaintext — so the code refuses the pattern entirely.
Anatomy of an agent
Every field below exists in the config schema today. Grouped by what it does:
Identity — how the agent appears
agents:
scanner:
display_name: scanner # dashboard label (defaults to the YAML key)
description: "Triages issues and opens hold-gated fix PRs."
emoji: "🔍" # dashboard badge
color: "#3498db" # dashboard accent color
role: scanner # behavioral role; defaults to the agent name
sort_order: 20 # dashboard ordering (supervisors default to 0, others 100)
aliases: [sc] # short names accepted in dispatch/commands
Engine — what powers it
backend: copilot # the method: claude | copilot | goose | codex | pi |
# bob | aider, or an inference backend:
# vllm | llm-d | litellm
model: claude-sonnet-4-6 # model id for that method
cli_pinned: true # pin the CLI so nothing auto-switches it
launch_cmd: "/usr/bin/copilot --allow-all --model claude-sonnet-4-6"
# explicit launch command (optional — hive builds
# from backend + model + mode when omitted)
The dashboard also offers gemini as a live method (with live model discovery); as a persisted
backend:value inhive.yaml, stick to the validated list above.
Behavior — what it may do, and when
enabled: true # default true; set false to keep it configured but off
mode: ISSUES_AND_PRS # GitHub interaction tier: ADVISORY | ISSUES_ONLY |
# ISSUES_AND_PRS | ISSUES_PRS_MERGE
bead_role: worker # worker | supervisor (supervisors sort first,
# monitor the others); default worker
kick_template: scanner-holdgated.md
# named work-prompt template in the policies dir
include_repos: true # append the project repo list to each kick (default true): false # true = never kicked by the governor timer;
# triggered explicitly (e.g. inception)
clear_on_kick: true # default true; false keeps session context across kicks
stale_timeout: 28800 # seconds of silence before the agent counts as stale —
# must exceed its longest cadence
restart_strategy: immediate # how to bring a dead session back
beads_dir: /data/beads/scanner # work-record (bead) storage; default per-agent
lane_keywords: [bug, triage, fix] # routes matching issues into this agent's lane
detect_keywords: [scanner, triage] # attributes GitHub activity back to this agent
Declarative extensions
Three optional blocks replace hardcoded behavior with declarations:
channels: # how the agent gets triggered. Omit = governor timer.
- type: kick # kick | webhook | discord | schedule | bead
- type: schedule
schedule: "0 */4 * * *" # cron; required for type: schedule
tools: # tool permissions. Omit = the mode field governs.
preset: issues-only # advisory | issues-only | issues-prs | full
rules: # per-tool allow/deny overrides on top of the preset
- pattern: "mcp__github__create_issue"
action: allow
reason: "advisory issues are fine"
connections: # external integrations
- name: github-mcp
type: mcp # mcp | api | knowledge
uri: "stdio:///usr/local/bin/mcp-github"
Presets map modes (advisory denies issue and PR creation, issues-only denies PRs, issues-prs and full deny nothing), and an explicit allow rule overrides a preset deny.
Rounding out the schema — fields you will rarely touch:
| Field | What it does | Default |
|---|---|---|
id | Stable identifier | agent name |
acmm_levels | ACMM levels this agent participates in | all |
caveman_mode | Prompt-compression experiment: lite, full, ultra, wenyan | off |
metrics_collector | Named metrics source for the stats panel | none |
stats_display | Custom sidebar metrics (key, label, source, field, style) | none |
hidden (packs) | Keep a pack agent out of the default roster view | false |
Methods: subscription CLIs vs self-hosted inference
backend: picks of two families. They differ in how you authenticate and where model lists come from:
| Method | Family | Auth | Model discovery |
|---|---|---|---|
claude | CLI | log in per method | maintained list (Anthropic exposes no “list my models” API) |
copilot | CLI | log in per method (GitHub device flow) | live — entitlement-filtered /models on your plan’s API host |
gemini | CLI | API key (GEMINI_API_KEY) | live — Google models API, filtered to generateContent |
goose | CLI | provider-configured (GOOSE_PROVIDER) | curated per-provider list |
vllm | inference | endpoint + optional key — no login | live — /v1/models |
llm-d | inference | endpoint + optional key — no login | live — /v1/models |
litellm | inference | endpoint + API key — no login | live — /v1/models, entitlement-filtered per key |
Two rules of thumb:
- CLI methods are subscriptions. You log in per method from the dashboard, and every agent using that method shares the login.
- Inference methods are endpoints. You configure a base URL and a key reference (env var name or key-file path — the value goes in
/data/secrets/, never in YAML). Agents onvllm/llm-d/litellmlaunch the Claude CLI routed through hive’s inference translator, so there is no separate login.
Every discovery probe is best-effort: a failed or absent probe falls back to a current static list, so a model dropdown is never empty. Fallback entries are marked “unverified” in the UI.
Model pinning and auto-switching
Each agent shows a 📌 pin on its CLI and its model in the dashboard. The semantics are deliberately narrow — a model changes out from under you in exactly two cases:
- Unpinned + governor. The governor may auto-select a different model (budget, mode). A pin blocks this — and only this. Your own explicit switch always goes through; it simply retargets the pin to the new model, so the agent stays pinned.
- Discovery says the model is gone. When a genuine (non-fallback) discovery returns a model set that no longer contains an agent’s selected model — a key swap or endpoint change stripped the entitlement — the agent is switched to the first available model, with a toast. A static-fallback list never triggers this, and a model that is still present is never re-selected.
Pin a model when reproducibility matters more than the governor’s budget optimizations. Leave it unpinned when you want the hive to manage cost for you.
Cadences and the governor
Agents don’t schedule themselves. The governor evaluates the work queue every eval_interval_s (default 300s), computes a mode from queue depth — idle → quiet → busy → surge (default thresholds: quiet > 2, busy > 10, surge > 20; override with threshold:) — and kicks each agent on the cadence that mode assigns it:
governor:
eval_interval_s: 300
modes:
busy:
threshold: 16 # queue depth that activates this mode
supervisor: 5m # per-agent kick interval in this mode
scanner: 15m
ci-maintainer: 1h
architect: pause # "pause" stops kicks for this agent in this mode
- Per-agent, per-mode intervals. A cadence entry is just
agent-name: durationunder the mode. Anything Go’s duration parser accepts works (5m,2h). - Pausing. The value
pause(orpaused) suspends an agent for that mode without disabling it. - On-demand agents (
on_demand: true) are skipped by the governor timer entirely — they run when explicitly triggered (the inception workflow drivesbrainstormthis way). - Budget. When the weekly token budget is exhausted, kicks are suppressed hive-wide (exempt agents excepted) until the period rolls over.
Set stale_timeout with your cadences in mind: an agent kicked every 4h with a 30-minute stale timeout will look dead between kicks. The shipped packs use “longest cadence × 2”.
ACMM levels: agent rosters as packs
You don’t have to design a roster. Hive ships six ACMM packs (level-1.yaml … level-6.yaml, embedded in the binary and forkable) that pair a curated agent roster with governor cadences and a merge policy:
| Level | Name | Posture |
|---|---|---|
| L1 | Assisted | inception: brainstorm + guide, everything conversational |
| L2 | Instructed | advisory beads; agents observe, humans act |
| L3 | Measured | quality opens issues and hold-gated test PRs; the rest stay advisory |
| L4 | Adaptive | all agents open issues — no PRs yet |
| L5 | Semi-Automated | issues and hold-gated PRs; humans batch-approve |
| L6 | Fully Autonomous | auto-merge on green CI, no hold label |
Applying a level reconciles the whole roster, not just the diff: missing agents are created (as overlay files in /data/agent-configs/), existing agents are merged — pack values fill blanks, but your explicit backend:, model:, and enabled: false always win — and the level’s kick_template and mode are updated so the agent’s policy matches the level. A failed agent doesn’t abort the rest; the level is recorded as cleanly applied when every agent reconciled.
The L5 roster is the canonical worked example — nine agents, eight on the governor timer plus on demand:
| Agent | Mode | Cadence (all governor modes) | |
|---|---|---|---|
| supervisor 👑 | health monitor, sweeps | ADVISORY | 5m |
| scanner 🔍 | triage + fix PRs | ISSUES_AND_PRS | 4h |
| ci-maintainer 🔧 | CI + dependencies | ISSUES_AND_PRS | 4h |
| quality 🧪 | test coverage | ISSUES_AND_PRS | 2h |
| guide 🧭 | documentation | ISSUES_AND_PRS | 4h |
| sec-check 🛡 | CVEs, vulnerabilities | ISSUES_AND_PRS | 4h |
| architect 🏗 | RFCs, refactors | ISSUES_AND_PRS | 4h |
| strategist 🧠 | cross-agent coordination | ISSUES_AND_PRS | 4h |
| brainstorm 💡 | ideation | ADVISORY | on demand |
At L5, every agent PR gets a hold label automatically. The system proposes; it does not merge autonomously.
Kick templates: what an agent is told to do
kick_template names a Markdown file resolved from the hive’s policies checkout (/data/policies/examples/kubestellar/agents/, or the directory your policies: config points at), falling back to the defaults embedded in the binary (v2/pkg/policies/defaults/). It is the agent’s periodic work prompt: on every kick, the template is loaded, variables like ${ISSUE_LIST}, ${PR_LIST}, ${AGENT_NAME}, ${PROJECT_ORG}, and ${KNOWLEDGE} are substituted, and the result is dispatched to the agent’s session.
Resolution order: the agent’s explicit kick_template wins; otherwise the ACMM pack’s template for that agent at the current level; otherwise convention — /data/agents/<name>/CLAUDE.md, then <name>.md in the policies checkout, then the embedded default. Pack templates carry the level’s policy in their names — scanner-holdgated.md is scanner-at-L5; the same scanner at L6 gets scanner-automerge.md.
Portable agents bundle everything — config plus a promptTemplate — in a single AgentDefinition YAML you can import from a URL in the dashboard (see v2/examples/agents/customized-agent.yaml).
When to add what
| Add… | …when |
|---|---|
| nothing (name + method + model) | you’re starting. Defaults are production defaults. |
display_name, emoji, color | the dashboard roster grows past a handful and you want it scannable |
| a model pin 📌 | you need reproducible behavior and the governor keeps optimizing your model away |
cli_pinned: true | a CLI update broke an agent and you never want that surprise again |
on_demand: true | the agent should run when something (you, inception) explicitly fires it |
| cadence overrides | the pack’s rhythm doesn’t match your project — a hot repo may want scanner: 15m, a quiet 4h |
pause in a mode | an agent is noisy exactly when the queue is deep (e.g. pause architect during surge) |
stale_timeout | you changed cadences — keep it above the longest interval |
clear_on_kick: false | the agent genuinely benefits from remembering previous kicks (rare; context bloat is real) |
channels | governor timer kicks aren’t enough — you want webhook-, schedule-, or bead-triggered work |
tools rules | agent needs a sharper permission edge than its mode tier provides |
| a higher ACMM level | your review capacity, CI trust, and appetite for autonomy have all grown — raise the level and let the pack reconcile the roster |
| an inference method | you have GPUs (or a LiteLLM gateway) and want agents off subscription seats |
What to read next
- Introduction — what hive is, setup, and the command surface.
- Architecture — the two scheduling models and how the supervisor drives agents.
- macOS Setup — run a hive locally.
- Troubleshooting — stuck sessions, login expiry, restart loops.
- ACMM policy matrix — the full per-level, per-agent policy table in the hive repo.