Use Claude with the OpenAI SDK Without Rewriting Your Client
Call Claude from the OpenAI SDK for evaluation, then use a gateway that adapts OpenAI ingress to native Claude Messages for production.
You can point the official OpenAI Python or TypeScript SDK at Claude by changing base_url, the API key, and the model ID, then keep using chat.completions. Anthropic documents that path in its OpenAI SDK compatibility guide. The same client shape can also hit an OpenAI-compatible API gateway that stores Anthropic credentials server-side and converts OpenAI-style requests into native Claude Messages upstream.
Those two paths are not equivalent. Direct compatibility is for evaluation. A production gateway that speaks OpenAI to clients and Claude Messages to Anthropic is a different reliability story.
Evaluation path versus production path
Anthropic states that its OpenAI compatibility layer is primarily for testing and model comparison and is not a long-term or production-ready solution for most use cases. Treat that sentence as product policy, not marketing fine print.
| Path | Client | Upstream | Best for |
|---|---|---|---|
| Direct Anthropic compatibility | OpenAI SDK → https://api.anthropic.com/v1/ | Anthropic's OpenAI-shaped surface | Local eval, prompt bake-offs, short spikes |
| Gateway OpenAI ingress | OpenAI SDK → your gateway /v1 | Gateway converts to native Claude Messages | Shared keys, quotas, failover, multi-provider products |
| Native Anthropic SDK / Messages API | Anthropic client | Full Claude feature set | Prompt caching, citations, extended thinking details, guaranteed structured outputs |
Use the first row to answer "is Claude good enough on our fixed suite?" Use the second when several services need Claude without each holding an Anthropic key. Use the third when you need Claude-native controls that the compatibility layer omits or ignores.
This repository's Claude channel converts OpenAI Chat Completions into Claude Messages (RequestOpenAI2ClaudeMessage and related adaptors). That is not the same as proxying Anthropic's compatibility endpoint unchanged. Clients still speak OpenAI JSON; the control plane owns mapping, credentials, and usage logs.
Important limits of Anthropic's OpenAI compatibility layer
When you call api.anthropic.com with the OpenAI SDK, current Anthropic docs call out concrete gaps. Budget for them before anyone claims "drop-in parity."
stricton tools is ignored. Tool argument JSON is not guaranteed to match the supplied schema. Validate arguments in your runtime (or use native Claude structured outputs when you need server-side guarantees).- Audio input is stripped. Multimodal audio parts are ignored rather than rejected with a loud error.
- Prompt caching is unsupported on the compatibility path. Caching remains available through Anthropic's own SDKs and native API.
- System and developer messages are hoisted and concatenated into a single leading system message. Anthropic supports one initial system message; OpenAI-style mid-conversation system/developer turns are merged with newlines.
- Most unsupported fields are silently ignored. Staging should fail closed when a field changes product behavior if it disappears upstream.
- Error bodies keep OpenAI-shaped envelopes but detail text is not equivalent to OpenAI's. Log for debugging; do not parse prose as a stable contract.
Full Claude features such as PDF processing, citations, extended thinking with detailed thought access, and prompt caching belong on the native Claude API (or a gateway path that maps to those native fields). For agent tool loops that must stay portable across brands, see portable tool calling across providers.
Direct Anthropic base URL (evaluation)
Anthropic's documented Python pattern:
from openai import OpenAI
import os
client = OpenAI(
api_key=os.environ["ANTHROPIC_API_KEY"],
base_url="https://api.anthropic.com/v1/",
)
response = client.chat.completions.create(
model="claude-sonnet-5", # or claude-opus-4-8; verify on Anthropic model docs
messages=[
{"role": "system", "content": "You are a precise API integration assistant."},
{"role": "user", "content": "Summarize three risks of hardcoding provider SDKs."},
],
max_tokens=800,
)
print(response.choices[0].message.content)
TypeScript:
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.ANTHROPIC_API_KEY,
baseURL: "https://api.anthropic.com/v1/",
});
const response = await client.chat.completions.create({
model: "claude-sonnet-5",
messages: [
{ role: "system", content: "You are a precise API integration assistant." },
{ role: "user", content: "Summarize three risks of hardcoding provider SDKs." },
],
max_tokens: 800,
});
console.log(response.choices[0]?.message?.content);
Official examples often use claude-opus-4-8. Current Anthropic model docs also list Claude Sonnet 5 and Claude Haiku 4.5. Prefer the live model table over any blog snapshot, including this one.
Gateway base URL (production-shaped multi-service)
When Claude is one channel among many, point the same SDK at the gateway and keep the Anthropic credential only on the server:
client = OpenAI(
api_key="GATEWAY_API_KEY",
base_url="https://your-gateway.example.com/v1",
)
response = client.chat.completions.create(
model="claude-sonnet", # stable gateway alias mapped to a current Claude ID
messages=[
{
"role": "user",
"content": "Draft a migration checklist for SDK consolidation.",
}
],
max_tokens=800,
)
Operators map aliases such as claude-sonnet or claude-opus to raw upstream IDs (claude-sonnet-5, claude-opus-4-8, dated snapshots when required). Application configs should depend on aliases so an upstream rename is a channel edit, not a multi-repo incident. That is the control plane described in multi-provider LLM gateway.
What usually ports on the common path
Messages
- Ordinary
system/user/assistantchat history works for evaluation and most product chat. - Mid-conversation system or developer turns are not preserved as separate OpenAI roles on Anthropic's compatibility layer; expect merge behavior.
- Keep policy text explicit. Do not assume Claude inherits hidden instructions tuned only for OpenAI models.
Tools
OpenAI-style tools definitions often work for early agent ports. Example:
tools = [
{
"type": "function",
"function": {
"name": "lookup_order",
"description": "Fetch an order by ID from the shop system",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
},
},
}
]
response = client.chat.completions.create(
model="claude-sonnet-5",
messages=[{"role": "user", "content": "Where is order A-100?"}],
tools=tools,
tool_choice="auto",
)
message = response.choices[0].message
if message.tool_calls:
for call in message.tool_calls:
print(call.function.name, call.function.arguments)
Because strict is ignored on Anthropic's compatibility surface, parse and schema-validate arguments before any side effect. On a gateway path, still validate in the tool executor; never trust model-emitted JSON alone.
Streaming
SSE streaming matches what most OpenAI chat UIs already consume. Confirm first-token latency, mid-stream error handling, and whether your gateway normalizes Claude stream events into a stable client shape. Automatic provider switching after partial tokens is harder than pre-stream failover; pair this with LLM API failover strategy.
Structured output, safety, and observability gaps
If a pipeline depends on strict JSON Schema enforcement, test the exact schema on Claude before claiming parity. Where strict mode is incomplete, validate in application code or use native Claude structured outputs.
Providers differ on refusals, rate-limit headers, and token accounting even when JSON keys look identical. Normalize error classes at the gateway if clients expect one contract. Do not retry permanent auth or policy failures as if they were transient 5xx responses.
Direct Anthropic keys and gateway keys produce different audit trails. Teams usually want usage history next to channel health rather than only in a single-provider console. Public pricing and model catalog pages help stakeholders; keep authenticated operator URLs out of every paragraph.
Controlled cutover sequence
- Inventory services that already depend on the OpenAI SDK or raw
/v1/chat/completions. - Run a fixed eval suite against Anthropic's compatibility endpoint with one Claude model ID.
- Register Anthropic credentials as a gateway channel and publish a stable alias.
- Point one low-risk internal job at the gateway alias; do not flip customer chat first.
- Compare schema validity, refusal rate, latency, and cost per successful task.
- Add tools and streaming only after plain chat is stable.
- Document rollback: keep the previous model alias live.
HTTP smoke test
curl https://your-gateway.example.com/v1/chat/completions \
-H "Authorization: Bearer $GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet",
"messages": [
{"role": "user", "content": "Reply with the single word ready."}
],
"max_tokens": 32
}'
Expect Chat Completions-shaped JSON with choices[0].message.content. If the envelope diverges, fix mapping before product code.
Production checklist (gateway path)
- Eval proved quality on a fixed suite; production traffic does not rely on Anthropic's compatibility layer as the long-term hop.
- Model alias maps to a current Claude ID from Anthropic docs or your maintained catalog.
- Secrets live in the gateway or secret manager, never in browsers or mobile apps.
-
max_tokensis explicit; silent defaults can truncate long answers. - Tool arguments are schema-validated server-side; do not depend on ignored
strict. - Streaming clients handle incomplete finals and mid-stream errors.
- Cost and error dashboards separate Claude from other providers.
- Failover policy states whether Claude is primary, backup, or pinned.
When the gateway beats a direct Anthropic base URL
| Trigger | Why the gateway helps |
|---|---|
| Multiple providers in one product | One client config, many channels |
| Team-wide credentials | Scoped gateway keys instead of shared Anthropic keys |
| Spend reviews | Unified usage history and pricing context |
| Reliability targets | Retry and failover without rewriting each service |
| Agent fleets | Central policy for tools and model routing |
AveMujica API is built as that control plane: OpenAI-compatible ingress, provider channels, model catalog, and operational history. It does not remove the need to read Anthropic's compatibility notes; it keeps those notes from turning into five divergent client forks.
Official sources
- Anthropic OpenAI SDK compatibility
- Anthropic models overview
- OpenAI Chat Completions reference
- OpenAI Python SDK
Last checked: 2026-07-15. Re-verify model IDs and compatibility limitations on Anthropic's docs before any production freeze.
Common questions
Is Anthropic's OpenAI SDK path production-ready?
Anthropic describes it as primarily for testing and comparison, not a long-term production solution for most use cases. For production fleets, prefer a gateway that adapts OpenAI ingress to native Claude Messages, or use Anthropic's native API where you need Claude-only features.
Can every OpenAI Chat Completions field run unchanged on Claude?
No. strict is ignored, audio is stripped, prompt caching is unavailable on the compatibility layer, and system/developer turns are merged. Test the exact request shape you ship.
Which model string should land in application config?
Prefer a gateway alias (claude-sonnet) mapped by operators to a current ID such as claude-sonnet-5 or claude-opus-4-8. Avoid hardcoding yesterday's snapshot across every service.
Do I still need the Anthropic SDK?
Yes when you intentionally need native-only controls (prompt caching markers, full extended thinking access, native structured outputs). Keep the OpenAI SDK when the OpenAI-shaped surface is enough and the gateway owns provider diversity.
Ship the first Claude cutover
Pick one service that already uses the OpenAI SDK. Prove quality on Anthropic's compatibility endpoint, then move that service to a gateway alias that routes to Claude Messages. Only after plain chat is green, expand tools and streaming and compare the first day's traffic against your previous OpenAI baseline.