Reference implementation notes

Where one implementation of this architecture enforces each concept, with source chips. The chips name files in that implementation's source tree; line numbers refer to commit 92b55fe (2026-11-01).

exampleHealthokprod
Tokens 24h1.84M
Month41.37

The rest of this site describes the pattern. This page maps it onto a reference implementation: a Node / TypeScript orchestrator on the Claude Agent SDK, with tool servers for GitLab, Ansible Automation Platform, NetBox, Proxmox VE, ServiceNow and Grafana, a Next.js web client and a SwiftUI phone app. Nothing on the other pages depends on these choices.

01Concept → implementation

ConceptHow the reference implementation does itSource
Agents propose in code; pipelines applyThe change specialist's Git tool server opens merge requests with a change record; the automation tool server can only check and run records through a change-runner job template; no tool changes a device directly.server/src/changes.ts:1-22 mcp/aap/src/server.ts:1-18 mcp/gitlab/src/server.ts:1-16
Agents never hold credentialsEach agent process gets an environment rebuilt from a short allow-list plus one model credential; ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, ANTHROPIC_BASE_URL and CLAUDE_CODE_OAUTH_TOKEN from the backend's own environment are never copied.server/src/auth.ts:12-13, 37-51
Secrets rendered outside the agent's reachTool-server credentials are rendered by the deploy automation into the site's MCP configuration; each tool server receives only the env in its own entry; admission hashes exclude env.docs/DEPLOY.md:168-179 server/src/admission.ts:8-17
Secret files are unreadableThe Git tool server refuses to read vault files, env files and the MCP configuration.mcp/gitlab/src/server.ts:233
Output redacted before the modelThe automation tool server redacts device and API output; source-of-truth, hypervisor and ITSM servers redact secret-looking fields; ITSM credentials only from the server's own env; the audit writer drops secret-looking keys.mcp/aap/src/redact.ts mcp/servicenow/src/guards.ts server/src/audit.ts:9-35
Reads are free; writes need a grantThe change gate classifies the message once per turn; without a grant write-class tools are refused.server/src/changegate.ts:1-36 server/src/sessions.ts:342-371, 401-405
The nine checksA PreToolUse hook (scope, profile, change gate, budget) and the SDK's canUseTool callback (all but budget, then guards, admission, policy, change path, verdict).server/src/sessions.ts:695-840
Approval cards and digestsFrozen input, a SHA-256 digest over session, approval id, tool and input; single use; re-checked on approve.server/src/sessions.ts:566-583, 769-788, 922-944
Merge card raised by the orchestratorAfter a check passes at a known head; bound to request, change and head commit; 24 h.server/src/sessions.ts:951-994, 1064-1065
Admission by hashLaunch definition, source files or binary, every tool classed; changed servers refused at agent start.server/src/admission.ts:8-17, 137-165 server/src/sessions.ts:592-616
Protected targetsA hard guard on stop, shutdown, reboot of listed VMs; the hypervisor server checks its own list too.server/src/guards.ts:21-27
BudgetsPer origin: tool calls per agent run and per message, tokens per message and per chat, USD per chat (API-key mode only).server/src/budgets.ts:5-40 config/budgets.json:3-26 server/src/sessions.ts:394-399, 820-831, 1116-1129
Scope per specialistDefinitions only expose own servers; a scope check on every call.server/src/specialists.ts:152-171, 224-266
Hash-chained auditAppend-only, seq and prev, fsync per record; a verifier.server/src/audit.ts:37-98
Roles from directory groups; approvers separateOIDC with PKCE; roles from claims; approver groups; any approver may approve any card (no self-approval block).server/src/oidc.ts:1-12 server/src/rbac.ts:93-99
Triggers and schedulesAlert triggers with secrets, dedupe and rate limits; cron schedules; job and alert chats on read-only profiles by default.server/src/automations.ts:1-70 server/src/index.ts:580-646
Metricsodin_tokens_total, odin_cost_usd_total, odin_turns_total, odin_budget_stops_total.server/src/metrics.ts:1-55

02Not in the reference implementation (yet)

