Models

Models (모델)

Agents SDK는 OpenAI 모델을 두 가지 형태로 기본 지원해요. 어떤 형태를 고를지, 어떻게 커스텀 설정을 적용하는지, 그리고 OpenAI가 아닌 다른 제공자(provider)와 섞을 때 주의할 점까지 정리해 드릴게요.

출처: 문서

본문

Agents SDK는 OpenAI 모델을 두 가지 형태로 기본 지원해요:

모델 설정 고르기

자신의 환경에 맞는 가장 간단한 경로부터 시작하세요:

시도하려는 것 권장 경로 자세히 보기
OpenAI 모델만 사용 기본 OpenAI 제공자 + Responses 모델 경로 사용 OpenAI 모델
websocket 전송으로 OpenAI Responses API 사용 Responses 모델 경로 유지 + websocket 전송 활성화 Responses WebSocket 전송
OpenAI 호스팅 하위 에이전트 사용 실험적 호스팅 멀티-에이전트 모델 사용 호스팅 멀티-에이전트
비-OpenAI 제공자 하나 사용 내장 제공자 통합 지점부터 시작 비-OpenAI 모델
에이전트 간 모델·제공자 혼합 실행별·에이전트별 제공자 선택 + 기능 차이 검토 한 워크플로우에서 모델 섞기제공자 간 모델 섞기
고급 OpenAI Responses 요청 설정 조정 OpenAI Responses 경로에서 ModelSettings 사용 고급 OpenAI Responses 설정
비-OpenAI 또는 혼합 제공자 라우팅에 타사 어댑터 사용 지원되는 beta 어댑터 비교 + 배포할 제공자 경로 검증 타사 어댑터

OpenAI 모델

대부분의 OpenAI 전용 앱에서는 기본 OpenAI 제공자와 함께 문자열 모델 이름을 쓰고 Responses 모델 경로를 유지하는 게 권장 경로예요.

Agent가 모델을 지정하지 않으면, Agents SDK는 기본적으로 gpt-5.6-lunareasoning.effort="none"verbosity="low"로 사용해요. 이는 비용에 민감하고 대량의 에이전트 워크플로우를 위한 기본값이에요. 프론티어 성능이 필요한 앱은 model="gpt-5.6-sol"을 명시적으로 설정하고 워크로드에 맞는 model_settings를 고르면 돼요.

gpt-5.6-sol 같은 다른 모델로 바꾸고 싶다면 두 가지 방법이 있어요.

기본 모델

첫째, 커스텀 모델을 설정하지 않은 모든 에이전트에 특정 모델을 일관되게 쓰고 싶다면, 에이전트를 실행하기 전에 OPENAI_DEFAULT_MODEL 환경 변수를 설정하세요.

export OPENAI_DEFAULT_MODEL=gpt-5.6-sol
python3 my_awesome_agent.py

둘째, RunConfig로 실행의 기본 모델을 설정할 수 있어요. 에이전트에 모델을 설정하지 않았다면 이 실행의 모델이 사용돼요.

from agents import Agent, RunConfig, Runner

agent = Agent(
    name="Assistant",
    instructions="You're a helpful agent.",
)

result = await Runner.run(
    agent,
    "Hello",
    run_config=RunConfig(model="gpt-5.6-sol"),
)
GPT-5 모델

이런 방식으로 gpt-5.6-sol 같은 GPT-5 모델을 사용하면 SDK가 기본 ModelSettings를 적용해요. 대부분의 사용 사례에서 가장 잘 동작하는 값들을 설정해 주는 거예요. 기본 모델의 reasoning effort를 조절하려면 자신의 ModelSettings를 전달하면 돼요:

from openai.types.shared import Reasoning
from agents import Agent, ModelSettings

my_agent = Agent(
    name="My Agent",
    instructions="You're a helpful agent.",
    # OPENAI_DEFAULT_MODEL=gpt-5.6-sol 이 설정되어 있다면 model_settings만 전달해도 돼요.
    # GPT-5 모델 이름을 명시적으로 전달해도 괜찮아요:
    model="gpt-5.6-sol",
    model_settings=ModelSettings(reasoning=Reasoning(effort="high"), verbosity="low")
)

더 낮은 지연을 원한다면 GPT-5 모델에 reasoning.effort="none"을 쓰는 것을 권장해요.

GPT-5.6은 reasoning 모드, 대화 턴에 걸친 reasoning 컨텍스트 전달, 그리고 기존 reasoning 설정을 통한 "max" effort 수준도 지원해요. 이런 제어는 Responses API 경로에서 사용할 수 있어요:

from openai.types.shared import Reasoning
from agents import Agent, ModelSettings

agent = Agent(
    name="Deep research agent",
    model="gpt-5.6-sol",
    model_settings=ModelSettings(
        reasoning=Reasoning(
            mode="pro",
            effort="max",
            context="all_turns",
        ),
    ),
)

reasoning.modereasoning.context는 Responses 전용 설정이에요. Chat Completions는 reasoning.effort만 사용하고, 지원되는 effort 수준은 모델과 API 표면에 따라 달라요. GPT-5.6 "max" effort에는 Responses API를 사용하세요. Chat Completions 어댑터는 mode와 context를 경고와 함께 무시해요. strict_feature_validation=True를 OpenAI 제공자에 설정하면 그 경고를 오류로 바꿀 수 있어요.

context="all_turns"를 사용할 때는 previous_response_id, 서버 측 Responses API 대화를 통해서, 또는 다음 요청에 이전 reasoning 항목을 포함해서 대화를 보존하세요. 무상태(stateless) store=False 호출에서는 응답에 reasoning.encrypted_content를 요청한 뒤, 그 reasoning 항목들을 다음 요청의 입력으로 포함하면 돼요.

ComputerTool 모델 선택

에이전트에 ComputerTool이 포함되면, 실제 Responses 요청의 유효 모델이 SDK가 보내는 컴퓨터-도구 페이로드를 결정해요. 에이전트가 model을 설정하지 않으면 일반적인 SDK 모델 선택 우선순위가 적용돼요. 현재 gpt-5.6-luna인 내장 SDK 기본값은 GA 내장 computer 도구를 지원해요. OPENAI_DEFAULT_MODEL이나 RunConfig.model이 그 기본값을 덮어쓰면, 컴퓨터 사용을 지원하는 모델을 선택하세요. 컴퓨터 사용 워크로드에 다른 기능·비용 프로필을 고르고 싶다면 에이전트에 model을 설정하세요. 예를 들어 model="gpt-5.6"은 OpenAI가 GPT-5.6 Sol로 라우팅하는 별칭을 사용해요. 명시적인 computer-use-preview 요청은 이전 computer_use_preview 페이로드를 유지해요.

