Skip to content
This page is a translation of the authoritative Chinese source and may lag behind.View the original

Call Anthropic Claude with the OpenAI SDK

This chapter teaches you how to call Anthropic's Claude models with an OpenAI SDK — the client protocol (OpenAI Chat Completions) and the upstream protocol (Anthropic Messages) differ, so the gateway translates in both directions. This is a typical example of the gateway's cross-protocol capability.

What you'll accomplish

  • An anthropic upstream (pointing to the Anthropic API)
  • A claude-sonnet model (upstream protocol anthropic)
  • Call claude-sonnet with the OpenAI Python SDK and see the model's reply

Prerequisites

  • The gateway is running (http://localhost:7890) and you can log in to the Console
  • ENCRYPTION_KEY is set — the upstream API key and access key you're about to save are encrypted before storage; if unset, saving reports encryption_key not set in config. See Docker single node → Prerequisites
  • An Anthropic API key

1. Create an anthropic upstream

Console → UpstreamsNew:

FieldValueDescription
NameanthropicUnique upstream identifier
ProtocolanthropicDetermines the executor and request schema
Base URLhttps://api.anthropic.comThe upstream's real address, no trailing /
API KeyAnthropic's keyClick "Add" to add more, distributed by weight
Enabled

Save.

2. Create a claude model

In the anthropic upstream row, click Expand → model sub-table → New model:

FieldValueDescription
Nameclaude-sonnetThe model name exposed to clients
UpstreamanthropicSelect the upstream you just created
Upstream model IDclaude-sonnet-4-5Anthropic's real model name
Enabled

Save. When clients call using claude-sonnet, the gateway routes to claude-sonnet-4-5 on the anthropic upstream.

"Upstream model ID" must be a real model name that exists on Anthropic (in this example claude-sonnet-4-5); a wrong or discontinued model name yields a 404. For the full list of available models, see Anthropic's official model list.

3. Configure a key group to allow it

Console → Access KeysKey Groups tab → New:

FieldValueDescription
NamedefaultGroup name
ModelsSelect claude-sonnet, or * (all)Determines which models this group's keys can call
Enabled

4. Issue an access key

Console → Access KeysNew:

FieldValueDescription
Namemy-app-keyThe key's identifier, used for management and auditing
API Keyclick "Generate"Auto-generates a string; the credential the client carries when calling
GroupdefaultDetermines which models this key can access
Enabled

5. Call with the OpenAI SDK

python
from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:7890/v1",
    api_key="<your access key>",
)

resp = client.chat.completions.create(
    model="claude-sonnet",
    messages=[{"role": "user", "content": "hello"}],
)
print(resp.choices[0].message.content)

The request body is in OpenAI Chat Completions format. The gateway:

  1. Receives the OpenAI-format request
  2. Translates it to Anthropic Messages format and sends it to https://api.anthropic.com/v1/messages
  3. Translates the Anthropic response back to OpenAI format and returns it

The client is unaware and sees a standard OpenAI response.

6. Or use curl

bash
curl http://localhost:7890/v1/chat/completions \
  -H "Authorization: Bearer <your access key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet",
    "messages": [{"role":"user","content":"hello"}]
  }'

Receiving Claude's reply means it works.

Cross-protocol translation details

Tool calls

For cross-protocol tool calls (OpenAI tools → Anthropic tools), the gateway automatically translates the tools / tool_choice / tool_calls fields. Key constraints:

  • tool_call_id must keep its original value across the cross-protocol round trip — the tool_call_id you pass back in a multi-turn tool conversation must be exactly what the gateway gave you, otherwise the upstream cannot match it.
  • The tool_use id in responses is synthesized by the gateway — the gateway assigns each tool_use block a globally unique toolu_ id (it does not pass through the original id the upstream assigned). You just echo it back verbatim as the next turn's tool_use_id / tool_call_id; no need to care about the upstream's original id.
  • tool_use ids in the request history must be globally unique — the gateway validates /v1/messages requests the same way the Anthropic official API does; a history containing duplicate tool_use ids returns 400 invalid_request_error (with a message like tool_use ids must be unique). Echoing back the gateway's synthesized ids normally won't trigger this.

Streaming

Streaming requests are also translated: the gateway converts Anthropic's SSE event stream into OpenAI's data: {...} block stream. If the upstream inference takes a long time, the gateway inserts :keep-alive SSE comments to keep the connection alive. Standard SSE client implementations ignore these automatically; no special handling is needed.

Mid-stream interruption

When an upstream stream is interrupted mid-transfer, the gateway doesn't just error out and break the conversation. Instead, it:

  • Closes the content blocks that haven't finished
  • Inserts a _gateway_warning extension field into the SSE stream, telling you the reason for the interruption (including reason / detail / last_finish_reason / timestamp)
  • Sends the normal termination sequence so the client can finish cleanly

If you see _gateway_warning while parsing the stream, it means this response had a problem mid-way; you can log or alert on it.

Reverse: call OpenAI with the Anthropic SDK

You can also do the reverse: the upstream is OpenAI (openai protocol), and the client uses the Anthropic SDK to call /v1/messages. The gateway translates the Anthropic request to an OpenAI request and sends it to the upstream, then translates the response back to Anthropic. For the specific connection method, see Client integration and gateway differences.

FAQ

Q: Cross-protocol calls lose tool calls / upstream reports 400 invalid tool_call_id? Check whether the tool_call_id you pass back in a multi-turn tool conversation is exactly what the gateway gave you. In cross-protocol translation, tool_call_id must keep its original value.

Q: Calling /v1/messages reports 400 tool_use ids must be unique? The conversation history you sent has two tool_use blocks using the same id — the Anthropic contract requires tool_use ids to be globally unique, and the gateway rejects it just like the official API. Check whether your history-construction logic reuses ids across turns; echoing back the gateway's synthesized toolu_ ids normally won't collide.

Q: A _gateway_warning field is mixed into the response? It's not from the upstream; the gateway added it. It means the upstream stream was interrupted mid-way. Look at its reason/detail to decide whether to retry.

Q: Client reports 400 unsupported_feature? There's no translator for that "client protocol → upstream protocol" pair. Check the Protocol interop matrix for the support matrix.

Q: Client reports 401 / 403 / 404?

  • 401: the access key isn't right
  • 403 model_access_denied: the key group's "models" list doesn't include claude-sonnet
  • 404 model_not_found: the model name is misspelled, or claude-sonnet has hide_name set

Next: Endpoints · auth · protocol interop for the full endpoint list; Protocol interop matrix for support across all protocol pairs; Client integration and gateway differences for each SDK's connection method.