PR Pipeline — Authorize → Validate → Review → Merge / auth (push) Successful in 6s
PR Pipeline — Authorize → Validate → Review → Merge / validate (push) Failing after 1s
PR Pipeline — Authorize → Validate → Review → Merge / lint (push) Skipped
PR Pipeline — Authorize → Validate → Review → Merge / ai-review (push) Skipped
PR Pipeline — Authorize → Validate → Review → Merge / gate (push) Skipped
- Note that vault sync is pending (service token not on kagentz) - Key is stored in /home/hermes/syslog/agent-zero-keys.env as fallback
130 lines
5.0 KiB
Markdown
130 lines
5.0 KiB
Markdown
---
|
|
kind: function
|
|
name: agent-zero-openrouter-key
|
|
description: >
|
|
Manages the OpenRouter API key for Agent Zero (Docker container on kagentz .14).
|
|
Agent Zero uses OpenRouter as its primary LLM provider for the moonshotai/kimi-k3
|
|
model. The key is stored in Infisical vault (project=agents, env=production) and
|
|
referenced from /a0/usr/.env in the container. Key must be rotated when the
|
|
OpenRouter user account changes or on quarterly hygiene. Last verified: 2026-09-01.
|
|
---
|
|
|
|
## Parameters
|
|
|
|
- action: "verify" | "rotate" | "update" | "list" — What to do (default: "verify")
|
|
- container_name: string — Docker container name (default: "agent-zero")
|
|
- host: string — Proxmox host running the container (default: "kagentz" at 192.168.68.14)
|
|
- env_path: string — Path to .env file in container (default: "/a0/usr/.env")
|
|
- vault_project: string — Infisical project slug (default: "agents")
|
|
- vault_env: string — Infisical environment (default: "production")
|
|
|
|
## Returns
|
|
|
|
- action: string — What was done
|
|
- key_status: string — "valid" | "invalid" | "not_found"
|
|
- key_prefix: string — First 10 chars of the key (for identification)
|
|
- user_id: string — OpenRouter user ID associated with the key
|
|
- vault_synced: boolean — Whether the key is in the Infisical vault
|
|
- container_updated: boolean — Whether the container's .env was updated
|
|
- verification: { status: string, detail: string } — Health check result
|
|
|
|
## Execution
|
|
|
|
### 1. Verify the key
|
|
|
|
1. **Extract key from container**
|
|
```bash
|
|
sudo docker exec agent-zero grep '^API_KEY_OPENROUTER' /a0/usr/.env | cut -d'=' -f2-
|
|
```
|
|
|
|
2. **Test against OpenRouter API**
|
|
```bash
|
|
curl -s https://openrouter.ai/api/v1/auth/key \
|
|
-H "Authorization: Bearer <key>" | python3 -m json.tool
|
|
```
|
|
Expected: HTTP 200, JSON with `data.label` and `data.is_free_tier`
|
|
|
|
3. **Check vault sync**
|
|
```bash
|
|
infisical secrets get OPENROUTER_API_KEY \
|
|
--token=$(cat ~/.infisical-token) \
|
|
--projectId=agents \
|
|
--env=production \
|
|
--domain=https://vault.sysloggh.net
|
|
```
|
|
|
|
4. **Return status**
|
|
- If all checks pass: `{ key_status: "valid", key_prefix: "sk-or-v1-0af", user_id: "user_2rt9lCqcd5d7Vk1t18DHsvWdPTT" }`
|
|
- If OpenRouter returns 401: `{ key_status: "invalid", detail: "User not found" }`
|
|
- If vault secret is missing: `{ vault_synced: false }`
|
|
|
|
### 2. Rotate the key
|
|
|
|
1. **Generate new key** in OpenRouter UI or via API
|
|
2. **Update container .env**
|
|
```bash
|
|
sudo docker exec agent-zero sed -i 's/^API_KEY_OPENROUTER=.*/API_KEY_OPENROUTER=<new_key>/' /a0/usr/.env
|
|
```
|
|
3. **Update Infisical vault**
|
|
```bash
|
|
infisical secrets set OPENROUTER_API_KEY=<new_key> \
|
|
--token=$(cat ~/.infisical-token) \
|
|
--projectId=agents \
|
|
--env=production \
|
|
--domain=https://vault.sysloggh.net
|
|
```
|
|
4. **Restart Agent Zero UI**
|
|
```bash
|
|
sudo docker exec agent-zero supervisorctl restart run_ui
|
|
```
|
|
5. **Verify** — Run "verify" action again
|
|
|
|
### 3. Update (key changed but no rotation)
|
|
|
|
1. **Update container .env** (same as rotate step 2)
|
|
2. **Sync vault** (same as rotate step 3)
|
|
3. **Restart run_ui** (same as rotate step 4)
|
|
|
|
## Current Key Inventory
|
|
|
|
| Field | Value |
|
|
|-------|-------|
|
|
| **Key Prefix** | `sk-or-v1-0af3f3` |
|
|
| **Full Key** | `«redacted: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»` (in vault + /a0/usr/.env) |
|
|
| **OpenRouter User** | `user_2rt9lCqcd5d7Vk1t18DHsvWdPTT` |
|
|
| **Free Tier** | No |
|
|
| **Monthly Usage** | 0 (as of 2026-09-01) |
|
|
| **Last Verified** | 2026-09-01 |
|
|
| **Vault Sync** | ⏳ Pending (service token not on kagentz) |
|
|
|
|
## Key Rotation Log
|
|
|
|
| Date | Action | Notes |
|
|
|------|--------|-------|
|
|
| 2026-09-01 | fix-401 | Old key `sk-or-v1-036e5ca5…` returned 401 "User not found". Replaced with new key `sk-or-v1-0af3f3…` for user `user_2rt9lCqcd5d7Vk1t18DHsvWdPTT`. Verified OpenRouter 200. Container .env updated, run_ui restarted. |
|
|
|
|
## Infrastructure References
|
|
|
|
- **Docker container**: `agent-zero` (image: `agent0ai/agent-zero:latest`)
|
|
- **Host**: kagentz (192.168.68.14, Proxmox LXC CT105)
|
|
- **Volume**: `/var/lib/docker/volumes/agent_zero/_data` → `/a0/usr`
|
|
- **Config path**: `/a0/usr/.env` (line ~72: `API_KEY_OPENROUTER=…`)
|
|
- **Model preset**: "Cost Efficient" (uses `openrouter/moonshotai/kimi-k3`)
|
|
- **Model config**: `/a0/usr/plugins/_model_config/config.json`
|
|
|
|
## Verification Before Acting
|
|
|
|
**Key is a lead, not a fact.** Live OpenRouter accounts can change (user deletion,
|
|
plan change, key revocation). Before acting on this contract:
|
|
|
|
1. Verify the key against OpenRouter's `/auth/key` endpoint
|
|
2. Check the user ID matches the expected account
|
|
3. Confirm the model `moonshotai/kimi-k3` is available on that account's plan
|
|
4. Only then update the vault and container
|
|
|
|
## Related Contracts
|
|
|
|
- `litellm-api-keys.prose.md` — LiteLLM key management (Agent Zero does NOT use LiteLLM for OpenRouter)
|
|
- `infrastructure-control.prose.md` — Proxmox topology, container locations
|
|
- `gpu-fleet.prose.md` — Fleet-wide agent key inventory (add Agent Zero here)
|