Architecture
Halos has three planes plus a policy source. Each plane can be adopted independently, but the loop closes only when all three run.
Planes
Section titled “Planes”Client plane. Makes the developer environment match a signed release. It writes each harness’s native managed configuration (Claude Code managed-settings.json, managed MCP config and a managed CLAUDE.md; Codex requirements.toml and managed_config.toml; Gemini CLI system settings.json; Copilot CLI managed-settings.json) and installs the pinned CLI from a verified artifact. See delivery and the self-service portal.
Traffic plane. halo-proxy (or Kong with the halo-kong plugin) verifies the caller’s OIDC JWT, derives the ring and variant from the verified identity, rewrites model aliases to the variant route, stamps x-halo-* headers and enforces a fail-closed model allowlist. halo-shadow receives async copies of sampled sessions (first turns, or every step with turns: all). The gateway also polls halo-server’s signed kill list so a bad experiment can be switched off in seconds (experiments), and can sign Bedrock requests with its own AWS identity. See stack-agnostic and shadow traffic.
Evidence plane. An OTEL collector normalizes harness telemetry to halo.* in ClickHouse; halo eval run runs containerized headless replays; halo exp analyze applies sequential tests and guardrails; halo exp promote opens a PR, and the controller runs that loop on a timer. See evidence plane.
Design constraints
Section titled “Design constraints”- Rings point at immutable releases through signed pointers (ADR-0002, ADR-0008).
- Model experiments live at the gateway (ADR-0003).
- Assignment is one Go package (
internal/assign) shared byhalod,halo-proxy,halo-kongandhalo-shadow(ADR-0006). - Shadow is first-turn only (ADR-0004).
- A human owns every irreversible step. Promotion opens a PR; automatic rollback (the kill switch, ADR-0009) is the only automatic direction, and it only returns users to control.
Request path
Section titled “Request path”The mirror is asynchronous and dropped when its queue is full. A shadow job carries only the experiment, variant, protocol, path, allowlisted headers and body; halo-shadow resolves both upstreams from its own copy of the policy.
Components
Section titled “Components”| Component | Language | Notes |
|---|---|---|
halo |
Go | Compiler and operator CLI |
halod |
Go | Static binary; run/once/status/service; halod service install writes the launchd plist or systemd unit (templates embedded in cmd/halod/service.go, also printed by halod service print; the plist also lives in cmd/halod/packaging, the deb/rpm unit in deploy/packaging/halod.service), a scheduled task on Windows |
halo-proxy |
Go | Stack-agnostic proxy; /healthz and /metrics on the admin listener (--admin-listen) |
halo-kong |
Go (go-pdk) | External Kong plugin, same decision code |
halo-shadow |
Go | Async mirror, optional AES-256-GCM pair store |
halo-server |
Go + embedded web console | Inventory, drift, releases, experiments, audit log, portal, enrollment, device store, kill-list endpoint, optional controller (--controller) |