Responses API로 마이그레이션

Responses API로 마이그레이션 (Migrate to the Responses API)

Responses API는 우리의 새 API 프리미티브로, Chat Completions의 진화형이에요. 단순성을 더하고 강력한 에이전틱 프리미티브를 통합에 가져와요.

출처: 문서

본문

Chat Completions는 계속 지원되지만, 모든 새 프로젝트에는 Responses를 권장해요.

Responses API에 대해

Responses API는 강력하고 에이전트 같은 애플리케이션을 구축하는 통합 인터페이스예요. 다음을 포함해요.

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를 다시 보내세요.
  • 컨텍스트를 직접 관리·정리해야 할 때는 이전 output Items를 다음 요청에 다시 전달하세요.
  • 지속 대화 객체가 필요하면 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 사이에 함수를 정의하는 방식에 두 가지 작지만 주목할 만한 차이가 있어요.

  1. Chat Completions에서 함수 정의는 외부 태그(externally tagged)예요. Responses에서는 내부 태그(internally tagged)예요.
  2. 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.created
  • response.output_text.delta
  • response.completed
  • error

함수 호출 스트림은 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, 내장 도구 가이드를 함께 보면 좋아요.