Same Model, Three APIs: Contract-Testing with Docker Model Runner A developer demonstrated a contract-testing approach that runs OpenAI-, Anthropic-, and Ollama-compatible protocol adapters against a single local model environment using Docker Model Runner, arguing that "OpenAI-compatible" is shorthand rather than a portability guarantee. The method normalizes each wire format into a small ChatResult type, then applies shared tests for bounded responses, streaming deltas, cancellation, error mapping, JSON schema validation, and tool calling. Unsupported behavior is made explicit through an AdapterCapabilities type so applications fail fast instead of discovering gaps mid-run. “OpenAI-compatible” is useful shorthand. It is not a portability guarantee. Two APIs may accept similar chat messages while differing in streaming events, tool calls, token counts, error shapes, stop reasons, and supported parameters. Swapping a base URL can make a demo work while leaving the production abstraction full of assumptions. Docker Model Runner is a useful local contract target because it exposes OpenAI-, Anthropic-, and Ollama-compatible formats over one local model environment. Instead of comparing three remote providers, we can test three protocol adapters against controlled local infrastructure. Keep provider objects out of domain code: type ChatRequest = { messages: Array<{ role: "user" | "assistant"; content: string } ; maxOutputTokens: number; stream?: boolean; }; type ChatResult = { text: string; finishReason: "stop" | "length" | "tool" | "unknown"; inputTokens?: number; outputTokens?: number; }; interface ModelAdapter { id: string; chat request: ChatRequest : Promise