프롬프트 관리 호출이 주요 예외예요. 프롬프트 템플릿이 모델을 지정하는데 SDK가 요청에서 model을 생략하면, SDK는 프롬프트가 어떤 모델을 고정하는지 추측하지 않기 위해 preview 호환 컴퓨터 페이로드를 기본값으로 사용해요. 그 흐름에서 GA 경로를 유지하려면 model="gpt-5.6" 같은 지원되는 GA 모델을 요청에 명시하거나, ModelSettings(tool_choice="computer") 또는 ModelSettings(tool_choice="computer_use")로 GA 선택기를 강제하면 돼요.

등록된 ComputerTool과 함께라면 tool_choice="computer", "computer_use", "computer_use_preview"는 유효 요청 모델과 일치하는 내장 선택기로 정규화돼요. ComputerTool이 등록되지 않았다면 이 문자열들은 보통 함수 이름처럼 동작해요.

Preview 호환 요청은 environment와 디스플레이 크기를 미리 직렬화해야 하므로, ComputerProvider 팩토리를 사용하는 프롬프트 관리 흐름은 요청을 보내기 전에 구체적인 Computer 또는 AsyncComputer 인스턴스를 전달하거나 GA 선택기를 강제해야 해요. 전체 마이그레이션 세부 사항은 Tools를 참고하세요.

비-GPT-5 모델

커스텀 model_settings 없이 비-GPT-5 모델 이름을 전달하면 SDK는 어떤 모델과도 호환되는 일반 ModelSettings로 되돌아가요.

Responses 전용 도구 기능

다음 도구 기능은 OpenAI Responses 모델에서만 지원돼요:

이 기능들은 Chat Completions 모델과 비-Responses 백엔드에서 거부돼요. 지연-로딩 도구를 사용할 때는 에이전트에 ToolSearchTool()을 추가하고, 네임스페이스 이름이나 지연 전용 함수 이름을 강제하는 대신 auto 또는 required 도구 선택으로 모델이 도구를 로드하게 하세요. 설정 세부 사항과 현재 제약은 호스팅 도구 검색Programmatic Tool Calling을 참고하세요.

Responses WebSocket 전송

기본적으로 OpenAI Responses API 요청은 HTTP 전송을 사용해요. OpenAI Responses 제공자 경로를 사용할 때 websocket 전송에 선택적으로 참여할 수 있어요.

기본 설정
from agents import set_default_openai_responses_transport

set_default_openai_responses_transport("websocket")

이것은 기본 OpenAI 제공자가 모델 이름을 해석할 때 생기는 OpenAI Responses 모델("gpt-5.6-sol" 같은 문자열 모델 이름 포함)에 영향을 줘요.

전송 선택은 SDK가 모델 이름을 모델 인스턴스로 해석할 때 일어나요. 구체적인 Model 객체를 전달하면 그 전송은 이미 고정돼 있어요. OpenAIResponsesWSModel은 websocket, OpenAIResponsesModel은 HTTP를 사용하고, OpenAIChatCompletionsModel은 Chat Completions에 머물러요. RunConfig(model_provider=...)를 전달하면 그 제공자가 전역 기본값 대신 전송 선택을 제어해요.

제공자·실행 수준 설정

websocket 전송을 제공자별 또는 실행별로 구성할 수도 있어요:

from agents import Agent, OpenAIProvider, RunConfig, Runner

provider = OpenAIProvider(
    use_responses_websocket=True,
    # 선택사항; 생략하면 설정된 경우 OPENAI_WEBSOCKET_BASE_URL이 사용됩니다.
    websocket_base_url="wss://your-proxy.example/v1",
    # 선택사항인 저수준 websocket keepalive 설정.
    responses_websocket_options={"ping_interval": 20.0, "ping_timeout": 60.0},
)

agent = Agent(name="Assistant")
result = await Runner.run(
    agent,
    "Hello",
    run_config=RunConfig(model_provider=provider),
)

SDK의 OpenAI 통합을 통해 라우팅되는 제공자는 선택적 에이전트 등록 구성도 받아요. 이는 OpenAI 설정이 harness ID 같은 제공자 수준 등록 메타데이터를 기대하는 경우를 위한 고급 옵션이에요.

from agents import (
    Agent,
    OpenAIAgentRegistrationConfig,
    OpenAIProvider,
    RunConfig,
    Runner,
)

provider = OpenAIProvider(
    use_responses_websocket=True,
    agent_registration=OpenAIAgentRegistrationConfig(harness_id="your-harness-id"),
)

agent = Agent(name="Assistant")
result = await Runner.run(
    agent,
    "Hello",
    run_config=RunConfig(model_provider=provider),
)
MultiProvider로 고급 라우팅

접두사 기반 모델 라우팅이 필요하다면(예: 한 실행에서 openai/...any-llm/... 모델 이름을 섞는다면), MultiProvider를 사용하고 거기서 openai_use_responses_websocket=True를 설정하세요.

MultiProvider는 두 가지 과거 기본값을 유지해요:

  • openai/...는 OpenAI 제공자의 별칭으로 취급되므로, openai/gpt-4.1은 모델 gpt-4.1로 라우팅돼요.
  • 알 수 없는 접두사는 통과(pass-through) 대신 UserError를 발생시켜요.

OpenAI 제공자를 리터럴 네임스페이스 모델 ID를 기대하는 OpenAI 호환 엔드포인트에 연결할 때는 통과(pass-through) 동작을 명시적으로 선택하세요. websocket 활성화 설정에서는 MultiProvider에도 openai_use_responses_websocket=True를 유지하세요:

from agents import Agent, MultiProvider, RunConfig, Runner

provider = MultiProvider(
    openai_base_url="https://openrouter.ai/api/v1",
    openai_api_key="...",
    openai_use_responses_websocket=True,
    openai_prefix_mode="model_id",
    unknown_prefix_mode="model_id",
)

