IBEX Harness
DocsBenchmarksBlogChangelogRoadmap
GitHub
IBEX Harness

Documentation

Architecture Decision RecordsADR-0002: Repository foundation bootstrapADR-0003: Branch protection and merge policyADR-0004: Protobuf and code generation policyADR-0005: Postgres migration strategyADR-0006: Auth protobuf contract (`ibex.auth.v1`)ADR-0007: Auth token validation implementationADR-0008: Security scanning and CI quality gatesADR-0009: Permission bitmap layoutADR-0010: Cryptography policyADR-0011: Proxy auth gRPC client and middlewareADR-0012: Proxy request normalization (OpenAI chat)ADR-0013: Proxy input validation and stable error envelopeADR-0014: Core domain migration sequencingADR-0015: Proxy rate limit skeleton (Phase 1)ADR-0016: Proxy agent identity verification (Phase 1)ADR-0017: Request ID and trace context strategy (Phase 1)ADR-0018: Graceful shutdown contract (Phase 1)ADR-0019: OpenTelemetry provider configuration (Phase 1)ADR-0020: Shared package boundaries — `packages/config` and `packages/apierror`ADR-0021: Prometheus Metric Catalog (Phase 1)ADR-0022: Health check contract (Phase 1)ADR-0023: Docs site architecture (Phase 1.5)ADR-0024: Benchmark data publishing modelADR-0025: LLM provider abstractionADR-0026: OpenAI client designADR-0027: Streaming dual-write strategyADR-0028: Auth cache designADR-0029: Token revocation propagation via Redis pub/subADR-0030: Directive versioning strategyADR-0031: System prompt injection strategyADR-0032: Session data model and retentionADR-0033: ClickHouse llm_traces schema and retentionADR-0034: Proxy overhead performance measurement methodologyADR-0035: Chat Idempotency-Key Redis dedupeADR-0038: Context assembly service design and gRPC contractADR-0039: Proxy Postgres ownership for session and directive storesADR-0040: Anthropic provider adapterADR-0041: Model capability registryADR-0042: Self-hosted OpenAI-compatible LLM adapterADR-0043: Tokenizer registry architectureADR-0044: Non-streaming response pipelineADR-0045: Streaming response transformationADR-0046: Embedder interface and profile registryADR-0047: Memory temporal validity foundationADR-0048: Memory multi-label categoriesADR-0049: Memory relationship graph readinessADR-0050: MCP server skeleton (transport, auth, audit)ADR-0051: Local LGTM observability stack (Phase 2.5 exit pull-forward)ADR-0052: Memory schema v2 expand (HNSW, quality columns)ADR-0053: Vector store abstraction and composite scoring v2
ADRs›ADR-0026: OpenAI client design
ADRs

ADR-0026: OpenAI client design

Architecture decision record 0026 — OpenAI HTTP client, retry policy, env contract, and proxy forwarding for Phase 2.

ADR-0026: OpenAI client design

  • Status: Accepted
  • Date: 2026-07-12
  • Authors: IBEX Harness team
  • Milestone: 2.1.2 OpenAI non-streaming client

Context

Milestone 2.1.1 shipped packages/provider with an empty registry. Phase 2 Goal 2.1 requires POST /v1/chat/completions with stream=false to return a real OpenAI completion. The first concrete adapter lives in packages/provider/openai/ and is registered by the proxy at startup.

Prior engineering docs (ENVIRONMENT_VARIABLES.md §9) described generic IBEX_PROVIDER_* variables that were never wired. Phase 2 is OpenAI-first; Anthropic env vars and multi-key live registration land in Phase 2.5 (ADR-0040).

Decision

1) Environment contract

VariableRequiredDefaultPurpose
IBEX_LLM_MODENomockmock = empty registry (501 for chat); live = register OpenAI
OPENAI_API_KEYWhen live—OpenAI API key (secret; never logged)
OPENAI_BASE_URLNohttps://api.openai.com/v1API base URL
OPENAI_REQUEST_TIMEOUTNo120sPer-request HTTP timeout
OPENAI_MAX_RETRIESNo3Retries on transient failures
OPENAI_RETRY_BASE_DELAYNo500msExponential backoff base

IBEX_PROVIDER_* circuit-breaker variables remain documentation-only until multi-provider work.

2) Retry policy

Retry on HTTP 429, 500, 502, 503, 504 and retryable network errors. Do not retry 400, 401, 403, 404. Backoff: min(base * 2^attempt + jitter, 30s). Honor Retry-After on 429 when present.

3) HTTP transport

Single shared http.Client per process with connection pooling (MaxIdleConnsPerHost: 20). Constructed once in openai.New.

4) Request translation

services/proxy/internal/llm.ToProviderRequest converts parsed chat bodies to provider.Request. OpenAI-specific JSON marshaling stays in packages/provider/openai. Directive injection is not in this client — see ADR-0025 §5 and milestone 2.3.3.

Unknown top-level JSON fields from the chat parser are ignored. provider.Request.PassthroughFields merges permitted OpenAI fields (for example top_p) into the outbound body; model, messages, and stream cannot be overridden.

5) Streaming

Streaming is implemented in milestone 2.1.3. See ADR-0027 for dual-write, flush, and no-retry-after-start rules. The OpenAI client sets Accept: text/event-stream when Request.Stream is true and returns the live SSE body to the proxy.

6) Error mapping

  • Client: returns provider.ProviderError for non-2xx HTTP responses; transport errors as wrapped errors.
  • Shared mapper (2.1.5): provider.MapError / MapProviderError → apierror.Error; proxy writes via apierror.WriteHTTP.
  • Pre-stream failures (including stream=true before first SSE byte) use the same mapper; mid-stream failures follow ADR-0027 verbatim close (no JSON swap).

7) Observability

OTel span openai.Complete with provider.name and llm.model attributes. Prometheus counters: ibex_proxy_provider_requests_total{provider,status_class}, ibex_proxy_provider_retries_total{provider}. Never log API keys, message content, or raw provider bodies.

8) Supported models (Phase 2)

gpt-4o, gpt-4o-mini, gpt-4-turbo, gpt-3.5-turbo.

Consequences

Positive:

  • First end-to-end non-streaming forward with CI-safe IBEX_LLM_MODE=mock
  • Clear env contract for operators enabling live mode
  • Registry lookup lives in ProviderRoutingMiddleware (milestone 2.1.4); handler reads provider from context
  • Provider → IBEX envelope mapping centralized in packages/provider (milestone 2.1.5)

Negative:

  • (none outstanding for error mapping; Phase 4 may add provider-specific nuance without changing the shared table)

References

  • ADR-0025: LLM provider abstraction
  • Provider adapters
  • Milestone 2.1.2

Was this page helpful?

Edit on GitHub

Last updated on

PreviousADR-0025: LLM provider abstractionNextADR-0027: Streaming dual-write strategy

On this page

  • Context
  • Decision
  • 1) Environment contract
  • 2) Retry policy
  • 3) HTTP transport
  • 4) Request translation
  • 5) Streaming
  • 6) Error mapping
  • 7) Observability
  • 8) Supported models (Phase 2)
  • Consequences
  • References
0%