Responses API로 마이그레이션
Responses API로 마이그레이션 (Migrate to the Responses API)
Responses API는 우리의 새 API 프리미티브로, Chat Completions의 진화형이에요. 단순성을 더하고 강력한 에이전틱 프리미티브를 통합에 가져와요.
출처: 문서
본문
Chat Completions는 계속 지원되지만, 모든 새 프로젝트에는 Responses를 권장해요.
Responses API에 대해
Responses API는 강력하고 에이전트 같은 애플리케이션을 구축하는 통합 인터페이스예요. 다음을 포함해요.
- web search, file search, computer use, code interpreter, remote MCP 같은 내장 도구.
- 이전 응답을 전달해 더 높은 정확도의 추론 결과를 얻을 수 있는 매끄러운 다중 턴 상호작용.
- 텍스트와 이미지에 대한 네이티브 멀티모달 지원.
Responses 이점
Responses API는 Chat Completions에 비해 여러 이점이 있어요.
- 더 나은 성능: GPT-5 같은 reasoning 모델을 Responses와 함께 쓰면 Chat Completions보다 더 나은 모델 지능을 얻을 수 있어요. 내부 evals는 같은 프롬프트·설정으로 SWE-bench에서 3% 개선을 보여줘요.
- 기본적으로 에이전틱: Responses API는 에이전틱 루프로, 모델이 단일 API 요청 범위 안에서
web_search,image_generation,file_search,code_interpreter, 원격 MCP 서버, 그리고 여러분의 사용자 지정 함수를 호출할 수 있어요. - 더 낮은 비용: 개선된 캐시 활용으로 비용이 낮아져요(내부 테스트에서 Chat Completions 대비 40%에서 80% 개선).
- 상태 유지 컨텍스트:
store: true를 사용해 턴 간 상태를 유지하고 reasoning·도구 컨텍스트를 보존할 수 있어요. - 유연한 입력: 문자열 입력이나 메시지 목록을 전달하고, 시스템 수준 지침에는
instructions를 사용해요. - 암호화된 reasoning: 상태 저장 없이 고급 reasoning의 이점을 여전히 얻을 수 있어요.
- 미래 대비: 향후 모델에 대비한 구조예요.
| 기능 | Chat Completions API | Responses API |
|---|---|---|
| 텍스트 생성 | ||
| 오디오 | Coming soon | |
| 비전 | ||
| Structured Outputs | ||
| 함수 호출 | ||
| Web search | ||
| File search | ||
| Computer use | ||
| Code interpreter | ||
| MCP | ||
| 이미지 생성 | ||
| Reasoning summaries |
예시
특정 시나리오에서 Responses API가 Chat Completions API와 어떻게 비교되는지 보세요.
Messages vs Items
두 API 모두 우리 모델에서 출력을 생성하기 쉽게 해요. Chat completions 호출의 입력·결과는 Messages 배열이지만, Responses API는 _Items_를 사용해요. Item은 모델 동작의 가능한 범위를 나타내는 여러 유형의 합집합이에요. message는 Item의 한 유형이고, function_call이나 function_call_output도 그래요. 여러 관심사가 하나의 객체에 붙어 있는 Chat Completions Message와 달리, Items는 서로 구별되며 모델 컨텍스트의 기본 단위를 더 잘 나타내요.
또한 Chat Completions는 n 파라미터로 choices로 여러 병렬 생성을 반환할 수 있어요. Responses에서는 이 파라미터를 제거하고 하나의 생성만 남겼어요.
Chat Completions API:
from openai import OpenAI
client = OpenAI()
completion = client.chat.completions.create(
model="gpt-6-astra",
messages=[
{
"role": "user",
"content": "Write a one-sentence bedtime story about a unicorn.",
}
],
)
print(completion.choices[0].message.content)
Responses API:
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-6-astra",
input="Write a one-sentence bedtime story about a unicorn.",
)
print(response.output_text)
Responses API로부터 응답을 받으면 필드가 약간 다릅니다. message 대신 자체 id를 가진 타입화된 response 객체를 받아요. Responses는 기본적으로 저장돼요. Chat completions는 새 계정에 대해 기본적으로 저장돼요. 어느 API든 저장을 비활성화하려면 store: false로 설정하세요.
이 API들로 받는 객체는 약간 다릅니다. Chat Completions에서는 각각 message를 포함한 choices 배열을 받아요. Responses에서는 output으로 라벨된 Items 배열을 받아요.
추가 차이점
- Responses는 기본적으로 저장돼요. Chat completions는 새 계정에 대해 기본적으로 저장돼요. 어느 API든 저장을 비활성화하려면
store: false를 설정하세요. - Reasoning 모델은 Responses API에서 개선된 도구 사용으로 더 풍부한 경험을 가져요. GPT-5.4부터 Chat Completions는
none외의reasoning_effort값으로 도구 호출을 지원하지 않아요. - Structured Outputs API 모양이 달라요.
response_format대신 Responses에서text.format을 사용하세요. 자세한 내용은 Structured Outputs 가이드에서 배우세요. - 함수 호출 API 모양이 달라요. 요청의 함수 구성과 응답으로 돌려보내는 함수 호출 모두 그렇죠. 전체 차이는 함수 호출 가이드를 참고하세요.
- Responses SDK에는 Chat Completions SDK에는 없는
output_text헬퍼가 있어요. - Chat Completions에서는 대화 상태를 수동으로 관리해야 해요. Responses API는 지속 대화를 위한 Conversations API와 호환되거나,
previous_response_id를 전달해 Responses를 쉽게 체인할 수 있어요.
Chat Completions에서 마이그레이션
마이그레이션을 세 가지 관련 변경으로 취급하세요. 요청을 /v1/responses로 보내고, 타입화된 output 배열에서 출력을 읽고, 애플리케이션이 턴 사이 상태를 어떻게 가져갈지 선택하세요.
1. 생성 엔드포인트 업데이트
생성 엔드포인트를 post /v1/chat/completions에서 post /v1/responses로 업데이트하세요.
함수나 멀티모달 입력을 사용하지 않는다면 단순 메시지 입력은 한 API에서 다른 API로 호환돼요.
context = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"},
]
completion = client.chat.completions.create(model="gpt-6-astra", messages=context)
response = client.responses.create(model="gpt-6-astra", input=context)
(JavaScript, Go, Java, C#, Ruby, curl 예시도 같은 input 재사용 패턴입니다.)
Chat Completions에서 messages 배열을 만들고 completion.choices[0].message.content에서 모델 텍스트를 읽어요. Responses에서는 최상위에서 instructions와 input을 분리하고 response.output_text에서 생성된 텍스트를 읽어요.
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-6-astra", instructions="You are a helpful assistant.", input="Hello!"
)
print(response.output_text)
(JavaScript, Go, Java, C#, Ruby, curl 예시도 instructions와 input을 분리하는 같은 패턴입니다.)
2. Messages를 Items로 매핑
Chat Completions는 messages를 입력·출력 모두로 사용해요. Responses는 타입화된 Items의 input과 output 배열을 사용해요. message는 reasoning, function_call, function_call_output 같은 Items와 함께 하나의 Item 유형이에요.
| Chat Completions 개념 | Responses 매핑 |
|---|---|
messages[] |
input (문자열 또는 입력 Items 배열) |
| System 또는 developer 지침 | 최상위 instructions, 또는 기존 대화록을 보존해야 할 때 호환 가능한 message Items |
| User message | role: "user"의 입력 message Item |
| Assistant message | response.output의 출력 message Item. 상태를 수동으로 관리한다면 input에 다시 전달 |
| Tool 또는 function call | function_call 출력 Item |
| Tool 또는 function result | call_id로 호출에 연결된 function_call_output 입력 Item |
n으로 여러 생성 |
Responses에서는 사용 불가. 여러 후보 출력이 필요하면 별도 요청 |
최종 텍스트만 필요할 때는 SDK output_text 헬퍼를 쓰세요. 흐름이 reasoning, 도구, 멀티모달 출력을 사용한다면 response.output을 반복하고 각 Item을 type으로 처리하세요.
3. 다중 턴 대화 업데이트
애플리케이션에 다중 턴 대화가 있다면 컨텍스트 로직을 업데이트하세요. Responses는 세 가지 일반적인 상태 관리 옵션을 줘요.
- OpenAI가 이전 응답 컨텍스트를 관리하게 하려면
previous_response_id를 사용하세요.previous_response_id는 이전 응답의 최상위instructions를 가져오지 않으므로 각 요청에 안정적인instructions를 다시 보내세요. - 컨텍스트를 직접 관리·정리해야 할 때는 이전
outputItems를 다음 요청에 다시 전달하세요. - 지속 대화 객체가 필요하면 Conversations API를 사용하세요.
Chat Completions에서는 대화록을 저장하고 각 요청에 누적된 messages 배열을 보내요. Responses에서는 한 응답의 출력을 다른 응답의 입력에 수동으로 전달하거나 previous_response_id를 사용할 수 있어요.
수동 컨텍스트 (Responses):
context = [{"role": "user", "content": "What is the capital of France?"}]
res1 = client.responses.create(
model="gpt-6-astra",
input=context,
)
# Append the first response's output to context
context += res1.output
# Add the next user message
context += [{"role": "user", "content": "And its population?"}]
res2 = client.responses.create(
model="gpt-6-astra",
input=context,
)
previous_response_id 사용 (Responses):
res1 = client.responses.create(
model="gpt-6-astra", input="What is the capital of France?", store=True
)
res2 = client.responses.create(
model="gpt-6-astra",
input="And its population?",
previous_response_id=res1.id,
store=True,
)
previous_response_id를 사용할 때도 체인의 응답에 대한 이전 입력 토큰은 모두 API에서 입력 토큰으로 청구돼요.
4. 상태 유지 사용 시점 결정
Responses는 기본적으로 저장돼요. Chat Completions는 새 계정에 대해 기본적으로 저장돼요. 어느 API든 저장을 비활성화하려면 store: false를 설정하세요.
Zero Data Retention (ZDR) 요구사항이 있는 조직처럼 일부 조직은 규정 준수·데이터 보유 정책 때문에 Responses API를 상태 유지 방식으로 쓸 수 없어요. 이런 경우를 지원하기 위해 OpenAI는 암호화된 reasoning Items를 제공해, 상태 저장 없이 워크플로를 유지하면서 reasoning Items의 이점을 그대로 얻을 수 있게 해요.
상태 저장을 비활성화하면서 reasoning을 활용하려면:
- store 필드에서
store: false를 설정하세요. - 반환된 모든 reasoning Item을 보존하고 재생하세요. 응답을 만들 때 각 항목은 기본적으로
encrypted_content를 포함해요.
그러면 API가 reasoning 토큰의 암호화 버전을 반환하고, 일반 reasoning Items처럼 향후 요청에 다시 전달할 수 있어요. ZDR 조직의 경우 OpenAI가 store: false를 자동으로 강제해요. 요청에 encrypted_content가 포함되면 메모리에서 복호화되고, 다음 응답 생성에 사용된 뒤 안전하게 폐기돼요. 새 reasoning 토큰은 즉시 암호화되어 반환되므로 중간 상태가 지속되지 않아요.
5. 함수 정의·출력 업데이트
Chat Completions와 Responses 사이에 함수를 정의하는 방식에 두 가지 작지만 주목할 만한 차이가 있어요.
- Chat Completions에서 함수 정의는 외부 태그(externally tagged)예요. Responses에서는 내부 태그(internally tagged)예요.
- Chat Completions에서 함수는 기본적으로 non-strict예요. Responses에서는
strict를 생략하면 strict 모드를 시도하고, 스키마를 호환되게 만들 수 없으면 Responses가 non-strict best-effort 함수 호출로 폴백하고 해결된 도구를strict: false로 반환해요. Responses에서 non-strict 동작을 명시적으로 유지하려면strict: false를 설정하세요.
오른쪽의 Responses API 함수 예시는 왼쪽 Chat Completions 예시와 기능적으로 동등해요.
Chat Completions API:
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Determine weather in my location",
"strict": true,
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"location"
]
}
}
}
Responses API:
{
"type": "function",
"name": "get_weather",
"description": "Determine weather in my location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"location"
]
}
}
함수 호출 모범 사례 따르기
Responses에서 도구 호출과 그 출력은 call_id로 상관되는 두 가지 별개의 Item 유형이에요. Responses에서 함수 호출이 어떻게 작동하는지 자세한 내용은 함수 호출 문서를 참고하세요.
6. Structured Outputs 정의 업데이트
Responses API에서 Structured Outputs 정의가 response_format에서 text.format으로 옮겨졌어요.
Chat Completions (Structured Outputs):
response = client.chat.completions.create(
model="gpt-6-astra",
messages=[
{
"role": "user",
"content": "Jane, 54 years old",
}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": True,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string", "minLength": 1},
"age": {"type": "number", "minimum": 0, "maximum": 130},
},
"required": ["name", "age"],
"additionalProperties": False,
},
},
},
reasoning_effort="medium",
)
Responses (Structured Outputs):
response = client.responses.create(
model="gpt-6-astra",
input="Jane, 54 years old",
text={
"format": {
"type": "json_schema",
"name": "person",
"strict": True,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string", "minLength": 1},
"age": {"type": "number", "minimum": 0, "maximum": 130},
},
"required": ["name", "age"],
"additionalProperties": False,
},
}
},
)
(JavaScript, Go, Java, C#, Ruby, curl 예시도 text.format에서 동일한 json_schema 구성을 쓰는 같은 패턴입니다.)
7. 스트리밍 소비자 업데이트
Chat Completions 스트리밍은 delta 필드가 있는 증분 청크를 반환해요. Responses 스트리밍은 타입화된 server-sent events를 사용해요. 스트림 소비자를 각 이벤트의 type으로 분기하고 UI·오케스트레이션 계층이 필요로 하는 이벤트를 처리하도록 업데이트하세요.
텍스트 스트리밍에서는 다음 같은 이벤트를 들어보세요.
response.createdresponse.output_text.deltaresponse.completederror
함수 호출 스트림은 response.function_call_arguments.delta와 response.function_call_arguments.done 같은 이벤트도 방출할 수 있어요. 스트리밍 Responses 가이드와 Responses 스트리밍 이벤트 레퍼런스를 참고하세요.
8. 네이티브 도구로 업그레이드
애플리케이션에 OpenAI 네이티브 tools의 이점을 누릴 사용 사례가 있다면 도구 호출을 OpenAI 도구를 기본으로 사용하도록 업데이트할 수 있어요.
Chat Completions에서는 OpenAI 호스팅 도구를 네이티브로 쓸 수 없고 자체 도구 통합을 작성해야 해요. 이 예시는 GPT-5.6을 사용해요. GPT-6 Astra는 도구 호출에 Responses API가 필요하기 때문이에요. Web search 도구:
import requests
def web_search(query):
r = requests.get(f"https://api.example.com/search?q={query}")
return r.json().get("results", [])
completion = client.chat.completions.create(
model="gpt-5.6",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Who is the current president of France?"},
],
functions=[
{
"name": "web_search",
"description": "Search the web for information",
"parameters": {
"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"],
},
}
],
)
Responses에서는 web search 같은 네이티브 도구를 기본으로 사용할 수 있어요. Web search 도구:
response = client.responses.create(
model="gpt-6-astra",
input="Who is the current president of France?",
tools=[{"type": "web_search"}],
)
print(response.output_text)
(이 가이드 뒤쪽에는 출력 텍스트 읽기, 마이그레이션 체크리스트 등의 추가 섹션이 이어집니다.)
더 알아보기 (Learn more)
관련 문서: 함수 호출, Structured Outputs, 스트리밍 Responses, 내장 도구 가이드를 함께 보면 좋아요.