agent = Agent(
    name="Assistant",
    instructions="Be concise.",
    model="openai/gpt-4.1",
)

result = await Runner.run(
    agent,
    "Hello",
    run_config=RunConfig(model_provider=provider),
)

백엔드가 리터럴 openai/... 문자열을 기대할 때는 openai_prefix_mode="model_id"를 사용하세요. 백엔드가 openrouter/openai/gpt-4.1-mini 같은 다른 네임스페이스 모델 ID를 기대할 때는 unknown_prefix_mode="model_id"를 사용하세요. 이 옵션들은 websocket 전송 밖에서도 MultiProvider에서 동작해요. 이 예시는 이 절에서 설명하는 전송 설정의 일부이므로 websocket을 활성화한 채로 두었어요. 같은 옵션은 responses_websocket_session()에서도 사용할 수 있어요.

MultiProvider를 통해 라우팅하면서 같은 제공자 수준 등록 메타데이터가 필요하다면 openai_agent_registration=OpenAIAgentRegistrationConfig(...)를 전달하면 되고, 그것은 내부 OpenAI 제공자에 전달돼요.

커스텀 OpenAI 호환 엔드포인트나 프록시를 사용한다면 websocket 전송도 호환되는 websocket /responses 엔드포인트를 필요로 해요. 그런 설정에서는 websocket_base_url을 명시적으로 설정해야 할 수 있어요.

참고 사항
  • 이것은 Realtime API가 아니라 websocket 전송 위의 Responses API예요. Chat Completions에는 적용되지 않아요. 비-OpenAI 제공자에는 Responses websocket /responses 엔드포인트를 지원할 때만 적용돼요.
  • 환경에 아직 없다면 websockets 패키지를 설치하세요.
  • websocket 전송을 활성화한 뒤 바로 Runner.run_streamed()를 사용할 수 있어요. 턴(및 중첩 agent-as-tool 호출)에 걸쳐 같은 websocket 연결을 재사용하려는 멀티턴 워크플로우에서는 responses_websocket_session() 헬퍼를 권장해요. Running agents 가이드와 examples/basic/stream_ws.py를 참고하세요.
  • 긴 reasoning 턴이나 지연 스파이크가 있는 네트워크에서는 responses_websocket_options로 websocket keepalive 동작을 커스터마이즈하세요. 지연된 pong 프레임을 허용하려면 ping_timeout을 늘리거나, 하트비트 타임아웃을 없애려면 ping_timeout=None으로 설정하면서 ping은 켜둘 수 있어요. websocket 지연보다 안정성이 더 중요하다면 HTTP/SSE 전송을 선호하세요.
  • 기본적으로 SDK는 들어오는 메시지 크기 제한을 비활성화해요 (max_size=None). 프록시 뒤 또는 메모리 제한 컨테이너의 장수명 에이전트 프로세스에서는 responses_websocket_options={"max_size": 8 * 1024 * 1024}를 설정해서 메시지당 메모리 사용을 제한하세요.
  • Responses API WebSocket 서비스는 각 연결에서 한 번에 하나의 응답을 처리하고, 각 연결을 60분으로 제한해요. 그 한도를 넘으면 새 연결을 열고, 병렬 실행이 필요하면 여러 연결을 사용하세요.
  • 서비스는 연결 로컬 메모리에 가장 최근 응답만 유지해요. 실패한 4xx 또는 5xx 턴은 previous_response_id가 참조하는 응답을 그 메모리에서 추방해요. 재연결 후 저장된 응답은 가능하면 계속 이어갈 수 있지만, store=False와 ZDR 흐름은 지속된 폴백이 없어요. previous_response_id=None으로 새 체인을 시작하고 전체 입력 컨텍스트를 보내거나, 로컬 관리 세션 상태에서 그 컨텍스트를 재구성하세요.

호스팅 멀티-에이전트 (실험적)

OpenAI Responses API 호스팅 멀티-에이전트 beta는 GPT-5.6 루트 모델이 서버 호스팅 하위 에이전트를 만들고 조정하게 해줘요. Agents SDK는 평소처럼 Runner를 계속 사용할 수 있어요. 호스팅 조정은 서비스에 남고, 개발자가 정의한 함수 도구는 애플리케이션에서 실행돼요.

이 통합은 실험적이며, 로컬 함수 출력을 response.inject로 활성 호스팅 에이전트에 반환할 수 있도록 Responses WebSocket 전송을 사용해요. client.beta.responses.connect를 노출하는 openai[realtime] 버전 2.45.0 이상의 빌드가 필요해요. 인터페이스와 beta 항목 스키마는 일반 공급(general availability) 전에 바뀔 수 있어요.

모델 구성

실험용 모듈에서 모델을 가져와 SDK Agent에 할당하세요:

from agents import Agent
from agents.extensions.experimental.hosted_multi_agent import OpenAIHostedMultiAgentModel

agent = Agent(
    name="Research coordinator",
    instructions="Delegate independent research tasks, then synthesize the findings.",
    model=OpenAIHostedMultiAgentModel(model="gpt-5.6-sol", config={"max_concurrent_subagents": 3}),
)

OpenAIHostedMultiAgentModel을 생성하면 multi_agent.enabled가 활성화되고 OpenAI-Beta: responses_multi_agent=v1 WebSocket 헤더가 전송돼요. 모델은 openai_client가 제공되지 않으면 기본 OpenAI 클라이언트를 사용해요. max_concurrent_subagents를 생략하면 서비스 기본값이 사용돼요.

로컬 함수 도구

모든 호스팅 에이전트는 요청에 구성된 모델과 도구를 공유해요. Responses API가 어느 호스팅 에이전트가 함수를 호출할지 결정해요. 일반 SDK Runner가 함수를 로컬에서 실행하고, 같은 호출 ID를 가진 function_call_output을 활성 WebSocket 응답에 주입해서 서비스가 원래 호스팅 호출자로 재개할 수 있게 해요. 함수 실행은 여전히 Runner의 일반 guardrail, 훅, 실패 변환을 통과해요. SDK 도구 승인 인터럽트는 지원되지 않아요. needs_approval 설정이 False가 아닌 함수 도구는 요청이 전송되기 전에 거부돼요.

