API
verified · type: comparison · verified: 2026-07 · review: 30d · updated: 2026-07-25 · [api, comparison]

OpenAI API Parity — Anthropic 코드를 OpenAI로 옮기기

Anthropic Messages API로 짠 코드를 OpenAI로 포팅할 때, 필드 이름·구조·기본값이 어떻게 어긋나는지 찾아보는 대응표.

Anthropic 쪽 값은 이 위키의 §7 first-party 사실이 최종 권위다. OpenAI 쪽은 developers.openai.com 1차 확인(HIGH)과 미확인 항목을 구분해 표기했다. openai.com 본체는 403으로 미확인.


먼저: 두 API 중 어느 것으로 옮기나 🧭

OpenAI에는 API가 둘 있다. Anthropic의 단일 Messages API와 달리 갈래를 골라야 한다.

Responses API Chat Completions
엔드포인트 POST /v1/responses POST /v1/chat/completions
OpenAI 권장 신규 프로젝트 전부 이쪽 계속 지원(deprecated 아님)
상태 stateful (store, previous_response_id) stateless
서버측 내장툴 web search·file search·code interpreter·MCP 없음
출력 typed output[] / output_text flat choices[0].message.content
  • OpenAI 공식 문구: "While Chat Completions remains supported, Responses is recommended for all new projects."
  • Anthropic Messages는 무상태(매 요청 전체 히스토리 전송)라서, 구조가 더 가까운 건 Chat Completions다. 하지만 신규 코드라면 Responses가 권장 대상이다 — 상태 유지 모델이 다르니 포팅 시 가장 큰 함정(아래 참조).
  • 참고로 Assistants API는 2026-08-26 sunset (verified 2026-07) — 여기로는 옮기지 마라. 기능은 Responses로 흡수됐다.

필드 대응표 (Anthropic → OpenAI)

항목 Anthropic Messages OpenAI Chat Completions OpenAI Responses
시스템 프롬프트 top-level system messages[]system role top-level instructions
입력 messages[] (role+content) messages[] input (+ typed Items)
툴 정의 tools[], strict: true(top-level) tools[] 함수 스키마, strict: true tools[] flat {type,name,description,parameters,strict}
툴 결과 반환 user 턴에 tool_result 블록(tool_use_id) {role:"tool", tool_call_id, content} {type:"function_call_output", call_id, output}
병렬 툴 끄기 disable_parallel_tool_use parallel_tool_calls: false 동일
구조화 출력 output_config.format.json_schema response_format.json_schema text.format.json_schema
추론 강도 output_config.effort (기본 high) reasoning.effort (기본 medium) reasoning.effort (기본 medium)
응답 접근 content[] typed 블록 choices[0].message.content output_text / output[]

세 API 모두 구조화 출력은 json_schema + strict/additionalProperties:false로 같은 개념이지만, 필드가 얹히는 위치가 셋 다 다르다 — 여기서 제일 많이 넘어진다.

툴/함수 호출 옮길 때

  • 스키마 본문(name/description/parameters)은 세 API가 동일. 옮기기 쉬운 부분.
  • strict: true 요구조건도 사실상 같다: "additionalProperties": false + 모든 필드 required + 선택 필드는 type: ["string","null"]. Anthropic의 strict tool use 규칙과 그대로 겹친다.
  • 툴 결과 반환 형식이 셋 다 다르다 (위 표). Anthropic은 user 턴 안의 tool_result 블록, Chat은 role:"tool" 메시지, Responses는 function_call_output 아이템. 여기가 포팅의 핵심 수작업 지점.
  • tool_choice: OpenAI는 auto(기본)/required/특정 함수. Responses는 allowed_tools도 있다.
  • 함수콜 스트리밍 이벤트: Responses는 response.function_call_arguments.delta / .done (verified 2026-07).

구조화 출력 옮길 때

# Anthropic (§7)
client.messages.parse(output_format=MyPydanticModel, ...)   # output_config.format 로 내려감

# OpenAI Responses
client.responses.parse(text_format=MyPydanticModel, ...)    # text.format.json_schema

# OpenAI Chat Completions
client.chat.completions.parse(response_format=MyPydanticModel, ...)  # response_format.json_schema
  • Python은 Pydantic, TS는 Zod(zodTextFormat() / zodResponseFormat())로 스키마 변환·파싱이 자동. Anthropic의 .parse() 습관을 그대로 옮길 수 있다.
  • 두 프로바이더 모두 안전 거부(refusal)를 프로그램적으로 감지 가능한 필드로 노출한다. Anthropic은 stop_reason: "refusal", OpenAI는 별도 refusal 필드.

