Apex — Architecture (v1.0)
Single endpoint, smart-router shim, hidden upstreams. The locked production topology as of 2026-05-19.
v1.0 locked 2026-05-19, end-to-end verified via /forge bot 2026-05-20. Single endpoint at
https://apex.cmmd.ai. All routes speak Anthropic Messages API natively — no translation layer. LiteLLM is retired from the apex-core path. Two-tunnel architecture is superseded by the smart-router shim.
Topology
Section titled “Topology” ┌──────────────────────────────────┐ │ Forge desktop / ForgeCode / │ │ any Anthropic-SDK client │ │ │ │ ANTHROPIC_BASE_URL=apex.cmmd.ai │ │ ANTHROPIC_AUTH_TOKEN=<bearer> │ │ ANTHROPIC_MODEL=apex-{tier} │ └──────────────┬───────────────────┘ │ HTTPS, single endpoint ▼ ┌──────────────────────────────────┐ │ https://apex.cmmd.ai/v1/messages│ │ Cloudflare tunnel "apex" │ └──────────────┬───────────────────┘ ▼ ┌──────────────────────────────────┐ │ Mac Studio: apex-think-shim │ │ (smart router, 127.0.0.1:11500) │ │ │ │ 1. Bearer auth (SQLite tokens) │ │ 2. Route by body.model field │ │ 3. Rewrite request + response │ │ for brand isolation │ │ 4. SSE keepalive (local only) │ └──────────────┬───────────────────┘ │ ┌───────────────────────┬──────────┴──────────┬───────────────────────┐ ▼ ▼ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ ┌─────────────────────┐ │ apex-core │ │ apex-flash │ │ apex-general │ │ apex-reason │ │ local / free │ │ cloud / paid │ │ cloud / paid │ │ cloud / paid │ │ (default) │ │ fast lint-style │ │ general purpose │ │ deepest review │ │ │ │ │ │ │ │ │ │ Mac Studio │ │ Anthropic-native │ │ Anthropic-native │ │ Anthropic-native │ │ Ollama :11434 │ │ cloud endpoint │ │ cloud endpoint │ │ cloud endpoint │ │ │ │ │ │ │ │ │ │ vision-aware │ │ ~1.3s │ │ ~1s │ │ ~1.7s │ │ ~1s warm │ │ │ │ │ │ │ └──────────────────┘ └──────────────────┘ └──────────────────┘ └─────────────────────┘The upstream backing each cloud tier is operational detail recorded in the shim source + the CMMD secrets vault. Apex consumers (Forge, ForgeCode, the /forge bot, the CMMD app) should never need to know — only
apex-*slugs are routable, and brand isolation holds in both directions.
End-to-end verified 2026-05-19: all four routes return 200 in 1–2s with the response model field showing the apex-* slug the client sent (brand isolation holds in both directions).
| Machine | Role in v1.0 | Specs |
|---|---|---|
| Mac Studio (M1 Ultra 128GB) | apex-shim + local Ollama serving apex-core. Also the smart router for the three cloud-backed tiers. | macOS 15+, 128 GB unified memory |
| CMMD-Homebase (Linux) | Self-hosted GHA runner for the /forge bot (label cmmd). Holds a pre-cloned forge-code working copy at ~/forge-code. | Ubuntu, x86_64 |
| Ryzen (RTX 2080S 8GB) | Lab tier (apex-flash-lab) — exposed at lab.apex.cmmd.ai via dedicated tunnel. | Ubuntu 22.04, Ryzen 9 |
| alex-windows (1080Ti 11GB) | Lab tier (apex-general-lab) — deferred until Tailscale ingress lands. | Windows, 11 GB VRAM |
| Mac Mini M4 (16 GB unified) | Lab tier (apex-core-lab) — deferred until Tailscale ingress lands. | macOS, 16 GB unified |
| Cloudflare | DNS + tunnel for apex.cmmd.ai. Dashboard-managed ingress to Mac Studio shim at 127.0.0.1:11500. | Zswire account, cmmd.ai zone |
The smart router (apex-think-shim)
Section titled “The smart router (apex-think-shim)”Source: cmmd-center/apex → mac-studio/think-shim/shim.py
The shim is ~380 lines of Python stdlib (http.server, http.client, sqlite3) with one job: be a smart Anthropic Messages API proxy.
Routing table (Apex consumer view)
Section titled “Routing table (Apex consumer view)”| Apex slug | Tier | Local quirks |
|---|---|---|
apex-core | local / free (Ollama on Mac Studio) | inject thinking:disabled, SSE keepalive trick |
apex-flash | cloud / paid | — |
apex-general | cloud / paid | — |
apex-reason | cloud / paid | — |
Unknown model → routes to apex-core (local) as a backwards-compat fallback. Lets generic Anthropic-default model names (e.g. when an SDK falls back internally) transparently end up on the free local tier. The shim source (mac-studio/think-shim/shim.py) holds the actual upstream URL + canonical model id for each route — kept off the docs surface to maintain brand isolation.
Auth: both X-Api-Key and Authorization Bearer
Section titled “Auth: both X-Api-Key and Authorization Bearer”The shim accepts the API token via EITHER header:
Authorization: Bearer <token>— the original interface (used byapex-tokenCLI clients + the CMMD app)X-Api-Key: <token>— Anthropic-native auth header (used by@ai-sdk/anthropic, which powers ForgeCode + the /forge bot)
Lookup is case-insensitive (X-Api-Key, x-api-key, X-API-KEY all match — see PR shipping the case-insensitive fix).
/v1/models is synthetic
Section titled “/v1/models is synthetic”The shim does NOT proxy GET /v1/models to local Ollama (that would leak underlying tag names like qwen3.5:122b-a10b). Instead, it returns a synthesized OpenAI-compat list of the four apex-* slugs from the in-memory ROUTES table. Dynamic — adding a route to ROUTES.py auto-exposes it.
Brand isolation (both directions)
Section titled “Brand isolation (both directions)”- Request side: Client sends
model: "apex-flash". Shim rewrites body’smodelfield to the upstream canonical id before forwarding. - Response side: Upstream’s
"model": "<canonical>"is string-replaced back to"model": "apex-flash"before streaming to the client. - Auth side: Client sends CMMD bearer/api-key. Shim validates against SQLite, then replaces the auth header with the upstream’s API key from env before calling upstream. Client token never leaks to upstream; upstream keys never leak to clients.
- Models list:
/v1/modelsonly ever names theapex-*slugs.
Why no Anthropic↔OpenAI translation
Section titled “Why no Anthropic↔OpenAI translation”The cloud upstreams the shim wraps speak Anthropic Messages API natively at a path-prefixed sub-route. Same JSON shape as Anthropic’s own. The shim’s job is rewrite-and-forward, not translate — keeping it small, single-format, and easy to maintain.
The gzip gotcha (and the fix)
Section titled “The gzip gotcha (and the fix)”Upstreams honor Accept-Encoding: gzip when set. The shim used to strip Content-Encoding: gzip response headers but forward the gzipped body unchanged — clients couldn’t decode. Fix: shim sets Accept-Encoding: identity on outbound requests so upstreams return plaintext. Locked into the shim’s permanent contract.
Endpoints
Section titled “Endpoints”| Endpoint | Purpose | Public? |
|---|---|---|
https://apex.cmmd.ai/v1/messages | Anthropic Messages API for all four apex-* slugs | ✅ |
https://apex.cmmd.ai/v1/models | Health check / model list (unauthenticated) | ✅ |
(deferred) https://apex.cmmd.ai/v1/messages with apex-*-lab model | Lab tier on Ryzen | 🛠 not yet routed |
Authentication
Section titled “Authentication”Bearer tokens managed by apex-token CLI on Mac Studio. SQLite-backed (~/.apex/think-shim/tokens.db), only sha256 hashes stored. SIGHUP reloads cache after issue/revoke.
Three production tokens currently live (CLI-managed):
cmmd-prod— for the CMMD app on Railway (APEX_API_KEYenv)forge-prod— for Forge desktop / Forge cloud (Fly.ioAPEX_API_KEYsecret onforge-cloud-master+forge-cloud-users)github— for GitHub Actions workflows incl. the /forge bot (broadcast asAPEX_API_KEYrepo secret across all 12 CMMD-Center repos)
Each token is shown ONCE at issue time. Lost token = apex-token rotate <id>.
Rotation discipline: rotating any token invalidates the previous plaintext immediately. The new plaintext must be re-broadcast to every consumer in the same operation, or production breaks. See Apex Operations → token rotation for the broadcast procedure.
Configuration files on Mac Studio
Section titled “Configuration files on Mac Studio”All paths in cmmd-center/apex/mac-studio/ — these are the deploy targets:
| Purpose | Path on Mac Studio | Source in apex repo |
|---|---|---|
| Shim source | /Users/cmmd/.apex/think-shim/shim.py | mac-studio/think-shim/shim.py |
| Shim LaunchAgent | ~/Library/LaunchAgents/com.apex.think-shim.plist | mac-studio/think-shim/com.apex.think-shim.plist |
| Apex Token CLI | /Users/cmmd/.apex/think-shim/apex-token | mac-studio/think-shim/apex-token |
| Token DB | /Users/cmmd/.apex/think-shim/tokens.db | (runtime, not in git) |
| Ollama LaunchAgent | ~/Library/LaunchAgents/com.apex.ollama.plist | mac-studio/ollama/com.apex.ollama.plist |
| Caffeinate LaunchAgent | ~/Library/LaunchAgents/com.apex.caffeinate.plist | mac-studio/caffeinate/com.apex.caffeinate.plist |
| Modelfile (apex-core) | ~/.apex/Modelfile.apex-core | mac-studio/Modelfile.apex-core |
| Ollama models dir | /Users/cmmd/.apex/models | (runtime) |
| Cloudflared tunnel config | (Cloudflare dashboard-managed) | mac-studio/cloudflared/TUNNEL_CONFIG.md |
LaunchAgent env vars
Section titled “LaunchAgent env vars”The shim plist holds the upstream API keys at the OS level (not in source). The repo’s checked-in plist uses __SET_VIA_SECRETS_VAULT__ placeholders — the live plist on Mac Studio has the real values, sourced from the CMMD/production secrets vault.
Env var names + their consumers are tracked in DISASTER_RECOVERY.md. Reload the LaunchAgent (launchctl bootout && launchctl bootstrap) after rotation.
What changed from the previous architecture
Section titled “What changed from the previous architecture”| Before (≤ 2026-05-18) | v1.0 (2026-05-19+) |
|---|---|
Two endpoints: apex-api.cmmd.ai + lab-apex-api.cmmd.ai | One endpoint: apex.cmmd.ai |
| LiteLLM proxy fronting Ollama | No LiteLLM — direct Anthropic Messages API via shim |
Two tunnels (apex + lab-apex) | One tunnel (apex); lab tunnel still exists but unused in v1.0 |
| Clients knew per-tier endpoints | Clients only know one endpoint, pick by model name |
| Mixed Ollama + cloud per tier | Local for apex-core, cloud for the rest, lab tier deferred |
| Cortex brand for cloud, Apex for local | Apex is the brand for everything — Cortex is retired (see model lineup) |
Why v1.0 is shaped this way
Section titled “Why v1.0 is shaped this way”Three forcing functions led here:
- Brand discipline. Clients only ever see
apex-*model identifiers — never the underlying upstream model names. The shim rewrites both directions so the brand layer holds. Internal docs follow the same rule: upstream specifics live in the shim source + secrets vault, not on the docs surface. - Single auth realm. One bearer-token gate. Upstream keys live server-side, never on clients. Rotating a token in one place revokes access everywhere.
- Operational simplicity. One endpoint to monitor, one log to grep, one config to deploy. LiteLLM was overkill once Ollama 0.24 shipped native Anthropic Messages API.
Verified end-to-end (2026-05-19)
Section titled “Verified end-to-end (2026-05-19)”cmmd/apex-core → Mac Studio Ollama → 1.0s → response model: "apex-core"cmmd/apex-flash → api.deepseek.com → 1.3s → response model: "apex-flash"cmmd/apex-general → api.moonshot.ai → 1.0s → response model: "apex-general"cmmd/apex-reason → api.deepseek.com → 1.7s → response model: "apex-reason"Test command (you can re-run this):
TOKEN="sk-apex-cmmd-prod-..." # see apex-token list on Mac Studiofor model in apex-core apex-flash apex-general apex-reason; do curl -s -X POST https://apex.cmmd.ai/v1/messages \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ --data-binary "{\"model\":\"$model\",\"max_tokens\":15,\"messages\":[{\"role\":\"user\",\"content\":\"Reply hi\"}]}" \ --max-time 60 | head -c 200 echodoneDeferred to v1.1
Section titled “Deferred to v1.1”- Lab tier (
apex-flash-lab,apex-core-lab) — needs Mac Studio → Ryzen Tailscale path. Models pulled on Ryzen but not yet routable through the shim. - apex-vision — multimodal tier on a Mac Studio model (Qwen 2.5 VL or similar).
- Stable rate-limits / per-token quotas — currently soft; future feature lives in shim.
- Observability — Alertmanager + Uptime Kuma + ntfy.sh on homebase (separate workstream).
Related
Section titled “Related”- Models — per-spec capabilities, context window, sample latency
- API Reference — request/response shapes
- Operations — runbooks (rotate token, redeploy shim, debug a slow request)
- Tool use verification — end-to-end Claude Code CLI smoke test
- ADR-0002: Apex harness Anthropic-compat — why we picked the native Anthropic path
- ADR-0003: Apex model choices — the rationale for DeepSeek + Kimi + Qwen