도구가 호출자 인식 로깅이나 인가를 필요로 할 때는 get_hosted_agent_metadata()를 사용하세요:

from typing import Any

from agents.decorators import tool
from agents.extensions.experimental.hosted_multi_agent import get_hosted_agent_metadata
from agents.tool_context import ToolContext

@tool
def lookup_document(ctx: ToolContext[Any], section: str) -> str:
    metadata = get_hosted_agent_metadata(ctx)
    caller = metadata.agent_name if metadata else "unknown"
    print(f"tool caller: {caller}; call ID: {ctx.tool_call_id}")
    return f"Contents for {section}"

호스팅 에이전트 이름은 관찰용 메타데이터이지 로컬 라우팅 메커니즘이 아니에요. SDK가 제공하는 호출 ID로 출력을 라우팅하세요. 부수 효과(side-effecting)가 있는 도구에서는 그 호출 ID를 멱등성(idempotency) 키로 사용하고, 도구 실행 전이나 중에 필요한 인가를 애플리케이션 코드에서 강제하세요. 이 모델과 함께 needs_approval을 사용하지 마세요. 도구 인자와 출력은 Responses API 경계를 가로질러요.

출력과 스트리밍 동작

/root에 귀속되고 phase가 final_answer인 메시지만 일반 최종 메시지가 돼요. 실험적 어댑터는 하위 에이전트 메시지와 호스팅 조정 기록을 고수준 RunResult에서 걸러내요. SDK는 그 기록들을 로컬 함수로 절대 실행하지 않아요.

원시 스트리밍은 호스팅 출력 항목과 response.inject.created 승인을 포함한 beta Responses 이벤트를 계속 노출해요. 어댑터는 함수 호출이 준비되면 하나의 활성 제공자 응답을 SDK가 보이는 논리적 모델 턴으로 나누고, Runner가 출력을 만든 뒤 그 같은 제공자 응답을 재개해요. 원시 호스팅 항목이나 ToolContext와 함께 get_hosted_agent_metadata()을 사용해서 항목이나 도구 호출이 귀속된 호스팅 에이전트를 식별하면 돼요.

SDK 조정과의 관계

호스팅 멀티-에이전트는 SDK handoff 및 agents-as-tools와는 별개예요:

  • 호스팅 멀티-에이전트는 OpenAI 서비스에 하위 에이전트를 만들어요. 여러분의 애플리케이션이 그 하위 에이전트를 만들거나 스케줄링하지 않아요.
  • SDK handoff는 로컬 SDK Agent를 바꿔요. 이 실험적 모델이 사용될 때는 거부돼요. 모든 호스팅 에이전트가 같은 handoff 도구를 받아 충돌하는 소유권이 생기기 때문이에요.
  • Agents-as-tools는 계속 사용할 수 있지만, 사용하면 클라이언트 측과 서버 측 조정이 중첩돼요. 추가적인 지연, 비용, 도구 노출을 의도적으로 평가하세요.

현재 제한 사항

실험적 모델은 reasoning.summary, max_tool_calls, 그리고 호출자가 제공한 multi_agent 또는 betas 오버라이드를 거부해요. beta는 Responses /compact 엔드포인트를 지원하지 않지만, 명시적 context_management.compact_threshold는 사용할 수 있어요. 서비스가 각 호스팅 에이전트 컨텍스트를 독립적으로 자동 컴팩트하기 때문이에요.

OpenAIHostedMultiAgentModel 인스턴스 하나는 한 번에 기껏해야 하나의 활성 호스팅 응답을 소유해요. 로컬 함수 출력을 기다리는 동안 실행을 버렸다면 await model.close()를 호출해서 WebSocket을 해제하세요. 다른 프로세스나 이벤트 루프에서 진행 중인 호스팅 응답을 복원하는 것은 현재 지원되지 않아요.

기본 Responses API beta 동작은 OpenAI Multi-agent 가이드를, 비스트리밍·스트리밍 SDK 사용법은 examples/agent_patterns/hosted_multi_agent_beta.py를 참고하세요.

비-OpenAI 모델

비-OpenAI 제공자가 필요하다면 SDK의 내장 제공자 통합 지점부터 시작하세요. 많은 설정에서 타사 어댑터 없이도 충분해요. 각 패턴의 예시는 examples/model_providers에 있어요.

비-OpenAI 제공자 통합 방법

접근법 언제 쓰나 범위
set_default_openai_client 하나의 OpenAI 호환 엔드포인트가 대부분 또는 모든 에이전트의 기본이어야 함 전역 기본값
ModelProvider 하나의 커스텀 제공자가 단일 실행에 적용되어야 함 실행별
Agent.model 에이전트마다 다른 제공자나 구체적인 모델 객체가 필요함 에이전트별
타사 어댑터 내장 경로가 제공하지 않는 제공자 커버리지나 라우팅이 필요함 타사 어댑터 참고

다른 LLM 제공자는 이런 내장 경로로 통합할 수 있어요:

  1. set_default_openai_clientAsyncOpenAI 인스턴스를 LLM 클라이언트로 전역적으로 사용하고 싶은 경우에 유용해요. LLM 제공자가 OpenAI 호환 API 엔드포인트를 갖고 있고 base_urlapi_key를 설정할 수 있을 때 사용해요. 구성 가능한 예시는 examples/model_providers/custom_example_global.py를 참고하세요.
  2. ModelProviderRunner.run 수준에 있어요. "이 실행의 모든 에이전트에 커스텀 모델 제공자를 사용"할 수 있게 해줘요. 구성 가능한 예시는 examples/model_providers/custom_example_provider.py를 참고하세요.
  3. Agent.model은 특정 Agent 인스턴스에 모델을 지정하게 해줘요. 덕분에 에이전트마다 다른 제공자를 섞어 쓸 수 있어요. 구성 가능한 예시는 examples/model_providers/custom_example_agent.py를 참고하세요.

platform.openai.com에서 온 API 키가 없다면 set_tracing_disabled()로 트레이싱을 비활성화하거나, 다른 트레이싱 프로세서를 설정하는 것을 권장해요.

from agents import Agent, AsyncOpenAI, OpenAIChatCompletionsModel, set_tracing_disabled

set_tracing_disabled(disabled=True)

