Integrations
Using Claude through an OpenAI-compatible gateway
Point an existing OpenAI-SDK app at Claude through Ragmux — no Anthropic SDK, and the message, tool and image translation Ragmux does for you.
Updated: Verified against Ragmux 0.5.0
Claude is reached through Ragmux the same way every other provider is: your application
keeps calling /v1/chat/completions in the OpenAI schema, and the gateway is the part
that actually speaks Anthropic’s Messages API on the other side. That matters if you
already have OpenAI-SDK code, a framework that only knows the OpenAI shape, or several
providers behind one integration and no appetite for a second SDK just for one of them.
Adding the connection
POST /admin/api/models with provider_type: anthropic, an api_key, and a
model_name such as claude-sonnet-4-5 creates the connection; base_url doesn’t need
to be set — it defaults to https://api.anthropic.com, but can be pointed elsewhere if
you front Anthropic with your own proxy — one on a private or local network still has to
be allowlisted first, the same as any other connection (see
Private upstreams). Once saved, the key is never returned by the
API again — every later read shows api_key_masked instead, and rotating it means
setting a new key on the same connection, not reading the old one back out. Before
pointing a real project at it, POST /admin/api/models/{id}/test with {"mode": "chat"}
sends one bounded completion — max_tokens: 256 — and returns latency and a sample reply,
which is the cheap way to catch a bad key or a mistyped model name before a user does.
What the gateway translates for you
An OpenAI-shaped request doesn’t map onto Anthropic’s Messages API field-for-field, and this is the actual value a gateway adds over calling Claude directly with hand-rolled translation code:
- System and developer messages become one field. OpenAI’s
systemanddeveloperroles are merged, in order, into the single top-levelsystemfield Anthropic’s API expects, sent as text blocks — Claude has nosystemrole inside the message array itself. max_tokensis required, so Ragmux makes sure it’s always there. Anthropic rejects a request with nomax_tokens; a caller that never set one (normal for OpenAI, where it’s optional) gets4096filled in rather than a provider error surfaced back.- Sampling parameters map directly.
temperature,top_pandstopcarry across;n,response_formatanduserhave no Anthropic equivalent and are dropped rather than silently misapplied. A droppedresponse_formatis the one that announces itself: the response carries aWarning: 299 ragmux "response_format is not supported for anthropic connections; ignored"header, streams included, and the event is logged at info level. - Consecutive same-role messages are merged. Anthropic’s API expects strict user/assistant alternation; a caller that appends two user messages back to back before ever seeing an assistant reply has them combined into one, rather than the request failing on Anthropic’s side for a shape the caller didn’t know was invalid there.
- Tool calls translate both ways. OpenAI-shaped
toolsandtool_choicebecome Anthropic’stools/tool_choice, and a Claudetool_useblock comes back as an OpenAI-shapedtool_callsentry, so function-calling code written against OpenAI’s shape doesn’t need a Claude-specific branch. - Image URLs are handled the way Claude expects. Anthropic fetches an image URL itself rather than requiring the caller to inline it, so Ragmux passes the URL through as given.
- Finish reasons map to OpenAI’s vocabulary. Claude’s own stop reasons come back as
values OpenAI-SDK code already branches on:
end_turnandstop_sequencebecomestop;max_tokensandmodel_context_window_exceededbecomelength;tool_usebecomestool_calls;refusalbecomescontent_filter. A stop reason Ragmux doesn’t know becomesstopand is logged as a warning.
None of this is configurable per request; it’s the fixed translation every Anthropic connection gets, streaming and non-streaming alike, so the same client code that works against a streamed OpenAI response works against a streamed Claude one too.
What doesn’t carry over
A couple of things are worth knowing before they show up as a surprise rather than a
documented gap. Claude has no embeddings endpoint at all, so an Anthropic connection can
only ever back the chat half of a project — a private document Q&A
setup that wants Claude to answer still needs a separate openai, gemini, ollama or
custom_openai connection for the embedding half of the same RAG store. And a handful of
OpenAI-only parameters — response_format, n, user — are dropped rather than
emulated. For response_format the response says so in a Warning: 299 header; a caller
relying on OpenAI’s structured-output mode against a Claude connection needs to ask for
the shape in the prompt itself, because there’s no equivalent flag to forward.
Prompt caching works, but you have to ask for it
Claude bills cache writes as well as cache reads, and Ragmux relays a client’s
cache_control marker verbatim rather than inventing one on your behalf. Put
"cache_control": {"type": "ephemeral"} on a content part, a tool definition, or a
system/developer message’s content, and it’s copied onto the matching block Anthropic’s
API expects; leave it off, and a request against a Claude connection looks exactly like
it did before caching existed. The response accounting folds Anthropic’s own
cache_creation_input_tokens and cache_read_input_tokens into the OpenAI-shaped
usage.prompt_tokens_details object: reads become cached_tokens, the field OpenAI,
Gemini and DeepSeek connections populate too — custom_openai and ollama don’t report
cache usage at all (see the capability table) — while
cache_creation_tokens is Anthropic-specific: OpenAI doesn’t bill cache writes and Gemini
doesn’t report a separate write counter, so there’s nothing to report on those
connections. Both feed the per-request cost estimate when present. One gap worth knowing: the gateway doesn’t mark a cache
breakpoint on the system prompt or RAG context block it injects itself — that’s a
client-side decision today, not something a Claude connection does automatically.
After it’s connected
Everything else about the project is identical to any other provider: rate limits,
token budgets, the audit log and the request log all key off the project, not the
provider behind it, so tracking what a Claude-backed project actually
spent works the same way it would for GPT or
Gemini. Swapping the model later — moving to a newer Claude release, or to a different
provider entirely — means updating the connection or the project’s
model_connection_id, not touching the application code that calls
/v1/chat/completions.
Full reference: /docs/providers/#anthropic.
Connect Claude to Ragmux
Add an Anthropic model connection
POST /admin/api/models with provider_type: anthropic, an api_key, and a model_name such as claude-sonnet-4-5. base_url doesn't need to be set — it defaults to https://api.anthropic.com, but can be pointed elsewhere if you front Anthropic with your own proxy, provided that proxy isn't on a private or local network without first being allowlisted.
Test it before wiring it into a project
POST /admin/api/models/{id}/test with {"mode": "chat"} sends one bounded completion (max_tokens 256) and returns latency and a sample reply, so a bad key or model name fails here, not in front of a user.
Attach the connection to a project
POST /admin/api/projects with model_connection_id set to the Anthropic connection. The project's sk-proj-… key is shown exactly once — save it.
Call /v1/chat/completions exactly as you would against OpenAI
Point the OpenAI SDK's base_url at your Ragmux instance and its api_key at the project key. The gateway translates the request to Anthropic's Messages API and translates the response back before your code ever sees it.
Frequently asked questions
- Do I need the Anthropic SDK to call Claude through Ragmux?
- No — a project backed by an Anthropic connection is still called through Ragmux's own /v1/chat/completions endpoint, so the standard OpenAI SDK, in any language, works unchanged; Ragmux is what speaks Anthropic's Messages API on the other side.
- What happens if my request doesn't set max_tokens?
- Anthropic's API rejects a request with no max_tokens, so Ragmux fills in 4096 whenever a caller omits it, rather than passing the omission through and getting a provider-side error back.
- Can I use response_format: json_object with a Claude connection?
- Not as a constraint — response_format has no Anthropic equivalent, so the request is still answered but the field is ignored, and the response carries a Warning: 299 header saying so (the event is also logged at info level). A caller relying on OpenAI's JSON mode needs to ask for JSON in the prompt itself when the connection is Anthropic.
- Does Claude support embeddings through Ragmux?
- No — Anthropic has no embeddings API, so an anthropic connection can back a project's chat model but never a RAG store's embedding model; pair it with an openai, gemini, ollama or custom_openai connection for that half.
- How does Ragmux handle a system prompt when calling Claude?
- OpenAI-style system and developer messages are merged, in the order they appeared, into the single top-level system field Anthropic's Messages API expects (sent as text blocks), rather than being sent as a message in the array.