Pattern elementStatus
Model gatewayThe reference implementation calls the Anthropic API directly through the Claude Agent SDK, with model aliases mapped to claude-haiku-5-5, claude-sonnet-5-5 and claude-opus-5-5. Tiers map onto those aliases; a gateway is not part of it.
Digital twin and emulation labNot called by the reference implementation at this commit. Its source-of-truth server can export a site's devices and cabled links for a twin; the graph twin, what-if in CI and emulation rehearsals are specified on these pages as the pattern.
Vault integrationThe reference implementation does not talk to a vault itself: credentials are rendered into its environment and tool-server configuration at deploy time, and the automation platform holds device credentials. Short-lived, pipeline-fetched credentials are the pattern.
Active/passive failoverOne process with in-memory approvals and file state; failover is the platform's job (restart on a durable volume).
Self-approval blockNot enforced in code; separation of duties is group design.
ITSM container prefixA constant in the ITSM tool server's guards, not a setting.

03Model credentials in the reference implementation

  • ODIN_AUTH_MODE=api_key makes API-key mode the default for every new chat, including jobs and alerts; the mode is stored with each chat server/src/auth.ts:15-17 server/src/sessions.ts:296-302 server/src/index.ts:460, 589.
  • ODIN_API_KEY is injected into agent processes as ANTHROPIC_API_KEY and nowhere else; the backend warns at start-up if ANTHROPIC_* variables are set on it server/src/auth.ts:19-45.
  • Side calls (fresh-chat summary, next-prompt suggestion, spoken summary) use the same environment builder server/src/carryover.ts:52 server/src/suggest.ts:23 server/src/voice.ts:148.
  • The per-chat USD cap applies only in API-key mode, checked before each new message; cost is the SDK's own per-turn figure server/src/sessions.ts:394-399, 1080-1097.
  • Its README describes API-key mode as "for one session or job only"; the code applies ODIN_AUTH_MODE to every chat created while it is set README.md:112.
ODIN_AUTH_MODE
agent process environment
CLAUDE_AGENT_SDK_CLIENT_APPodin-…
identifies ODIN to the SDK
PATH, HOME, USER, LANG, TMPDIR, SHELL, TERMcopied
the only backend variables copied
ANTHROPIC_API_KEY= ODIN_API_KEY
the one credential, set only inside the agent process
MAX_MCP_OUTPUT_TOKENSODIN_MAX_TOOL_OUTPUT_TOKENS ?? 15000
caps what one tool result puts into context
never reaches the agent
ANTHROPIC_AUTH_TOKENnever passed
would override the credential ODIN chose
ANTHROPIC_BASE_URLnever passed
would redirect agent traffic to another endpoint
ANTHROPIC_API_KEY (from the backend's own env)never copied
only ODIN_API_KEY becomes the agent's key, and only in api_key mode
CLAUDE_CODE_OAUTH_TOKENnot passed
the other mode's credential
everything else (vault tokens, MCP credentials, …)not passed
the environment is rebuilt from scratch, not filtered
agentEnv(mode) starts from an empty object, copies a short allow-list, then adds the one credential for the chat's mode server/src/auth.ts:12-13, 37-51. Every agent process gets it: chats server/src/sessions.ts:639, the fresh-chat summary server/src/carryover.ts:52, the next-prompt suggestion server/src/suggest.ts:23 and the spoken reply server/src/voice.ts:148.

04Workflows → code

#StepSource
1"is the core switch healthy?"server/src/index.ts:85-141 server/src/rbac.ts:80-88
2change gate: no grantserver/src/sessions.ts:401-405 server/src/changegate.ts:16-34
3message → the chat's agentserver/src/sessions.ts:406-433
4delegate: health checkserver/src/specialists.ts:188-209, 275-278 server/src/handoffs.ts:43-58
5tool call → nine checksserver/src/sessions.ts:695-840
6network checks (all devices, one job)mcp/aap/src/server.ts:301-304
7launch a named read-only templatemcp/aap/src/server.ts:1-18
8parsed, redacted resultsmcp/aap/src/redact.ts mcp/aap/src/server.ts:151-158
9report (kept as a hand-off)server/src/handoffs.ts:27-34
10answer · "raise changes?"server/src/sessions.ts:1085-1095

05Tests in the reference implementation

  • A safety suite with no model and no network: 33 sections, 138 checks server/scripts/safety.ts:1-6; type checks and a contract check in CI .gitlab-ci.yml:17-44.
  • 17 behaviour evaluations with the model in the loop, approvals auto-denied server/evals/cases.json.