client = AsyncOpenAI(api_key="Api_Key", base_url="Base URL of Provider")
model = OpenAIChatCompletionsModel(model="Model_Name", openai_client=client)

agent= Agent(name="Helping Agent", instructions="You are a Helping Agent", model=model)

참고: 이 예시들은 Chat Completions API/모델을 사용해요. 많은 LLM 제공자가 아직 Responses API를 지원하지 않기 때문이에요. 내 LLM 제공자가 지원한다면 Responses를 사용하는 걸 권장해요.

한 워크플로우에서 모델 섞기

단일 워크플로우 안에서 에이전트마다 다른 모델을 사용하고 싶을 수 있어요. 예를 들어 트라이지에는 더 작고 빠른 모델을 쓰고, 복잡한 작업에는 더 크고 성능이 좋은 모델을 쓸 수 있어요. Agent를 구성할 때 다음 중 하나로 특정 모델을 고를 수 있어요:

  1. 모델 이름을 전달.
  2. 모델 이름 + 그 이름을 Model 인스턴스로 매핑할 수 있는 ModelProvider를 전달.
  3. 직접 Model 구현을 제공.

참고: SDK가 OpenAIResponsesModelOpenAIChatCompletionsModel 형태를 모두 지원하지만, 워크플로우마다 단일 모델 형태를 사용하는 것을 권장해요. 두 형태는 서로 다른 기능·도구 집합을 지원하기 때문이에요. 워크플로우가 모델 형태를 섞어 써야 한다면, 사용하는 모든 기능이 양쪽 모두에서 사용 가능한지 확인하세요.

import asyncio

from agents import Agent, Runner, AsyncOpenAI, OpenAIChatCompletionsModel

spanish_agent = Agent(
    name="Spanish agent",
    instructions="You only speak Spanish.",
    model="gpt-5-mini", # (1)!
)

english_agent = Agent(
    name="English agent",
    instructions="You only speak English",
    model=OpenAIChatCompletionsModel( # (2)!
        model="gpt-5-nano",
        openai_client=AsyncOpenAI()
    ),
)

triage_agent = Agent(
    name="Triage agent",
    instructions="Handoff to the appropriate agent based on the language of the request.",
    handoffs=[spanish_agent, english_agent],
    model="gpt-5.6-sol",
)

async def main():
    result = await Runner.run(triage_agent, input="Hola, ¿cómo estás?")
    print(result.final_output)

if __name__ == "__main__":
    asyncio.run(main())
  1. OpenAI 모델 이름을 직접 설정.
  2. Model 구현을 제공.

에이전트에 사용하는 모델을 더 구성하고 싶다면 temperature 같은 선택적 모델 구성 매개변수를 제공하는 ModelSettings를 전달하면 돼요.

from agents import Agent, ModelSettings

english_agent = Agent(
    name="English agent",
    instructions="You only speak English",
    model="gpt-4.1",
    model_settings=ModelSettings(temperature=0.1),
)

고급 OpenAI Responses 설정

OpenAI Responses 경로에 있고 더 많은 제어가 필요하다면 ModelSettings부터 시작하세요.

일반적인 고급 ModelSettings 옵션

OpenAI Responses API를 사용할 때 여러 요청 필드는 이미 직접적인 ModelSettings 필드를 갖고 있어서, 그 필드들에 extra_args가 필요 없어요.

  • parallel_tool_calls: 같은 턴에서 여러 도구 호출을 허용하거나 금지.
  • truncation: "auto"로 설정하면 컨텍스트가 넘칠 때 실패하는 대신 Responses API가 가장 오래된 대화 항목을 버리게 해줘요.
  • store: 생성된 응답을 서버 측에 저장해서 나중에 검색할 수 있게 할지 제어. 응답 ID에 의존하는 후속 워크플로우와, store=False일 때 로컬 입력으로 폴백해야 할 수 있는 세션 컴팩션 흐름에 중요해요.
  • context_management: compact_threshold로 Responses 컴팩션 같은 서버 측 컨텍스트 처리를 구성.
  • prompt_cache_retention: 예를 들어 "24h"로 이전 모델 계열의 확장 보존을 구성.
  • prompt_cache_options: 암시적 또는 명시적 프롬프트 캐싱을 선택하고, GPT-5.6에서는 "30m" 캐시 TTL을 구성.
  • response_include: web_search_call.action.sources, file_search_call.results, reasoning.encrypted_content 같은 더 풍부한 응답 페이로드 요청.
  • top_logprobs: 출력 텍스트에 대해 top-token logprobs를 요청. SDK는 message.output_text.logprobs도 자동으로 추가해요.
  • retry: 모델 호출의 runner 관리 재시도 설정에 참여. Runner 관리 재시도 참고.
from agents import Agent, ModelSettings

research_agent = Agent(
    name="Research agent",
    model="gpt-5.6-sol",
    model_settings=ModelSettings(
        parallel_tool_calls=False,
        truncation="auto",
        store=True,
        context_management=[{"type": "compaction", "compact_threshold": 200000}],
        prompt_cache_options={"mode": "explicit", "ttl": "30m"},
        response_include=["web_search_call.action.sources"],
        top_logprobs=5,
    ),
)

명시적 프롬프트 캐싱에서는 재사용 가능한 접두사를 끝내는 콘텐츠 부분에 중단점(breakpoint)을 추가하세요. 같은 ModelSettings.prompt_cache_options 필드는 Responses와 Chat Completions 요청 모두에 전달되며, Chat Completions 변환기는 텍스트, 이미지, 오디오, 파일 콘텐츠 부분의 중단점을 보존해요.

from agents import Runner

result = await Runner.run(
    research_agent,
    [
        {
            "role": "user",
            "content": [
                {
                    "type": "input_text",
                    "text": "Reusable background material...",
                    "prompt_cache_breakpoint": {"mode": "explicit"},
                },
                {
                    "type": "input_text",
                    "text": "Analyze the latest question.",
                },
            ],
        }
    ],
)

prompt_cache_retention은 레거시 보존 제어를 사용하는 이전 모델 계열에 계속 사용할 수 있어요. 직접 ModelSettings 필드와 같은 키를 extra_args에 함께 넣지 마세요.

