Phase 4 operator platform

Docs-truth close for the Phase 2.5 / ADR-0040 Anthropic adapter: verification that SSE translation, anthropic-version, and system-role extraction already shipped, plus minor stream-translate test hardening.

Milestone 4.C.1 — Anthropic Adapter Hardening

Status: Completed
Goal: Track C — Multi-Provider Adapters & Resilience
Phase: 4 — Operator Platform & Multi-Provider
Estimated effort: 3 days
Track: Track C — Multi-Provider Adapters & Resilience


Why This Milestone Exists

The Anthropic adapter already shipped in Phase 2.5 (2.5.G1.M1) and is documented in ADR-0040 (Accepted 2026-08-21): OpenAI-compatible SSE translation, anthropic-version on every request, system-role extraction (leading + mid-conversation fold), and mid-stream event: error → pipe CloseWithError (no JSON-swap). Phase 2.5’s exit gate already checked Anthropic test-depth parity with OpenAI.

This milestone is therefore not a greenfield hardening pass. It closes roadmap drift against live code and adds two small, additive stream-translate test assertions (incomplete mid-stream body; explicit ignore of non-text delta types). No adapter behavior change; no proxy handler/middleware changes.


Non-Goals

  • Tool-use / image / vision / thinking passthrough
  • ANTHROPIC_API_VERSION env wiring
  • Shared parameterized OpenAI/Anthropic stream harness
  • Per-org model routing (4.C.2)
  • Circuit breaker (4.C.3)
  • Azure OpenAI or Bedrock adapters (future)
  • Changes to packages/provider/openai/** or services/proxy/** handlers/middleware

Shipped surface (already in tree)

Request construction

  • packages/provider/anthropic/request.go — peel leading system messages + fold mid-conversation systems into top-level system; reject tool role; deny-by-default passthrough allowlist (text-only).
  • packages/provider/anthropic/client.go — newMessagesRequest sets x-api-key, anthropic-version, Content-Type on every Messages call.

Streaming translation

  • packages/provider/anthropic/stream_translate.go — Anthropic named events → OpenAI-compatible SSE; non-text_delta content deltas ignored; mid-stream event: error → CloseWithError (no [DONE], no fabricated OpenAI error chunk in the pipe body).
  • Retry does not re-issue after a live stream body has started (retry.go).

Registry / capabilities

  • Built-in IDs: claude-sonnet-4-5, claude-haiku-4-5, claude-opus-4-5 (+ ExtraModels).
  • Capability rows in capability_catalog.go (context window / streaming flags); tools/vision flags are vendor-capability metadata, not a claim that the adapter implements tool/image passthrough.

Success signals

  • Exact-ID Registry.For("claude-sonnet-4-5") (and sibling Claude IDs) resolves when Anthropic is registered; NewRegistry returns ErrDuplicateModel on colliding model IDs
  • Streaming translation emits OpenAI-shaped chunks suitable for ADR-0027 dual-write; mid-stream Anthropic event: error terminates the translate pipe as incomplete (no data: [DONE], no fabricated OpenAI-shaped error chunk) — asserted in stream_translate_test.go
  • Anthropic HTTP / mapped provider errors continue through provider.MapError / existing failure paths — no proxy handler special-case for Anthropic
  • Non-streaming and streaming fixture coverage lives in packages/provider/anthropic (inline httptest / SSE fixtures; no separate golden-file harness required)
  • Zero proxy handler or middleware changes for this milestone (docs + Anthropic package tests only)
  • Non-text stream deltas (input_json_delta, thinking_delta, signature_delta) are ignored without leaking into OpenAI-shaped output

Local verification

  1. go test ./packages/provider/anthropic/...
  2. go test ./packages/provider/...
  3. go test ./services/proxy/... (regression only; no proxy edits)

Prerequisites

  • Phase 2.5 Anthropic adapter merged (2.5.G1.M1 / ADR-0040)
  • packages/provider.Provider interface stable (M2.1.1)
Edit on GitHub

Last updated on