# Use the OpenAI SDK with Claude and Gemini: what works, what doesn't

URL: https://infro.io/blog/openai-sdk-claude-gemini
Author: INFRO Editorial (https://infro.io/blog/editorial)
Publisher: INFRO
Published: 2026-10-20
Last modified: 2026-10-20
Last reviewed: 2026-10-20 (next review due 2026-11-19)
Topic: Architecture and migration
Format: Guide

> Anthropic's compatibility endpoint is https://api.anthropic.com/v1/ and Google's is https://generativelanguage.googleapis.com/v1beta/openai/; both accept the OpenAI SDK with the provider's own key and model names. Anthropic says its layer is primarily for testing and comparing models: it ignores strict function schemas and response_format, does not support prompt caching, and hoists every system message to the top. Google labels its layer beta and passes Gemini-specific options through extra_body. For production, use the native SDKs or a gateway that translates to each provider's own API.

Key takeaways:
- Claude: base URL https://api.anthropic.com/v1/ with a Claude API key. Gemini: https://generativelanguage.googleapis.com/v1beta/openai/ with a Gemini API key.
- Anthropic calls its layer primarily for testing and comparison, not a long-term production solution for most use cases.
- On Claude, strict schemas and response_format are ignored and prompt caching is unsupported, so JSON and cost behave differently than on the native API.
- Google labels its layer beta; Gemini-only options such as cached content and search grounding go through extra_body.
- For production multi-provider code, use native SDKs behind your own interface, or a gateway that speaks each provider's own API.

**Can you call Claude and Gemini with the OpenAI SDK?** Yes. Point the client at Anthropic's `https://api.anthropic.com/v1/` or Google's `https://generativelanguage.googleapis.com/v1beta/openai/`, use that provider's API key and model name, and Chat Completions calls work[1][2]. Both providers are also clear about the cost: Anthropic says its layer is "primarily intended to test and compare model capabilities" and is not considered a long-term or production-ready solution for most use cases[1], and Google labels its support beta[2].

This guide shows the setup for each, lists what each layer ignores, and gives a rule for when to use it and when not to.

## Claude through the OpenAI SDK

```python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["ANTHROPIC_API_KEY"],
    base_url="https://api.anthropic.com/v1/",
)

reply = client.chat.completions.create(
    model="claude-sonnet-5-5",
    messages=[
        {"role": "system", "content": "You are a concise assistant."},
        {"role": "user", "content": "Name three uses of a message queue."},
    ],
)
print(reply.choices[0].message.content)
```

A key with access to several workspaces must also send the `anthropic-workspace-id` header on every request[1].

### What Anthropic's layer ignores or changes

| OpenAI feature | Through the compatibility layer |
| --- | --- |
| `strict` on function schemas | Ignored: tool JSON is not guaranteed to match the schema |
| `response_format` | Ignored |
| Prompt caching | Not supported (supported in Anthropic's SDKs) |
| System and developer messages | Hoisted and concatenated into one top-level system prompt |
| Audio input, file parts | Ignored or stripped |
| `reasoning_effort`, `seed`, `logprobs`, `user`, `metadata` | Ignored |
| `n` | Must be 1 |
| `temperature`, `top_p` | Non-default values return 400 on Claude 4.7 and later |
| Forced `tool_choice` | Returns an error on Opus 5.5, Sonnet 5.5 and Fable 5.1; use `auto` |
| `usage.prompt_tokens_details` | Always empty |

Table: From Anthropic's OpenAI SDK compatibility page, 2026-10-20.

Three of these change production behaviour more than they look:

- **No guaranteed JSON.** With `strict` and `response_format` ignored, code that relied on OpenAI's structured outputs gets well-formed JSON most of the time and not always. Anthropic points to Structured Outputs on its native API for guaranteed conformance[1]. [Structured outputs across providers](https://infro.io/blog/structured-output-reliability) compares the options.
- **No prompt caching.** A long system prompt or document context is billed at the full input rate on every request through this layer, where the native API could read it from cache for a small fraction of that rate.
- **Thinking is invisible.** Thinking can be switched on with `extra_body`, but the OpenAI SDK does not return Claude's thinking[1].

Most unsupported fields are silently ignored rather than rejected[1], so a migration that "works" on the first test can still be running without the behaviour you assumed.

## Gemini through the OpenAI SDK

```python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["GEMINI_API_KEY"],
    base_url="https://generativelanguage.googleapis.com/v1beta/openai/",
)

reply = client.chat.completions.create(
    model="gemini-3.8-flash",
    reasoning_effort="low",
    messages=[{"role": "user", "content": "Name three uses of a message queue."}],
)
print(reply.choices[0].message.content)
```

Google's layer is broader than Anthropic's. Its page covers chat completions with streaming, function calling, structured output and image and audio input; image generation; video generation through an asynchronous `/videos` endpoint; embeddings; batch jobs (with file upload and download through Google's own SDK); and model listing[2].

Things to know:

- **Thinking maps to `reasoning_effort`.** Values `minimal`, `low`, `medium` and `high` map to Gemini's thinking levels; `none` works only on 2.5 models, because reasoning cannot be turned off on 2.5 Pro or Gemini 3 models. Do not combine `reasoning_effort` with Gemini's own thinking settings[2].
- **Gemini-only features go in `extra_body`.** Thinking configuration with thought summaries, `cached_content` for context caching, Google Search grounding (Gemini 3 or newer) and video options are passed that way[2].
- **Unlisted image parameters are silently ignored**, and the whole layer is labelled beta[2].

## When the compatibility layers are the right tool

| Situation | Use the compatibility layer? |
| --- | --- |
| Comparing models on your own prompts this week | Yes: fastest way to try them |
| A prototype or internal tool | Usually yes |
| Production traffic that needs guaranteed JSON | No, on Claude |
| Long repeated prompts where caching matters | No, on Claude; check `extra_body` on Gemini |
| Features that exist only natively (Claude's citations, PDFs, thinking blocks) | No |
| A product that may move between providers | Not on its own: see below |

The layers solve "I want to try another model without rewriting my client". They do not solve "my product should run on several providers and fail over between them": each layer only reaches its own provider, each has different gaps, and a request that fails on one has nowhere to go.

## A checklist for comparing models through these layers

Compatibility layers are a good way to run a quick comparison, provided the comparison is fair:

- [ ] **Same prompts, adapted once.** Anthropic notes that a prompt tuned heavily for OpenAI's models may need reworking for Claude[1]. Give each model one honest prompt pass, then freeze the prompts.
- [ ] **Same output contract.** If your code relies on JSON, validate every answer against the schema yourself during the test, because neither layer guarantees it the way OpenAI's strict mode does.
- [ ] **Same sampling settings where the model accepts them.** Claude 4.7 and later reject non-default `temperature` and `top_p`[1], so remove them for every model rather than comparing different settings.
- [ ] **Cost in dollars, not tokens.** Tokenizers differ, and the usage details these layers return can be empty; compute cost from each provider's own token counts and rates.
- [ ] **Latency from your region.** Measure time to first token and total time from where your application runs.
- [ ] **A reason to stop.** Decide in advance what result would make you move a workload, so the comparison ends in a decision.

Once a model wins, move that workload to the provider's native API or to a gateway that calls it natively, and re-run the comparison there: caching and structured outputs can change both the cost and the reliability you measured.

## Two production patterns for multiple providers

**Native SDKs behind your own interface.** Write a thin internal interface — `complete(messages, schema, model_class)` — and implement it with each provider's own SDK. You get every native feature, including caching and structured outputs, at the cost of maintaining the adapters. [Multi-model API architecture](https://infro.io/blog/multi-model-api-architecture) covers the design.

**A gateway that speaks each provider's own API.** Your application speaks one dialect to the gateway; the gateway translates to each provider's native API and can fail over between them. Ask any gateway exactly which fields it translates and which it drops per provider, because that list is the real product.

## Using INFRO

INFRO is a gateway on provider accounts you connect. Your application calls `https://api.infro.io/v1` in OpenAI's shape and names a model such as `anthropic/claude-sonnet-5.5` or `google/gemini-3.8-flash`; INFRO calls each provider's own API with your key, so you are not limited to the compatibility layers above. Parameters a model does not accept are adjusted per model and named in the `X-INFRO-Params-Dropped` header rather than dropped silently. For code that wants Anthropic's own API, INFRO also answers `POST /v1/messages` in Anthropic's shape, sent to Anthropic as written. Routes can fail over from one provider to another for the same request, and every request is recorded with an estimated provider cost.

## Summary

Use Anthropic's and Google's OpenAI-compatible endpoints to try models quickly. Before shipping on them, read each provider's list of ignored fields against the features you depend on — JSON guarantees and prompt caching above all — and for production multi-provider code, either own the adapters or use a gateway that calls each provider natively.

## Questions

### Can I use the OpenAI Python SDK with Claude?

Yes. Set base_url to https://api.anthropic.com/v1/, use a Claude API key and a Claude model name. Anthropic describes the layer as primarily for testing and comparing models: strict function schemas and response_format are ignored, prompt caching is not supported, and audio input is stripped.

### What is the Gemini OpenAI-compatible base URL?

https://generativelanguage.googleapis.com/v1beta/openai/, used with a Gemini API key. Google's page covers chat completions with streaming, function calling and structured output, images, video, embeddings, batch and model listing, and labels OpenAI library support as beta.

### Does prompt caching work through Claude's OpenAI compatibility layer?

No. Anthropic's compatibility page says prompt caching is not supported there; it is supported in Anthropic's own SDKs. On long, repeated prompts that difference can change the cost of a request several times over.

## Sources

1. OpenAI SDK compatibility — Anthropic. https://platform.claude.com/docs/en/cli-sdks-libraries/libraries/openai-sdk (accessed 2026-10-20)
2. OpenAI compatibility — Google. https://ai.google.dev/gemini-api/docs/openai (accessed 2026-10-20)
