Phase 2.5 provider generalization
Phase 2.5 — Goals
Generalize the proxy into a pluggable, multi-backend platform with provider adapters, tokenizer registry, response pipeline, embedding service, schema pre-work, and MCP skeleton.
Phase 2.5 — Goals
Track A — Multi-Provider Adapters
Goal 2.5.A: Prove the Provider interface generalizes beyond OpenAI
Milestones:
- 2.5.G1.M1 — Anthropic provider adapter: Implement
packages/provider/anthropic/provingprovider.Request/provider.Responseare vendor-neutral. Handles system-field extraction, Anthropic SSE event parsing, and error mapping to the sharedapierror.Errorenvelope. - 2.5.G1.M2 — Model capability registry:
ModelCapabilitystruct with context window, max output tokens, tool/vision/streaming support, and tokenizer family.Registry.Capability(model)alongsideRegistry.For(model). - 2.5.G1.M3 — Self-hosted LLM adapter (vLLM-first): Generalized
openaicompatiblepackage reusing OpenAI client logic with configurablebase_url. Health-check at bootstrap, circuit breaker for self-hosted backends, explicit 503/queue-full mapping.
Acceptance criteria:
- Second provider added without duplicating streaming/auth logic
ModelCapabilityqueryable for all registered models- Self-hosted vLLM endpoint registered and health-checked at bootstrap
Track B — Tokenizer Registry
Goal 2.5.B: Model-accurate token counting for every registered model
Milestones:
- 2.5.G2.M1 — Tokenizer registry:
packages/tokenizerGo package withTokenizerinterface (Count(model, text) (int, error)). tiktoken for OpenAI models, Hugging Facetokenizersvia CGo bindings for open-weight models. Tokenizers loaded once at startup, keyed byTokenizerFamilyfrom the capability registry.
Acceptance criteria:
- Token counts match ground truth for OpenAI and at least one open-weight model family
- No network dependency on Hugging Face at runtime (tokenizer files bundled or cached locally)
Track C — Response-Side Processing Pipeline
Goal 2.5.C: Create the extension point for Phase 3 response stages
Milestones:
- 2.5.G3.M1 — Response middleware hook (non-streaming):
ResponsePipelinewithStageinterface inpackages/responsepipeline. Typed decode of OpenAI chat response JSON, pipeline execution, re-encode. Fail-open by default. p99 overhead < 2ms benchmarked. - 2.5.G3.M2 — Streaming response pipeline design (design doc + prototype only): ADR evaluating token-window buffering vs. post-hoc correction vs. disable-for-flagged-agents. Throwaway prototype measuring buffering-vs-flush interaction.
Acceptance criteria:
- Byte-for-byte identical output vs. current passthrough when pipeline has zero stages
- ADR published with streaming transformation decision
Track D — Multi-Backend Pluggable Embedding Service
Goal 2.5.D: Embedding backends selectable per deployment profile
Milestones:
- 2.5.G4.M1 — Embedder interface + registry: Python ABC (
EmbeddingBackend), selected byEMBEDDER_PROFILEenv (cpu/gpu/hosted). Profile is a deployment-time choice, not per-request. - 2.5.G4.M2 — TEI backend (GPU): HTTP client to Hugging Face TEI sidecar running
BAAI/bge-m3. No hand-rolled batching — TEI handles it. - 2.5.G4.M3 — Hosted-API backend: OpenAI
text-embedding-3-largeas default hosted option. - 2.5.G4.M4 — Content-hash embedding cache: Redis
SHA-256(text) -> vectorcache, backend-agnostic, >80% hit-rate target.
Acceptance criteria:
- At least two real
EmbeddingBackendimplementations (TEI + hosted OpenAI or Cohere) passing the same contract test suite; CPU MiniLM profile remains stub (ADR-0046) - Org config carries
embedding_profile+embedding_dim, validated against pgvector column at migration time - Re-embedding migration runbook deferred to Phase 3 (non-goal for 2.5; exit criteria updated accordingly)
Track E — Schema Pre-Work
Goal 2.5.E: Prepare Postgres schema for Phase 3 memory store
Milestones:
- 2.5.G5.M1 — Temporal validity columns:
valid_from,valid_until,observed_atonibex_core.memories. Migration-only, no application code. - 2.5.G5.M2 — Multi-label category support:
ibex_core.memory_categoriesjoin table replacing singlecategoryenum exclusivity. - 2.5.G5.M3 — Relationship graph readiness: Graph-traversal index on
memory_relationships, helper view for recursive CTE traversal.
Acceptance criteria:
- All three migrations apply cleanly on top of existing Phase 3 draft schema with zero application code depending on new columns
- Verified via
make db-migrateon a seeded dataset
Track F — MCP Server Skeleton
Goal 2.5.F: Prove MCP auth and tool-call audit pipeline before memory exists
Milestones:
- 2.5.G6.M1 — MCP server with stub tools: Python MCP server using official SDK. OAuth via
AuthService.ValidateTokengRPC. Stubwrite_memory/search_memoryhandlers. Every tool invocation traced to ClickHouse.
Acceptance criteria:
- MCP server passes official conformance/inspector tool against stub handlers
- Auth reuses
AuthService.ValidateTokenvia gRPC (no second identity system) - Tool invocations written to ClickHouse
ibex.mcp_tool_calls(notllm_traces; ADR-0050)
Track G — Exit / Ops Pack-Up
Goal 2.5.G: Prove Phase 2.5 seams operate together with local observability
Milestones:
- 2.5.G7 — Phase 2.5 exit gate: Local LGTM stack (ADR-0051),
make verify-phase25, multi-service e2e, thin K8s observability chart, roadmap sign-off.
Acceptance criteria:
make observability-up/make observability-smokegreen with Proxy Critical Path dashboardmake verify-phase25maps exit criteria to runnable checks- Phase roadmap status completed; Phase 3 entry clear
Edit on GitHub
Last updated on