Route fovea LLM roles to ZDR open models via path-prefix agentgateway lanes
Date: 2026-06-25 Status: Accepted Decision: hl-0ah0 Deciders: Sean Brandt, Claude Opus 4.8
Context
Section titled “Context”fovea ran Anthropic-direct (claude-sonnet-4-6 for every role). The cluster agentgateway applies ZDR/require_parameters as backend-global overrides (no per-model selector in the CRD), so each ZDR model needs its own dedicated AgentgatewayBackend. fovea’s RoleModel exposes a per-role base_url but no custom-header field, so the existing header-selected ZDR chat lane (x-agentgateway-backend) is unreachable from fovea. The engram embeddings route already proves path-prefix routing to a dedicated ZDR backend with no URL-rewrite filter.
Decision
Section titled “Decision”Route both fovea roles through agentgateway (provider: openai) to ZDR OpenRouter lanes via two header-free path-prefix HTTPRoutes — /fovea-scout/v1 (DeepSeek V4-Flash, reusing openrouter-zdr) and /fovea-deepdive/v1 (GLM-5.2, new openrouter-zdr-glm backend). fovea selects each lane via per-role base_url. This reverses the prior “fovea is intentionally Anthropic-direct” decision.
Rationale
Section titled “Rationale”- fovea’s RoleModel has no custom-header injection; per-role base_url (path) is the only available lane-selection axis.
- Backend-global ZDR means each ZDR model requires its own AgentgatewayBackend — two roles, two backends, two routes.
- The path-prefix pattern is already proven in-cluster (engram’s /engram-embed/v1/embeddings), with no URL-rewrite filter needed.
- Cost: open models are ~5-80x cheaper per output token than claude-sonnet-4-6 for fovea’s workload.
- ZDR is preserved for private PR diffs, matching the octopus/engram precedent for code-bearing traffic.
Alternatives Considered
Section titled “Alternatives Considered”- Path-prefix HTTPRoutes per role (chosen): mirrors the proven engram pattern; zero client-code change via per-role base_url; cleanly disambiguates two ZDR backends.
- Header-based ZDR lane selection (rejected): fovea’s RoleModel cannot inject the x-agentgateway-backend header — structurally blocked.
- Single shared ZDR lane with model alias switching (rejected): backend-global ZDR pins one model per backend; two-model routing from one backend is impossible in the agentgateway CRD.
Consequences
Section titled “Consequences”- Positive: fovea unified onto the cluster gateway with OTel telemetry + virtual-key auth; per-role model selection with no upstream fovea change; ZDR contract maintained; break-glass revert to Anthropic-direct is a one-line flip (retained anthropicKey).
- Negative: two new HTTPRoutes + one new AgentgatewayBackend on the gateway surface; path prefixes are fovea-specific and not reusable by other clients.
- Neutral: GLM-5.2 deepdive structured output is unproven in-cluster (require_parameters: true forces loud failure, not silent degradation); the global openai.base_url defaults to the scout lane, with deepdive overriding it.