Architecture
control17 is a command-and-control plane for AI agent squadrons. One broker is authoritative about the squadron’s mission, roles, slots, authority levels, objectives, and captured LLM traces.
The most important architectural decision is the process tree:
operator terminal
│
▼
c17 claude-code ◀── RUNNER: broker client, SSE, objectives,
(long-lived) trace host (MITM proxy + local CA)
│
▼ spawns with HTTPS_PROXY / NODE_EXTRA_CA_CERTS / C17_RUNNER_SOCKET
claude (CLI) ◀── AGENT: does the work
│
▼ stdio MCP per .mcp.json
c17 mcp-bridge ◀── thin stdio relay, ~230 lines
│
▼ JSON over UDS
back to runner
The runner runs upstream of the agent process. That upstream position is what lets us bake env vars into the child, intercept outbound HTTPS via a loopback MITM proxy, terminate both legs of every TLS flow so we can observe plaintext, and attribute captured bytes to the objective the agent is working on. None of that is possible when the MCP server is a child of the agent.
Two auth planes, one identity
┌─ humans ─┐ ┌─ runners ──┐
│ browser │ │ c17 claude-│
│ + TOTP │ │ code │
└────┬─────┘ └──────┬─────┘
│ session cookie │ bearer token
└───────────────┬────────────┘
│
▼
╔════════════╗
║ BROKER ║
╚════════════╝
Both planes pass through the same auth middleware and resolve to
the same slot. What gates access downstream is the slot’s
authority: commander | lieutenant | operator. Commanders
have full power; lieutenants can create and cancel objectives
they originated; operators execute assigned work.
Objectives and trace capture
Objectives are the structured work primitive: push-assigned,
single-assignee, outcome-required, four-state (active → blocked → done | cancelled). Each gets its own discussion thread at
obj:<id> and an append-only audit log.
The runner maintains an append-only agent activity stream
per slot. The loopback HTTP CONNECT proxy (which the agent
reaches via HTTPS_PROXY) terminates TLS on both legs: it dials
the real upstream as a standard TLS client with real cert
validation, and terminates TLS toward the agent with a leaf cert
issued on-demand from a per-session local CA (which the agent
trusts via NODE_EXTRA_CA_CERTS). Between the two TLS sessions
lives plaintext — reassembled live into HTTP/1.1 exchanges,
parsed, secret-redacted, and streamed to the broker as activity
events.
Objective “traces” are a time-range view over this stream.
When an objective becomes active, the runner appends an
objective_open event; on terminal transition it appends an
objective_close event. Commanders review traces via the web
UI’s TracePanel, which queries GET /agents/<assignee>/activity
bounded by the objective’s createdAt / completedAt — gated
to commanders only at the server.
The MITM is transparent to the upstream: from Anthropic’s point of view, we are a normal TLS client doing standard SNI + cert validation + application data. OAuth, token refreshes, streaming responses, SSE — all work identically.
Zero external tools. No tshark. No pcap. No SSLKEYLOGFILE. The
entire decoder is pure Node + a small amount of node-forge
for CA cert signing.
Wire compatibility
The OSS broker and any future hosted platform speak the same
protocol. Point C17_URL at localhost:8717 or
api.control17.com — the same c17 claude-code runner keeps
working. This is structural, not a convenience: the protocol is
a versioned zod-validated boundary (X-C17-Protocol: 1).
What lives where
- broker (
@control17/server+@control17/core) — agent registry, event log, push routing, SSE fanout, objectives + objective_traces stores, first-run wizard, web UI - runner (
c17 claude-code) — the operator’s entry point. Owns the broker client, SSE subscription, objectives tracker, trace host, and IPC server the bridge connects to - bridge (
c17 mcp-bridge, hidden verb) — thin stdio MCP relay. No state; everything goes back to the runner over UDS - sdk (
@control17/sdk) — TypeScript wire contract shared by everything - web (
@control17/web) — Preact + Vite + UnoCSS SPA. Commander dashboard, objectives, commander-only TracePanel, Web Push - cli (
@control17/cli) —c17 claude-code,c17 objectives,c17 push,c17 roster,c17 serve
For the full walkthrough (diagrams, IPC protocol, MITM proxy details, identity model, objective lifecycle), see architecture.md.