추론/thinking 노브 옮길 때

Anthropic OpenAI
켜는 법 thinking:{type:"adaptive"} + output_config.effort reasoning.effort
effort 기본 high medium
effort 값 low·medium·high·xhigh·max none·minimal·low·medium·high·xhigh·max (재확인 필요)
추론 요약 thinking.display:"summarized" (기본 omitted) summary: auto|concise
raw CoT 절대 미반환 미노출(요약만)
무상태 연속성 매 요청 전체 히스토리 encrypted_content 재생 (재확인 필요)
  • 기본 effort가 다르다: Anthropic은 high, OpenAI는 medium. 그대로 옮기면 OpenAI 쪽이 덜 생각한다 — 비용/품질 튜닝 시 유의.
  • 두 프로바이더 다 raw chain-of-thought는 안 준다. 요약만.
  • Anthropic effortoutput_config 안, OpenAI effortreasoning 안. 컨테이너가 다르니 단순 치환 안 됨.

캐싱 대응

  • Anthropic은 명시적: cache_control breakpoint를 직접 찍는다. 캐시 쓰기 1.25배(5분)/2배(1시간), 읽기 0.1배. 최소 길이는 모델마다 다름(자세히는 prompt-caching).
  • OpenAI는 자동: 프리픽스 캐싱이 알아서 걸리고, 캐시 입력가는 표준 입력의 10%로 고정(예: gpt-5.6-sol $0.50 vs $5.00, verified 2026-07). breakpoint 개념 없음.
  • 포팅 함정: Anthropic에서 정성껏 배치한 cache_control 블록은 OpenAI로 옮길 때 버려라 — OpenAI에선 프롬프트 앞부분을 안정적으로 유지하는 것만이 레버다.

마이그레이션 함정 ⚠️

  • 상태 모델 역전: Anthropic은 무상태라 코드가 매 턴 전체 히스토리를 보낸다. Responses로 옮기면서 그 습관을 유지하면 store/previous_response_id의 이점이 죽는다. 반대로 서버 상태에 의존하도록 짜면 무상태 재시도·리플레이가 깨진다. 정확한 stateful 필드셋은 (재확인 필요).
  • 구조화 출력 필드 위치 3종: output_config.format(Anthropic) → response_format(Chat) → text.format(Responses). 이름만 바꾸면 안 되고 중첩 위치가 다르다.
  • 툴 결과 3종 포맷: 위 참조. 자동 변환 안 됨.
  • effort 기본값 차이(high→medium)로 옮긴 직후 품질이 떨어져 보일 수 있다.
  • 샘플링 파라미터: Anthropic 최신 모델은 temperature/top_p/top_k가 400 에러라 프롬프팅으로 대체해왔을 것이다. OpenAI로 옮기면 이 노브가 다시 살아나니, 재현성 때문에 명시하고 싶으면 OpenAI 쪽에서 설정.
  • 텍스트 스트리밍 이벤트명: Responses의 텍스트 델타 이벤트명(response.output_text.delta 추정)은 1차 미확인 (재확인 필요). 함수콜 델타 이벤트만 확인됨.
  • 롱컨텍스트 과금 경계: GPT-5.6은 입력 >272K 토큰이면 요청 전체가 입력 2배·출력 1.5배 (verified 2026-07). Anthropic 1M 컨텍스트 감각으로 대용량 프롬프트를 던지면 과금이 튄다.

모델 매핑 (기본값 감각)

Anthropic 기본 OpenAI 대응(가격대 기준)
claude-opus-5 (플래그십) gpt-5.6-sol — 입력 $5 / 출력 $30 (verified 2026-07)
중간 티어 gpt-5.6-terra — $2.50 / $15 (verified 2026-07)
claude-haiku-4-5 (저가) gpt-5.6-luna — $1.00 / $6 (verified 2026-07)

정확한 모델 ID·티어는 openai-gpt-family에. 벤치 점수 비교는 넣지 않았다(빨리 썩고 검증 불가).


참고

출처: OpenAI 쪽은 developers.openai.com 1차 확인(HIGH)과 미확인 구분, Anthropic 쪽은 이 위키 §7 first-party. openai.com 본체는 403 미확인, stateful 필드셋·텍스트 스트리밍 이벤트명은 재확인 필요. 원본 → 2026-07-25-openai-gpt-deep