Files
prose-contracts/hermes-key-enforcement.prose.md
T

6.9 KiB

kind, name, version, description, author
kind name version description author
enforcement hermes-key-enforcement 1.0.0 Enforces standardized API key configuration across all Hermes agents. Harness/LiteLLM providers MUST use api_key_env indirection. External providers (DeepSeek, OpenAI, Anthropic) may use hardcoded keys. Single source of truth: /etc/environment on each agent host. Designed to make key rotation a one-step operation. Abiba (pi agent)

Hermes Key Enforcement Contract

Rule (One Sentence)

Any api_key pointing to a Syslog-hosted LiteLLM/harness provider MUST be replaced with api_key_env: LITELLM_API_KEY — hardcoded harness keys are forbidden.

Scope

Applies to all Hermes agent configs across all hosts. Covers these config sections:

  • model.api_key
  • custom_providers[].api_key (when name contains harness or litellm)
  • auxiliary.*.api_key (when provider is harness or contains litellm)
  • delegation.api_key (when provider is harness or contains litellm)
  • compression.api_key (when provider is harness or contains litellm)
  • fallback_providers[].api_key (when provider is harness)

Exemptions

External providers are explicitly exempt and may use hardcoded keys:

  • DeepSeek (api.deepseek.com)
  • OpenAI (api.openai.com)
  • Anthropic (api.anthropic.com)
  • OpenRouter
  • Any provider whose base_url does NOT match 192.168.68.116 or litellm.sysloggh.net

Standard Pattern

# ✅ CORRECT — all harness/litellm providers
model:
  provider: harness                    # or custom:litellm.sysloggh.net
  base_url: http://192.168.68.116/v1
  api_key_env: LITELLM_API_KEY        # ← indirection

custom_providers:
  - name: harness
    base_url: http://192.168.68.116/v1
    api_key_env: LITELLM_API_KEY      # ← indirection

auxiliary:
  compression:
    provider: harness
    api_key_env: LITELLM_API_KEY      # ← indirection

# ✅ ALSO CORRECT — external providers
fallback_providers:
  - provider: deepseek
    base_url: https://api.deepseek.com
    api_key: sk-b7d9...               # ← hardcoded OK (external)
    api_key_env: DEEPSEEK_API_KEY      # ← also OK if set in /etc/environment
# ❌ FORBIDDEN — hardcoded harness/litellm key
model:
  provider: harness
  api_key: sk-Flc62smlegyMEaSo1ka8JA   # ← RULE VIOLATION

Detection Query

Run on any Hermes host to detect violations:

grep -rn 'api_key: sk-' /root/.hermes/ \
  --include='config.yaml' \
  | grep -v 'deepseek\|openai\|anthropic\|DEEPSEEK'

If any output — violation. Fix immediately.

Rotation Procedure

With this standard enforced, key rotation is one step:

# 1. Generate new key in LiteLLM
# 2. Update /etc/environment on agent host
ssh root@<host> "sed -i 's/LITELLM_API_KEY=.*/LITELLM_API_KEY=sk-NEW_KEY/' /etc/environment"
# 3. Restart agent gateway
ssh root@<host> "pkill -f 'hermes_cli.main gateway run'; sleep 2; nohup ... &"
# 4. Verify
curl -s -H "Authorization: Bearer sk-NEW_KEY" http://192.168.68.116/v1/models

Done. No config file changes needed. The agent picks up the new key on restart.

Key Longevity Policy (2026-07-04)

Keys are permanent and use bare agent name aliases.

  • Duration: null — keys never expire. This is enforced by default_key_generate_params in litellm_config.yaml.
  • Alias convention: bare agent name only (e.g., tanko, mumuni, koby, koonimo). No dates, no versions. The alias IS the identity.
  • Rotation triggers: compromise, personnel departure, or quarterly security hygiene. NOT calendar-driven.
  • Max budget: $100 per key (config default).
# In litellm_config.yaml — ensures all future keys inherit these defaults:
litellm_settings:
  default_key_generate_params:
    models: ["syslog-auto", "qwen3.6-27B-code", "gemma-4-12b"]
    duration: null        # ← permanent
    max_budget: 100
    metadata:
      purpose: "agent-inference"

Verified Agents (2026-07-04 final)

Agent CT Status LiteLLM Alias Key Type Systemd Source Last Verified
Tanko 112 Compliant tanko Dedicated /etc/environment only 23:00 EDT
Mumuni 114 Compliant mumuni Dedicated /etc/environment only 23:00 EDT
Koby 111 Compliant koby Dedicated User service + drop-in 23:00 EDT
Koonimo 113 Compliant koonimo Dedicated System service + drop-in 23:00 EDT
Abiba 100 N/A (pi native) 23:00 EDT
Kagenz0 105 DOWN 19:14 EDT

Systemd Service Pattern (2026-07-04 fix)

All Hermes agents use systemd to manage their gateway. Two issues were fixed:

  1. Drop-in override/etc/systemd/system/hermes-gateway.service.d/litellm-key.conf (or user equivalent) had hardcoded LITELLM_API_KEY that bypassed /etc/environment.
  2. Missing EnvironmentFile — Services did not source /etc/environment.

Correct pattern:

# In service file:
EnvironmentFile=/etc/environment

# Drop-in only for overrides, NOT primary key storage.
# If a drop-in exists, it must match /etc/environment.

Rotation procedure (one step with this standard):

  1. Generate new key in LiteLLM: curl /key/generate with agent alias
  2. Update /etc/environment: sed -i 's/LITELLM_API_KEY=.*/LITELLM_API_KEY=sk-NEW/' /etc/environment
  3. Update drop-in (if exists): same sed on litellm-key.conf
  4. Restart: systemctl [--user] restart hermes-gateway

Violation Response

  1. Detect — run detection query above
  2. Fix — replace api_key: sk-... with api_key_env: LITELLM_API_KEY in all harness/litellm sections
  3. Verifygrep -c "api_key_env" config.yaml should increase, hardcoded harness keys should be 0
  4. Restart — gateway must restart to pick up env var
  5. Confirm — test key against LiteLLM: curl -H "Authorization: Bearer $KEY" .../v1/models → 200
  6. Update — bump the verified table above
  7. Use safe-mutate — if the fix requires changing /etc/environment or restarting the gateway on a remote host, use safe-mutate to verify current state before mutating.
  • hermes-config-template.prose.md — full configuration template
  • litellm-health.prose.md — LiteLLM stack health verification
  • zulip-platform-verification.prose.md — cross-platform agent verification
  • litellm-api-keys.prose.md — API key creation, rotation, and verification

CI Pipeline (2026-07-04)

All contract changes must pass the PR Pipeline before merge:

auth → validate → lint → ai-review → gate
  • Trigger: push to master (abiba-bot only) or pull request
  • Branch protection: Only abiba-bot can push directly to master. All other users must use PRs.
  • Status check: PR Pipeline — Authorize → Validate → Review → Merge required before merge
  • Runner: runner-ct110 (Gitea Actions v0.6.1) on CT 110
  • Config: .gitea/workflows/pr-pipeline.yaml