Migrating from Anthropic to OpenAI: A Practical Guide

Moving from Anthropic’s Messages API to OpenAI’s Chat Completions is a mechanical remap: the system prompt becomes a message, max_tokens stops being required, the response shape changes, and tool results go back as a role: "tool" message instead of a content block.

API concept mapping

Anthropic Messages → OpenAI Chat Completions (as of June 2026).
ConceptAnthropicOpenAI
SDK anthropicopenai
Auth x-api-key + anthropic-versionAuthorization: Bearer
Endpoint /v1/messages/v1/chat/completions
System prompt top-level system parammessages[] with role: system
Max output max_tokens (required)max_tokens (optional)
Assistant text content[0].textchoices[0].message.content
Stop reason stop_reason (end_turn / max_tokens / tool_use)finish_reason (stop / length / tool_calls)
Tool result user msg with tool_result blockrole: tool message

Before / after

Before — Anthropic
import anthropic
client = anthropic.Anthropic()

resp = client.messages.create(
  model="claude-sonnet-4-6",
  max_tokens=1024,
  system="You are concise.",
  messages=[{"role": "user", "content": "Explain rate limits in one line."}],
)
print(resp.content[0].text)
After — OpenAI
from openai import OpenAI
client = OpenAI()

resp = client.chat.completions.create(
  model="gpt-5.4",
  messages=[
      {"role": "system", "content": "You are concise."},   # was top-level
      {"role": "user", "content": "Explain rate limits in one line."},
  ],
)
print(resp.choices[0].message.content)
Watch for these
  • System prompt moves into messages as a role: "system" entry.
  • max_tokens is now optional — keep a sensible cap, but it won’t error if omitted.
  • Response path changes to choices[0].message.content.
  • Tool calling differs: Claude’s tool_use block → OpenAI tool_calls; return results as a role: "tool" message (with tool_call_id), not a tool_result content block. Port input_schemaparameters.
  • Re-tune prompts — GPT models format and refuse differently than Claude.

What to do next

  1. Move the system prompt into the messages array; relax max_tokens.
  2. Update response parsing to choices[0].message.content and remap stop reasons.
  3. Port tool schemas (input_schemaparameters) and the result round-trip.
  4. Re-price with the cost calculator; reverse route is OpenAI → Anthropic.

Frequently asked questions

What breaks most often going Anthropic → OpenAI?
Forgetting to move the top-level system prompt into a role: system message, and reading the wrong response path — it's choices[0].message.content, not content[0].text.
How do tools translate?
Claude's tool_use content blocks become OpenAI tool_calls; tool schemas move from input_schema to parameters; and you return results as a role: tool message keyed by tool_call_id instead of a tool_result block.
Is max_tokens still required?
No — it's optional on OpenAI (required on Anthropic). Keep a realistic cap to bound cost, but omitting it won't error.