store=False로 설정하면 Responses API가 그 응답을 나중에 서버 측에서 검색할 수 없게 유지해요. 이는 무상태 또는 zero-data-retention 스타일 흐름에 유용하지만, 응답 ID를 재사용하던 기능들은 로컬 관리 상태에 의존해야 한다는 뜻이기도 해요. 예를 들어 OpenAIResponsesCompactionSession은 마지막 응답이 저장되지 않았을 때 기본 "auto" 컴팩션 경로를 입력 기반 컴팩션으로 바꿔요. Sessions 가이드를 참고하세요.

서버 측 컴팩션은 OpenAIResponsesCompactionSession과는 달라요. context_management=[{"type": "compaction", "compact_threshold": ...}]는 각 Responses API 요청과 함께 전송되고, 렌더링된 컨텍스트가 임계값을 넘으면 API가 응답의 일부로 컴팩션 항목을 내보낼 수 있어요. OpenAIResponsesCompactionSession은 턴 사이에 독립형 responses.compact 엔드포인트를 호출하고 로컬 세션 기록을 다시 작성해요.

extra_args 전달

SDK가 아직 최상위에서 직접 노출하지 않는 제공자별 또는 최신 요청 필드가 필요할 때 extra_args를 사용하세요.

OpenAI 모델을 사용할 때 extra_args는 Responses API와 Chat Completions API 양쪽에 선택적 매개변수(예: user, service_tier)를 전달할 수 있어요. 지원되는 모델에서는 extra_args={"service_tier": "fast"}를 설정해서 Fast mode를 사용할 수 있어요. "priority"는 여전히 동일한 의미예요. 직접 ModelSettings 필드를 통해 같은 요청 필드를 동시에 설정하지 마세요.

from agents import Agent, ModelSettings

english_agent = Agent(
    name="English agent",
    instructions="You only speak English",
    model="gpt-4.1",
    model_settings=ModelSettings(
        temperature=0.1,
        extra_args={"service_tier": "flex", "user": "user_12345"},
    ),
)

모델 호출 타임아웃

ModelSettings.timeout에 양의 초 단위 숫자를 설정해서 각 모델 호출 시도를 제한하세요. 타임아웃은 스트리밍 및 비스트리밍 호출에 적용되고, 전송 대기까지 포함한 전체 시도를 다뤄요. 전체 에이전트 실행, 함수-도구 실행, 재시도 백오프는 제한하지 않아요.

from agents import Agent, ModelSettings

agent = Agent(
    name="Assistant",
    model_settings=ModelSettings(timeout=30.0),
)

시도가 한도를 넘으면 SDK는 시도를 취소하고 정리(cleanup)가 끝날 때까지 기다린 뒤 ModelTimeoutError를 발생시켜요. runner 관리 재시도가 활성화되면 SDK는 context.normalized.is_timeoutTrue로 설정해서 타임아웃 실패를 재시도 정책에 전달해요. 예를 들어 retry_policies.network_error()가 그 분류와 일치해요. 허용된 각 재시도는 새 시도별 타임아웃을 받아요. SDK는 재시도 전에 여전히 일반 재생-안전 규칙을 적용해요.

Runner 관리 재시도

재시도는 런타임 전용이며 선택(opt in) 항목이에요. ModelSettings(retry=...)을 설정하고 재시도 정책이 재시도를 선택하지 않는 한, SDK는 일반 모델 요청을 재시도하지 않아요.

Responses websocket 전송에서 retry_policies.provider_suggested()는 응답 전 오버로드 프레임과 코드 없는 server_error 프레임을 재시도 제안으로 인식해요. 이것만으로는 재시도가 활성화되지 않아요. 여전히 ModelRetrySettings가 필요하고, 일반 재생-안전 검사가 계속 적용돼요. 응답 이벤트가 이미 하나라도 도착했다면 SDK는 요청을 재생하지 않아요.

from agents import Agent, ModelRetrySettings, ModelSettings, retry_policies

agent = Agent(
    name="Assistant",
    model="gpt-5.6-sol",
    model_settings=ModelSettings(
        retry=ModelRetrySettings(
            max_retries=4,
            backoff={
                "initial_delay": 0.5,
                "max_delay": 5.0,
                "multiplier": 2.0,
                "jitter": True,
            },
            policy=retry_policies.any(
                retry_policies.provider_suggested(),
                retry_policies.retry_after(),
                retry_policies.network_error(),
                retry_policies.http_status([408, 409, 429, 500, 502, 503, 504]),
            ),
        )
    ),
)

ModelRetrySettings는 세 필드를 가져요:

필드 타입 참고
max_retries `int None`
backoff `ModelRetryBackoffSettings dict
policy `RetryPolicy None`

재시도 정책은 다음을 담은 RetryPolicyContext를 받아요:

  • 시도 인식 결정을 내릴 수 있게 해주는 attemptmax_retries.
  • 스트리밍과 비스트리밍 동작 사이에서 분기할 수 있게 해주는 stream.
  • 원시 검사를 위한 error.
  • status_code, retry_after, error_code, is_network_error, is_timeout, is_abort 같은 normalized 사실.
  • 내부 모델 어댑터가 재시도 지침을 제공할 수 있을 때의 provider_advice.
  • 정책이 실행되기 전에 캡처된 안정적인 재생-안전 사실인 response_started, replay_safety, stateful_request. replay_safety"safe", "unsafe", "unknown"이며, stateful_request는 요청이 previous_response_idconversation_id를 사용할 때 true예요.

정책은 둘 중 하나를 반환할 수 있어요:

  • 단순한 재시도 결정을 위한 True / False.
  • 지연을 오버라이드하거나, 진단 이유를 붙이거나, 좁게 범위가 한정된 안전하지 않은 재생을 명시적으로 승인하고 싶을 때의 RetryDecision.

SDK는 retry_policies에 바로 쓸 수 있는 헬퍼들을 내보내요:

헬퍼 동작
retry_policies.never() 항상 선택 해제.
retry_policies.provider_suggested() 제공자의 재시도 조언이 있을 때 따름.
retry_policies.network_error() 일시적인 전송·타임아웃 실패와 일치.
retry_policies.http_status([...]) 선택된 HTTP 상태 코드와 일치.
retry_policies.retry_after() retry-after 힌트가 있을 때만 재시도하며 그 지연을 사용. 이 헬퍼는 retry-after 값을 명시적 정책 지연으로 취급하므로 backoff.max_delay가 상한으로 잡지 않아요.
retry_policies.any(...) 중첩 정책 중 하나가 선택하면 재시도.
retry_policies.all(...) 모든 중첩 정책이 선택할 때만 재시도.

정책을 구성할 때 provider_suggested()가 가장 안전한 첫 번째 구성 블록이에요. 제공자가 그것들을 구분할 수 있을 때 제공자 거부권과 재생-안전 승인을 보존하기 때문이에요.

안전 경계

어떤 실패는 절대 재시도되지 않아요:

  • 중단(abort) 오류.
  • 재생이 안전하지 않게 될 방식으로 출력이 이미 시작된 후의 스트리밍 실행.
  • Programmatic Tool Calling 요청을 포함해 별도의 로컬 부수 효과 재생 거부권이 있는 요청. 단, 제공자가 해당 재생을 독립적으로 안전하다고 표시한 경우는 제외.

제공자가 안전하지 않다고 표시한 실패도 기본적으로 차단돼요. 별도의 로컬 부수 효과 거부권이 없는 비스트리밍 요청에서는 RetryDecision(retry=True, approve_unsafe_replay=True)를 반환해서 제공자 측 재생 위험을 받아들일 수 있어요. 이 승인을 부여하기 전에 context.response_started, context.replay_safety, context.stateful_request를 확인하고, 제공자 측 작업을 반복하는 것이 허용될 때만 부여하세요. 일반 RetryDecision(retry=True)는 재생 보호를 우회하지 않으며, approve_unsafe_replay=True는 스트리밍 재시도나 로컬 부수 효과를 승인할 수 없어요.

previous_response_idconversation_id를 사용하는 상태 저장 후속 요청은 재생 안전이 알려지지 않았을 때 실패-폐쇄(fail closed)돼요. 그런 요청에서는 network_error()http_status([500]) 같은 비-제공자 조건자만으로는 부족해요. 일반적으로 retry_policies.provider_suggested()를 통한 제공자의 재생-안전 승인을 포함하거나, 제공자가 안전하지 않다고 표시한 비스트리밍 실패를 위에서 설명한 대로 명시적으로 승인하세요.

Runner와 에이전트 병합 동작

retry는 runner 수준과 에이전트 수준 ModelSettings 사이에서 깊게 병합돼요:

  • 에이전트는 retry.max_retries만 오버라이드하고 runner의 policy를 계속 상속할 수 있어요.
  • 에이전트는 retry.backoff의 일부만 오버라이드하고 runner의 형제 백오프 필드를 유지할 수 있어요.
  • policy는 런타임 전용이므로, 직렬화된 ModelSettingsmax_retriesbackoff를 유지하지만 콜백 자체는 생략해요.

더 완전한 예시는 examples/basic/retry.py어댑터 기반 재시도 예시를 참고하세요.

비-OpenAI 제공자 문제 해결

트레이싱 클라이언트 오류 401

트레이싱 관련 오류가 나는 건 트레이스가 OpenAI 서버에 업로드되는데 OpenAI API 키가 없기 때문이에요. 해결 방법은 세 가지예요:

  1. 트레이싱을 완전히 비활성화: set_tracing_disabled(True).
  2. 트레이싱용 OpenAI 키 설정: set_tracing_export_api_key(...). 이 API 키는 트레이스 업로드에만 사용되며 platform.openai.com에서 온 것이어야 해요.
  3. 비-OpenAI 트레이스 프로세서 사용. 트레이싱 문서 참고.

Responses API 지원

SDK는 기본적으로 Responses API를 사용하지만, 많은 다른 LLM 제공자는 아직 지원하지 않아요. 그 결과 404 같은 오류가 보일 수 있어요. 해결 방법은 두 가지예요:

  1. set_default_openai_api("chat_completions") 호출. OPENAI_API_KEYOPENAI_BASE_URL을 환경 변수로 설정하고 있다면 동작해요.
  2. OpenAIChatCompletionsModel 사용. 예시는 여기에 있어요.

Chat Completions 호환성 옵션

Chat Completions로 라우팅할 때 SDK는 Chat Completions가 보낼 수 없는 Responses 전용 필드(previous_response_id, conversation_id, Responses API prompt 필드, 텍스트 전용이 아닌 도구 출력 등)를 조용히 버려서 호환성을 유지해요. 개발 중에 그런 불일치를 즉시 실패시키고 싶다면 OpenAI 제공자에서 엄격한 기능 검증을 활성화하세요:

from agents import Agent, OpenAIProvider, RunConfig, Runner

provider = OpenAIProvider(
    use_responses=False,
    strict_feature_validation=True,
)

agent = Agent(name="Assistant")
result = await Runner.run(
    agent,
    "Hello",
    run_config=RunConfig(model_provider=provider),
)

MultiProvider를 사용한다면 대신 openai_strict_feature_validation=True를 전달하세요.

OpenAI Chat Completions API는 오디오 출력을 반환할 수 있지만, OpenAIChatCompletionsModel은 현재 오디오 출력을 Agents SDK 실행 항목으로 변환하지 않아요. 비스트리밍 메시지나 스트리밍 델타에 오디오 출력이 포함되면 어댑터는 부분적이거나 빈 결과를 반환하는 대신 AgentsException("Audio is not currently supported")를 발생시켜요. SDK 관리 오디오 워크플로우에는 Realtime 에이전트Voice 에이전트를 사용하세요.

스트리밍 또는 비스트리밍 Chat Completions 응답이 어시스턴트 텍스트, 도구 호출, 거절(refusal)을 만들기 전에 finish_reason="length"로 끝나면 어댑터는 ModelBehaviorError를 발생시켜요. SDK는 이 빈 결과를 콘텐츠 정책 거절이 아니라 토큰·reasoning 예산 소진으로 취급하므로, 모델 거절 핸들러가 이에 대해 실행되지 않아요.

일부 OpenAI 호환 Chat Completions 제공자는 SDK의 증분 처리에 충분히 신뢰할 수 없는 청크로 도구 호출 델타를 스트리밍해요. 그런 경우 스트리밍 도구 호출 버퍼링을 활성화해서 SDK가 제공자 스트림이 끝난 뒤에만 도구 호출을 내보내게 하세요:

from agents import OpenAIProvider

provider = OpenAIProvider(
    use_responses=False,
    buffer_streamed_tool_calls=True,
)

MultiProvider에서는 openai_buffer_streamed_tool_calls=True를 사용하세요.

구조화된 출력 지원

일부 모델 제공자는 구조화된 출력을 지원하지 않아요. 그러면 이런 오류가 가끔 발생해요:

BadRequestError: Error code: 400 - {'error': {'message': "'response_format.type' : value is not one of the allowed values ['text','json_object']", 'type': 'invalid_request_error'}}

이것은 일부 모델 제공자의 단점이에요. JSON 출력은 지원하지만 출력에 사용할 json_schema를 지정하게 해주지는 않아요. 이에 대한 수정을 진행 중이지만, JSON schema 출력을 지원하는 제공자에 의존하는 것을 권장해요. 그렇지 않으면 잘못된 JSON 때문에 앱이 자주 깨질 수 있거든요.

제공자 간 모델 섞기

모델 제공자 간의 기능 차이를 인지하지 못하면 오류가 날 수 있어요. 예를 들어 OpenAI는 구조화된 출력, 멀티모달 입력, 호스팅 파일 검색과 웹 검색을 지원하지만 많은 다른 제공자는 지원하지 않아요. 이런 제한 사항을 알고 있어야 해요:

  • 지원하지 않는 tools를 이해하지 못하는 제공자에 보내지 마세요.
  • 텍스트 전용 모델을 호출하기 전에 멀티모달 입력을 걸러내세요.
  • 구조화된 JSON 출력을 지원하지 않는 제공자는 가끔 잘못된 JSON을 만들 수도 있다는 점을 인지하세요.

타사 어댑터

타사 어댑터는 SDK의 내장 제공자 통합 지점만으로 부족할 때만 찾으세요. 이 SDK로 OpenAI 모델만 사용한다면 Any-LLM이나 LiteLLM 대신 내장 OpenAIResponsesModel 경로를 선호하세요. 타사 어댑터는 OpenAI 모델을 비-OpenAI 제공자와 결합해야 하거나, 어댑터만 제공하는 제공자 커버리지나 라우팅이 필요할 때를 위한 거예요. 어댑터는 SDK와 업스트림 모델 제공자 사이에 또 하나의 호환성 계층을 추가하므로, 기능 지원과 요청 의미론이 제공자마다 달라질 수 있어요. SDK는 현재 Any-LLM과 LiteLLM을 best-effort, beta 어댑터 통합으로 포함해요.

Any-LLM

Any-LLM 지원은 Any-LLM이 관리하는 제공자 커버리지나 라우팅이 필요할 때를 위해 best-effort, beta 기준으로 포함돼요.

업스트림 제공자 경로에 따라 Any-LLM은 Responses API, Chat Completions 호환 API, 또는 제공자별 호환성 계층을 사용할 수 있어요.

Any-LLM이 필요하다면 openai-agents[any-llm]을 설치하고, examples/model_providers/any_llm_auto.pyexamples/model_providers/any_llm_provider.py에서 시작하세요. MultiProvider와 함께 any-llm/... 모델 이름을 쓰거나, AnyLLMModel을 직접 인스턴스화하거나, 실행 범위에서 AnyLLMProvider를 사용할 수 있어요. 모델 표면을 명시적으로 고정할 필요가 있으면 AnyLLMModel을 구성할 때 api="responses"api="chat_completions"를 전달하세요.

Any-LLM Chat Completions 경로에서 ModelSettings.extra_body는 여전히 중첩된 extra_body 인자예요. Agents SDK는 그 매핑을 Any-LLM의 최상위 호출 인자에 병합하지 않으므로, 제공자별 요청 본문 필드를 extra_body 매핑 안에 유지하세요.

Any-LLM은 여전히 타사 어댑터 계층이므로, 제공자 의존성과 기능 격차는 SDK가 아니라 Any-LLM이 업스트림에서 정의해요. 업스트림 제공자가 반환하면 사용량 메트릭이 자동으로 전파되지만, 스트리밍 Chat Completions 백엔드는 usage 청크를 내보내기 전에 ModelSettings(include_usage=True)가 필요할 수 있어요. 구조화된 출력, 도구 호출, 사용량 보고, 또는 Responses 특정 동작에 의존한다면 배포할 정확한 제공자 백엔드를 검증하세요.

LiteLLM

LiteLLM 지원은 LiteLLM 특정 제공자 커버리지나 라우팅이 필요할 때를 위해 best-effort, beta 기준으로 포함돼요.

LiteLLM이 필요하다면 openai-agents[litellm]을 설치하고, examples/model_providers/litellm_auto.pyexamples/model_providers/litellm_provider.py에서 시작하세요. litellm/... 모델 이름을 쓰거나 LitellmModel을 직접 인스턴스화할 수 있어요.

LiteLLM 어댑터를 통해 접근하는 일부 제공자는 기본적으로 SDK 사용량 메트릭을 채우지 않아요. 사용량 보고가 필요하면 ModelSettings(include_usage=True)를 전달하고, 구조화된 출력, 도구 호출, 사용량 보고, 또는 어댑터 특정 라우팅 동작에 의존한다면 배포할 정확한 제공자 백엔드를 검증하세요.

LiteLLM이 응답 객체에 대해 Pydantic 직렬화 경고를 내보낸다면, LiteLLM 어댑터를 가져오기 전에 SDK의 호환성 패치에 선택적으로 참여할 수 있어요:

export OPENAI_AGENTS_ENABLE_LITELLM_SERIALIZER_PATCH=true

패치는 기본적으로 비활성화되어 있으며 1 또는 true 값에서만 활성화돼요. 이 패치는 프라이빗 LiteLLM 로깅 헬퍼를 래핑해서 특정 부류의 LiteLLM 응답 직렬화 경고를 억제해요. 그러니 일반적인 직렬화 설정이 아니라 표적 워크어라운드로 취급하세요. 프라이빗 LiteLLM API에 의존하므로 LiteLLM을 업그레이드할 때 다시 검증하고, 업스트림 경고가 더 이상 발생하지 않으면 환경 변수를 제거하세요.

더 알아보기 (Learn more)