OpenAI

OpenAI

이 문서에서는 pydantic-ai에서 OpenAI 모델과 OpenAI 호환 API를 설치하고 설정하는 방법을 알려드려요. Responses API와 Chat Completions API를 사용하는 법, 커스텀 클라이언트, 모델 설정, 프롬프트 캐싱, 네이티브 도구, 여러 OpenAI 호환 프로바이더(Groq, DeepSeek, Alibaba, Azure, Vercel, MoonshotAI, Fireworks, Together, vLLM, LiteLLM 등) 사용법을 다뤄요.

출처: 문서

본문

설치 (Install)

OpenAI 모델이나 OpenAI 호환 API를 사용하려면 pydantic-ai를 설치하거나, openai 선택 그룹과 함께 pydantic-ai-slim을 설치하세요:

pip install "pydantic-ai-slim[openai]"
uv add "pydantic-ai-slim[openai]"

구성 (Configuration)

OpenAI API로 OpenAI 모델을 사용하려면 platform.openai.com에 가서 API 키를 생성하는 곳을 찾아 만드세요.

— API 키 대신 ChatGPT/Codex 구독을 사용할 수도 있어요. openai-codex: 접두사는 공식 Codex CLI와 같은 OAuth 흐름으로 Codex 백엔드에 인증해요.

환경 변수 (Environment variable)

API 키를 얻으면 환경 변수로 설정하세요:

export OPENAI_API_KEY='your-api-key'

베어 'openai:' 접두사는 현대적인 Responses API를 사용하는 OpenAIResponsesModel로 해석돼요.

from pydantic_ai import Agent

agent = Agent('openai:gpt-6-sol')
...

대신 레거시 Chat Completions API에 고정하려면 'openai-chat:' 접두사를 사용하세요. 이것은 OpenAIChatModel로 해석돼요. gpt-6-solgpt-6-luna의 경우 Chat Completions는 openai_reasoning_effort='none'일 때만 함수 호출을 지원해요. reasoning과 도구를 함께 필요로 하면 Responses API를 사용하세요.

또는 모델 이름만으로 직접 모델을 초기화하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel

model = OpenAIResponsesModel('gpt-6-sol')
agent = Agent(model)
...

기본적으로 모델은 base_urlhttps://api.openai.com/v1OpenAIProvider를 사용해요.

프로바이더 구성 (Configure the provider)

코드에서 프로바이더에 파라미터를 전달하려면 OpenAIProvider를 프로그래밍 방식으로 인스턴스화해 모델에 전달하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel
from pydantic_ai.providers.openai import OpenAIProvider

model = OpenAIResponsesModel('gpt-5.2', provider=OpenAIProvider(api_key='your-api-key'))
agent = Agent(model)
...

커스텀 OpenAI 클라이언트 (Custom OpenAI Client)

OpenAIProvideropenai_client 파라미터를 통해 커스텀 AsyncOpenAI 클라이언트도 받아요. OpenAI API 문서에 정의된 대로 organization, project, base_url 등을 커스터마이즈할 수 있어요.

클라이언트는 에이전트의 재시도 예산과 무관하게 실패한 요청을 자체적으로 재시도해요. 기본 max_retries=2라 한 모델 요청이 네트워크에 최대 세 번 닿을 수 있어요. x-should-retry 응답 헤더를 존중하고, 그 헤더가 없으면 408, 409, 429, 5xx에 더해 타임아웃·연결 오류를 재시도하지만, 400·401 같은 다른 4xx는 재시도하지 않아요. 재시도 정책을 전송 계층에만 두려면 max_retries=0을 설정하세요. 계층이 어떻게 쌓이는지는 재시도 곱셈을 참고하세요.

from openai import AsyncOpenAI

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel
from pydantic_ai.providers.openai import OpenAIProvider

client = AsyncOpenAI(max_retries=3)
model = OpenAIResponsesModel('gpt-5.2', provider=OpenAIProvider(openai_client=client))
agent = Agent(model)
...

AsyncAzureOpenAI 클라이언트를 사용해 Azure OpenAI API를 쓸 수도 있어요. AsyncAzureOpenAIAsyncOpenAI의 서브클래스에요.

from openai import AsyncAzureOpenAI

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.openai import OpenAIProvider

client = AsyncAzureOpenAI(
    azure_endpoint='...',
    api_version='2024-07-01-preview',
    api_key='your-api-key',
)

model = OpenAIChatModel(
    'gpt-5.2',
    provider=OpenAIProvider(openai_client=client),
)
agent = Agent(model)
...

이미지 생성 (Image generation)

ImageGeneratoropenai: 이미지 모델과 함께 사용해 직접 생성과 참조 이미지 편집을 하세요. 이것은 대화형 Responses 모델이 아니라 OpenAI의 Images API를 사용해요:

from pydantic_ai import ImageGenerator
from pydantic_ai.images.openai import OpenAIImageGenerationSettings

generator = ImageGenerator(
    'openai:gpt-image-2',
    settings=OpenAIImageGenerationSettings(
        dimensions=(1280, 720),
        openai_quality='low',
        openai_output_format='jpeg',
    ),
)

OpenAI는 BinaryImageImageUrl 참조 입력을 받아요. 그것의 이미지 편집 엔드포인트는 파일 콘텐츠가 필요하고 UploadedFile 프로바이더 파일 ID는 받지 않아요. 투명 배경 지원은 모델에 따라 다르며 PNG 또는 WebP 출력이 필요해요. 프로바이더별 설정은 OpenAI에 전달되므로 새로 지원되는 값이 지난 클라이언트 측 검사에 차단되지 않아요. 생성·편집·기하학·정규화 설정은 이미지 생성 가이드를 참고하세요.

GPT 이미지 모델은 유료 사용 티어의 검증된 조직이 필요해요. 검증되지 않은 조직에서는 모든 요청이 생성 전에 요율 제한 오류로 실패해요. 복잡한 프롬프트는 처리에 최대 2분이 걸릴 수 있어요.

모델 설정 (Model settings)

OpenAIResponsesModelSettings로 모델 동작을 커스터마이즈할 수 있어요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel, OpenAIResponsesModelSettings

model = OpenAIResponsesModel('gpt-5.2')
settings = OpenAIResponsesModelSettings(
    temperature=0.2,
    service_tier='flex',
)
agent = Agent(model, model_settings=settings)
...

서비스 티어 (Service tier)

OpenAI는 지연 시간과 비용을 절충하는 서비스 티어 제어를 지원해요. 통합 필드 service_tier나 프로바이더 전용 openai_service_tier 필드를 사용할 수 있어요. 둘 다 'auto', 'default', 'flex', 'priority'를 그대로 전달하며 받아요. 둘 다 설정되면 openai_service_tier가 통합 필드보다 우선해요.

프롬프트 캐싱 (Prompt caching)

GPT-5.6과 GPT-6 모델은 Responses와 Chat Completions API 모두에서 OpenAI의 암묵적·명시적 프롬프트 캐시 중단점을 지원해요. OpenAI는 기본적으로 암묵적 중단점을 만든다. 캐시 가능 접두사를 정밀하게 제어하려면 접두사를 끝내야 할 사용자 콘텐츠 블록 뒤에 CachePoint를 삽입하세요:

from pydantic_ai import Agent, CachePoint
from pydantic_ai.models.openai import OpenAIResponsesModelSettings

settings = OpenAIResponsesModelSettings(
    openai_prompt_cache_key='product-docs-v1',
    openai_prompt_cache_options={'mode': 'explicit', 'ttl': '30m'},
)
agent = Agent('openai:gpt-5.6-sol', model_settings=settings)

result = agent.run_sync([
    'Long-lived reference material...',
    CachePoint(),
    'Answer using the reference material.',
])

캐싱은 최소 1024 토큰 접두사가 필요해요. 더 짧은 접두사는 명시적으로 표시돼도 캐시되지 않아요. mode='implicit'(기본)에서는 OpenAI가 암묵적 중단점 하나와 명시적 중단점 최대 세 개를 쓸 수 있어요. mode='explicit'에서는 명시적 중단점 최대 네 개를 쓰고 암묵적 중단점은 없어요. TTL은 요청 전체에 적용돼요. OpenAI는 현재 openai_prompt_cache_options를 통해 구성되는 '30m'만 받고, 일반적인 마커별 CachePoint.ttl 값은 무시해요. GPT-5.6 이상 모델에서는 안정적 openai_prompt_cache_key를 설정해 암묵적·명시적 캐싱 모두에 OpenAI의 더 안정적인 일치를 사용하세요. 키 없는 요청은 여전히 자동 캐시 히트를 받을 수 있지만 개선된 일치를 사용하지 않아요. 다른 키로 무관한 워크로드를 파티션하세요.

OpenAI가 프롬프트 캐시 쓰기를 보고하면 Pydantic AI는 그것을 result.usage.cache_write_tokens로 노출해요. 캐시 읽기는 result.usage.cache_read_tokens로 제공돼요. GPT-5.6 이상 모델군은 캐시 쓰기를 캐시되지 않은 입력 토큰 요율의 1.25배로 청구해요.

중재 (Moderation)

Responses와 Chat Completions API 모두 요청의 입력·출력에서 중재를 실행할 수 있어요. 중재는 기본 꺼져 있고 openai_moderation으로 켜요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel, OpenAIResponsesModelSettings

model = OpenAIResponsesModel('gpt-5.2')
settings = OpenAIResponsesModelSettings(
    openai_moderation={'model': 'omni-moderation-latest'}
)
agent = Agent(model, model_settings=settings)

result = agent.run_sync('Your prompt here')
moderation = result.response.provider_details.get('moderation')

응답이 중재 결과를 포함하면 그것은 ModelResponse.provider_details'moderation' 키 아래 저장돼요. inputoutput 항목이 각각 플래그된 상태, 카테고리별 플래그, 카테고리 점수를 지녀요.

OpenAIChatModel에서는 대신 OpenAIChatModelSettings을 사용하세요. 결과는 비스트리밍·스트리밍 경로 모두 같은 방식으로 표면화돼요. 단, Chat Completions API는 각 항목을 results 목록 아래 한 단계 더 중첩해요.

Responses API 기능 (Responses API features)

아래 기능은 Responses API에 특화되어 OpenAIResponsesModel(기본)에서만 사용할 수 있어요. Responses API가 Chat Completions와 어떻게 다른지에 대한 배경은 OpenAI API 문서를 참고하세요.

추론 모드 (Reasoning mode)

GPT-5.6과 GPT-6군은 OpenAI의 standardpro 추론 모드를 사용할 수 있어요. standard가 기본이고, pro는 어려운 작업의 신뢰성을 위해 더 많은 모델 작업을 수행하지만 더 높은 지연·토큰 사용을 요구해요. 모드는 추론 effort와 무관해요. 모드와 effort의 어떤 조합도 유효하고, 통합 thinking 설정은 effort에만 영향을 주므로, pro는 명시적으로 설정할 때만 사용돼요.

openai_reasoning_mode로 모드를 구성하세요. 선택할 별도 pro 모델은 없어요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel, OpenAIResponsesModelSettings

model = OpenAIResponsesModel('gpt-5.6-sol')
settings = OpenAIResponsesModelSettings(openai_reasoning_mode='pro')
agent = Agent(model, model_settings=settings)
...

설정은 OpenAIModelProfile.openai_responses_supports_reasoning_mode에 따라 추론 모드를 지원하지 않는 모델에서는 무시돼요.

추론 컨텍스트 (Reasoning context)

추론 모델은 OpenAI의 추론 컨텍스트를 사용해 샘플링 시 모델에 사용 가능한 이전 턴 추론 항목을 제어할 수 있어요. auto는 모델 자신의 기본값에 위임하고(OpenAI는 필드를 보내지 않는 것과 정확히 같게 취급), current_turn은 활성 턴의 추론만 사용 가능하게 하며, all_turns는 이전 턴의 호환 추론 항목을 다음 샘플에 렌더링해요. all_turnsprevious_response_id, 대화, 또는 재생된 히스토리를 통한 이전 응답 항목 접근이 필요해요. 첫 요청에서는 current_turn처럼 동작해요.

Pydantic AI는 지원하는 모델에서 기본적으로 all_turns를 보내, 이전 턴 reasoning이 옵트인 없이 사용 가능하게 해요. 이전 thinking이 다른 모델로 다시 보내지는 것과 일치해요. 이것은 각 후속 샘플에 이전 reasoning을 렌더링하며 추가 입력 토큰을 비용으로 지불해요. OpenAI 자체 모델별 기본값에 위임하려면 auto를 명시적으로, 이전 턴을 샘플에서 제외하려면 current_turn을 설정하세요.

openai_reasoning_context로 컨텍스트를 구성하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel, OpenAIResponsesModelSettings

model = OpenAIResponsesModel('gpt-5.6-sol')
settings = OpenAIResponsesModelSettings(openai_reasoning_context='all_turns')
agent = Agent(model, model_settings=settings)
...

autocurrent_turn은 reasoning을 지원하는 어떤 모델에도 보내져요. all_turns는 프로파일이 OpenAIModelProfile.openai_responses_supports_reasoning_context를 설정한 모델(현재 GPT-5.4, GPT-5.5, GPT-5.6, GPT-6군)에만 보내지고, 다른 모델에서는 무시돼요.

네이티브 도구 (Native tools)

Responses API에는 직접 만들지 않고 쓸 수 있는 네이티브 도구가 있어요:

  • 웹 검색: 모델이 응답 생성 전에 최신 정보를 위해 웹을 검색하게 해요.
  • 코드 인터프리터: 모델이 샌드박스 환경에서 응답 생성 전에 Python 코드를 쓰고 실행하게 해요.
  • 이미지 생성: 모델이 텍스트 프롬프트에 기반해 이미지를 생성하게 해요.
  • 파일 검색: 모델이 응답 생성 전에 관련 정보를 위해 파일을 검색하게 해요.
  • 컴퓨터 사용: 모델이 대신 작업을 수행하기 위해 컴퓨터를 사용하게 해요.

웹 검색, 코드 인터프리터, 이미지 생성, 파일 검색은 네이티브 도구 기능을 통해 네이티브 지원돼요.

컴퓨터 사용은 OpenAIResponsesModelSettingsopenai_native_tools 설정에 openai.types.responses.ComputerToolParam을 전달해 켤 수 있어요. 현재 메시지 히스토리나 스트리밍 이벤트에 NativeToolCallPartNativeToolReturnPart를 생성하지 않아요. 이 네이티브 도구에 네이티브 지원이 필요하면 이슈를 제출하세요.

from openai.types.responses import ComputerToolParam

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel, OpenAIResponsesModelSettings

model_settings = OpenAIResponsesModelSettings(
    openai_native_tools=[
        ComputerToolParam(
            type='computer_use',
        )
    ],
)
model = OpenAIResponsesModel('gpt-5.2')
agent = Agent(model=model, model_settings=model_settings)

result = agent.run_sync('Open a new browser tab')
print(result.output)
이전 응답 참조 (Referencing earlier responses)

Responses API는 previous_response_id 파라미터로 새 요청에서 이전 모델 응답을 참조해, reasoning 항목을 포함한 전체 대화 상태를 재전송 없이 컨텍스트에 유지하게 해요. 이것은 OpenAIResponsesModelSettingsopenai_previous_response_id 필드로 사용할 수 있어요.

필드가 'auto'로 설정되면 Pydantic AI가 메시지 히스토리에서 가장 최근 provider_response_id를 자동 선택하고 그 앞의 메시지를 생략해, OpenAI API가 서버 측 상태에서 재구성하게 해요. 실행 안에서 도구 호출 연속과 재시도를 가로질러 같은 체이닝이 적용되므로 OpenAI가 같은 메시지의 중복 사본을 절대 보지 않아요.

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel, OpenAIResponsesModelSettings

model = OpenAIResponsesModel('gpt-5.2')
agent = Agent(model=model)

result1 = agent.run_sync('Tell me a joke.')
print(result1.output)

model_settings = OpenAIResponsesModelSettings(openai_previous_response_id='auto')
result2 = agent.run_sync(
    'Explain?',
    message_history=result1.new_messages(),
    model_settings=model_settings
)
print(result2.output)

message_history를 넘기는 대신, 이전 실행의 구체적 provider_response_id를 시드로 넘길 수 있어요. Pydantic AI는 새 실행의 첫 요청에 시드를 사용한 뒤, 실행 내의 이후 호출에서 그 요청에 반환된 응답으로 자동 체이닝해요. 그래서 실행에 도구 호출 연속이나 재시도가 포함돼도 체인이 여전히 올바르게 확장돼요.

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel, OpenAIResponsesModelSettings

model = OpenAIResponsesModel('gpt-5.2')
agent = Agent(model=model)

result = agent.run_sync('The secret is 1234')
model_settings = OpenAIResponsesModelSettings(
    openai_previous_response_id=result.all_messages()[-1].provider_response_id
)
result = agent.run_sync('What is the secret code?', model_settings=model_settings)
print(result.output)
# 1234

참고 — 저장된 응답을 참조하려면 그 응답이 실제로 저장돼야 해요. OpenAI는 기본적으로 응답을 저장해요. openai_store=False로 저장을 비활성화했거나 조직이 Zero Data Retention을 켰다면 체이닝을 쓸 수 없고 모든 요청에서 전체 메시지 히스토리를 보내야 해요.

지속 대화 사용 (Using durable conversations)

OpenAI의 Conversations API는 Responses API와 함께 지속 대화 객체에 대화 상태를 영속하도록 동작해요. 이미 OpenAI 대화 ID가 있으면 openai_conversation_id로 전달하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel, OpenAIResponsesModelSettings

model = OpenAIResponsesModel('gpt-5.2')
agent = Agent(model=model)

model_settings = OpenAIResponsesModelSettings(openai_conversation_id='conv_...')
result = agent.run_sync('What did we discuss last time?', model_settings=model_settings)
print(result.output)

응답이 대화에 속하면 Pydantic AI는 반환된 ID를 ModelResponse.provider_details['conversation_id']에 저장해요. openai_conversation_id='auto'는 메시지 히스토리의 가장 최근 같은 프로바이더 대화 ID를 사용하고 그 응답 뒤의 새 입력 항목만 보내요.

메시지 수준 conversation_id 값이 가능하면, auto는 현재 Pydantic AI 대화의 OpenAI 대화만 재사용해요. 명시적으로 재사용하려면 구체적 OpenAI 대화 ID를 전달하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel, OpenAIResponsesModelSettings

model = OpenAIResponsesModel('gpt-5.2')
agent = Agent(model=model)

model_settings = OpenAIResponsesModelSettings(openai_conversation_id='conv_...')
result = agent.run_sync('What did we discuss last time?', model_settings=model_settings)

follow_up_settings = OpenAIResponsesModelSettings(openai_conversation_id='auto')
result2 = agent.run_sync(
    'Summarize the next step.',
    message_history=result.new_messages(),
    model_settings=follow_up_settings,
)
print(result2.output)

Pydantic AI는 OpenAI 대화를 대신 만들지 않아요. OpenAI 클라이언트로 대화를 만든 뒤 그 ID를 openai_conversation_id에 전달하세요. conversationprevious_response_id 파라미터는 OpenAI API에서 상호 배타적이므로 openai_conversation_idopenai_previous_response_id와 결합할 수 없어요.

메시지 압축 (Message Compaction)

Responses API는 긴 대화에서 토큰 사용을 줄이기 위한 메시지 히스토리 압축을 지원해요. 압축은 컨텍스트를 보존하면서 오래된 메시지를 대체하는 암호화된 요약을 만들어요.

압축을 켜는 가장 쉬운 방법은 OpenAICompaction capability예요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAICompaction

agent = Agent(
    'openai-responses:gpt-5.2',
    capabilities=[OpenAICompaction()],
)

기본적으로 OpenAICompactionstateful 모드로 실행돼요. 일반 /responses 요청의 context_management 필드를 통해 OpenAI 서버 측 자동 압축을 구성하고, 입력 토큰 수가 서버가 관리하는 임계값을 넘으면 OpenAI가 압축을 트리거해요. 이 모드는 openai_previous_response_id='auto'openai_conversation_id와 호환돼요.

압축 후에는 이후 요청이 최신 압축 항목부터 압축된 창만 보내요. Responses API는 압축 항목 앞의 재생된 항목을 처리·청구하므로, 그것들을 생략하면 압축된 컨텍스트가 다시 자라지 않게 해요.

token_threshold를 전달해 임계값을 재정의하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAICompaction

agent = Agent(
    'openai-responses:gpt-5.2',
    capabilities=[OpenAICompaction(token_threshold=100_000)],
)

대안으로 OpenAICompactionbefore_model_request 훅을 통해 상태 없는 /responses/compact 엔드포인트를 호출하는 stateless 모드(stateless=True)를 지원해요. OpenAI가 대화 데이터를 보유하지 말아야 하는 ZDR 환경, openai_store=False 사용 시, 압축이 언제 실행될지 명시적으로 대역 외 제어가 필요할 때 사용하세요. stateless 모드는 message_count_threshold나 커스텀 trigger callable 중 하나를 지정해야 해요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAICompaction

agent = Agent(
    'openai-responses:gpt-5.2',
    capabilities=[OpenAICompaction(message_count_threshold=20)],
)

모드는 전달한 파라미터에서 추론돼요. message_count_thresholdtrigger를 공급하면 stateless 모드, 그렇지 않으면 stateful 모드가 사용돼요. stateless=Truestateless=False를 명시적으로 전달할 수도 있어요. 다른 모드의 파라미터를 섞으면 UserError가 발생해요.

— stateful 압축은 openai_previous_response_id='auto'openai_conversation_id와 특히 잘 어울려요. 둘 다 OpenAI 서버 측 대화 상태에 의존하므로, OpenAI가 이전에 압축된 컨텍스트를 다음 턴의 시작점으로 사용할 수 있어 재전송하지 않아도 돼요.

저수준 사용 사례에서는 모델에서 compact_messages를 직접 호출할 수 있어요.

텍스트 단계 (Text phases)

지원하는 모델은 각 어시스턴트 메시지에 phase를 붙여요. commentary는 모델이 작업하면서 쓰는 머리말, final_answer는 답 자체예요. Pydantic AI는 그것을 TextPart.provider_details'phase'로 표면화하고, 필드를 받는 것으로 알려진 모델에서는 다음 요청에도 다시 보내 턴 간 구분을 유지해요.

스트리밍 시, phase는 각 텍스트 부분(첫 콘텐츠 청크 포함)을 여는 PartStartEvent에 설정돼요. 생성되는 대로 commentary와 최종 답을 다르게 라우팅할 수 있어요. 이를 위해 run_stream_events를 선호하세요. run_stream은 첫 텍스트 부분을 최종 출력으로 취급하는데, 머리말을 방출하는 모델에서는 보통 그것이 commentary예요.

from pydantic_ai import Agent, PartDeltaEvent, PartStartEvent, TextPart, TextPartDelta

agent = Agent('openai:gpt-5.5')


async def main():
    final_answer_indexes: set[int] = set()
    async with agent.run_stream_events('What is the capital of France?') as events:
        async for event in events:
            if isinstance(event, PartStartEvent):
                # 인덱스는 단일 모델 응답에 범위가 지정되고 다음 것에서 다시 시작되므로,
                # 인덱스의 새 부분이 그 전 것보다 우선한다.
                final_answer_indexes.discard(event.index)
                if isinstance(event.part, TextPart):
                    phase = (event.part.provider_details or {}).get('phase')
                    if phase == 'final_answer':
                        final_answer_indexes.add(event.index)
                        print(event.part.content)
            elif isinstance(event, PartDeltaEvent) and isinstance(event.delta, TextPartDelta):
                if event.index in final_answer_indexes:
                    print(event.delta.content_delta)

(이 예제를 실행하려면 asyncio가 import되고 asyncio.run(main())이 추가됐는지 확인하세요. 다른 변경은 필요 없어요.)

'phase' 키는 모델이 출력에 라벨을 붙일 때마다 provider_details에 나타나지만, OpenAIModelProfile.openai_supports_phase가 받는 것으로 표시한 모델에서만 다시 보내져요. 그 밖의 모든 모델에서는 라벨이 표면화되고 후속 요청에서 버려져요.

백그라운드 모드 (Background mode)

큰 reasoning이나 도구가 많은 작업처럼 동기 요청의 실질적 지속 시간을 초과할 수 있는 장기 실행 요청을 위해 OpenAI Responses API는 백그라운드 모드를 제공해요. 서버 측에서 요청을 실행하고 준비되면 결과를 검색하게 해요. openai_background로 켜요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel, OpenAIResponsesModelSettings

model = OpenAIResponsesModel('gpt-5.2')
settings = OpenAIResponsesModelSettings(openai_background=True)
agent = Agent(model, model_settings=settings)
...

응답이 여전히 대기 중('queued''in_progress')으로 돌아오면 Pydantic AI가 투명하게 완료로 계속하므로 아무것도 할 필요가 없어요. 이것은 agent.runagent.run_stream 모두에서 작동하고, 결과는 단일 ModelResponse로 이어진돼요. 스트리밍 시 생성되는 대로 실시간 토큰 활동이 표면화되고 하나의 연속 스트림으로 도착해요.

요청이 서버 측에서 대기열에 있으므로 첫 토큰까지의 시간이 동기 요청보다 높아요. 백그라운드 응답이 여전히 대기 중이면 Pydantic AI가 고정 간격으로 완료를 폴링해요.

참고 — 실행이 요청 중간에 일시 중단되고(최종 ModelResponse.state'suspended') 메시지 히스토리에 영속되면, 그 히스토리를 다시 넘기면 새 것을 시작하는 대신 같은 백그라운드 응답을 재개해요. 프로바이더 보존 창 이후 재개하면 SuspendedResponseExpired가 발생해요. 실행을 버리거나 취소하면 서버 측 백그라운드 작업이 취소돼요.

Chat Completions API

기본 Responses API 대신 Chat Completions API가 필요하면 'openai-chat:' 접두사나 OpenAIChatModel로 고정하세요:

from pydantic_ai import Agent

agent = Agent('openai-chat:gpt-5.2')
...
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel

model = OpenAIChatModel('gpt-5.2')
agent = Agent(model)
...

다섯 개 ModelSettings 필드 — seed, presence_penalty, frequency_penalty, logit_bias, stop_sequences — 가 이 API를 통해서만 OpenAI에 닿아요. Responses API는 그것들 중 어느 것도 받지 않으므로 기본 openai: 경로에서는 버려져요.

OpenAIChatModel은 아래 모든 OpenAI 호환 프로바이더를 뒷받침하는 것이기도 해요. 모두 Chat Completions 와이어 형식을 말하므로 같은 모델 클래스가 적용돼요.

OpenAI 호환 모델 (OpenAI-compatible Models)

많은 프로바이더와 모델이 OpenAI API와 호환되며 Pydantic AI에서 OpenAIChatModel로 사용할 수 있어요. 시작 전에 위 설치·구성 지침을 확인하세요.

호출하는 서비스의 프로바이더 클래스가 있으면 그것을 사용하세요. 예: OpenRouterProvider, LiteLLM 프록시LiteLLMProvider, 로컬·원격 vLLM 서버VLLMProvider. 이 프로바이더들은 인증을 구성하고 서비스의 모델 이름·API 동작을 고려한 모델 프로파일을 선택해요. Agent("<provider>:<model>") 약어(예: Agent("openrouter:openai/gpt-5.6-sol"))를 쓰거나 OpenAIChatModel(provider=...)에 프로바이더 이름을 전달할 수도 있어요.

서비스에 전용 프로바이더가 없으면 커스텀 base_urlapi_keyOpenAIProvider를 쓰거나, OPENAI_BASE_URLOPENAI_API_KEY 환경 변수를 사용할 수 있어요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.openai import OpenAIProvider

model = OpenAIChatModel(
    'model_name',
    provider=OpenAIProvider(
        base_url='https://<openai-compatible-api-endpoint>', api_key='your-api-key'
    ),
)
agent = Agent(model)
...

모델 프로파일 (Model Profile)

가끔 사용하는 프로바이더나 모델이 OpenAI API·모델과 약간 다른 요구 사항을 가질 수 있어요. 예를 들어 도구 정의의 JSON 스키마에 다른 제한이 있거나, 도구 정의를 strict로 표시하는 것을 지원하지 않을 수 있어요.

Pydantic AI가 제공하는 대체 프로바이더 클래스를 사용할 때는 보통 모델 이름에 기반해 적절한 모델 프로파일이 자동 선택돼요. 커스텀 엔드포인트에서는 프로파일 선택과 요청 번역이 일치해야 해요. reasoning을 지원하는 모델이 그 API가 OpenAI의 reasoning_effort 값을 받는 것을 의미하지는 않아요. 사용 중인 모델이 기본으로 올바르게 작동하지 않으면, 자신의 ModelProfile(모든 모델 클래스 간 공유 동작)이나 OpenAIModelProfile(OpenAIChatModel 특정 동작)을 제공해 모델 요청 구성의 여러 측면을 조정할 수 있어요:

from pydantic_ai import Agent, InlineDefsJsonSchemaTransformer
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.profiles.openai import OpenAIModelProfile
from pydantic_ai.providers.openai import OpenAIProvider

model = OpenAIChatModel(
    'model_name',
    provider=OpenAIProvider(
        base_url='https://<openai-compatible-api-endpoint>.com', api_key='your-api-key'
    ),
    profile=OpenAIModelProfile(
        json_schema_transformer=InlineDefsJsonSchemaTransformer,  # 베이스 ModelProfile로 모든 모델 클래스 지원
        openai_supports_strict_tool_definition=False,  # OpenAIChatModel과 OpenAIResponsesModel 지원
        openai_chat_supports_multiple_system_messages=False,  # OpenAIChatModel만 -- 정확히 하나의 초기 시스템 메시지를 요구하는 엄격한 프로바이더(일부 vLLM/LiteLLM 설정)용
        openai_chat_supports_max_completion_tokens=False,  # OpenAIChatModel만 -- `max_completion_tokens` 대신 이전 `max_tokens` 필드만 받는 프로바이더(OpenRouter 등)용
    )
)
agent = Agent(model)
게이트웨이용 커스텀 프로바이더 (Custom providers for gateways)

게이트웨이가 여러 프로바이더로 요청을 라우팅하면 OpenAIProvider를 서브클래싱하고 model_profile()을 재정의해 그 모델 ID를 해석하세요. 이것은 그 프로바이더를 사용하는 모든 모델에 프로파일을 선택하므로 각 모델에 profile=을 넘길 필요가 없어요. 프로파일 조회용으로만 이름을 정규화하세요. 게이트웨이에 보내는 모델 ID는 그대로 유지돼요.

내장 프로바이더처럼 pydantic_ai.profiles의 헬퍼를 사용해 기반 모델의 프로파일을 선택한 뒤 게이트웨이별 재정의를 적용하세요. 예를 들어 이 게이트웨이는 OpenRouter 경로에 openrouter/<provider>/<model>을, 다른 경로에 <provider>/<model>을 사용해요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.profiles import ModelProfile, merge_profile
from pydantic_ai.profiles.groq import groq_model_profile
from pydantic_ai.profiles.moonshotai import moonshotai_model_profile
from pydantic_ai.profiles.openai import (
    OpenAIJsonSchemaTransformer,
    OpenAIModelProfile,
    openai_model_profile,
)
from pydantic_ai.providers.openai import OpenAIProvider


class GatewayProvider(OpenAIProvider):
    @property
    def name(self) -> str:
        return 'my-gateway'

    @staticmethod
    def model_profile(model_name: str) -> ModelProfile:
        provider_to_profile = {
            'openai': openai_model_profile,
            'groq': groq_model_profile,
            'moonshotai': moonshotai_model_profile,
        }
        provider_name, _, model_name = model_name.removeprefix('openrouter/').partition('/')
        profile = None
        if profile_func := provider_to_profile.get(provider_name):
            profile = profile_func(model_name)
        return merge_profile(
            OpenAIModelProfile(json_schema_transformer=OpenAIJsonSchemaTransformer),
            profile,
        )


provider = GatewayProvider(
    base_url='https://gateway.example/v1',
    api_key='your-gateway-api-key',
)
model = OpenAIChatModel('openrouter/openai/gpt-5.6-sol', provider=provider)
agent = Agent(model)

게이트웨이가 서빙하는 모델·별칭에 맞게 매핑과 정규화 규칙을 확장하세요. OpenAI JSON 스키마 트랜스포머는 폴백이고, 모델군 헬퍼가 자체 트랜스포머를 공급할 수 있어요. 반환된 프로파일은 OpenAIProvider의 프로파일 선택을 대체하고, Pydantic AI가 DEFAULT_PROFILE과 자동 병합해요. 게이트웨이별 재정의를 merge_profile()의 마지막 인자로, 모델군 프로파일 뒤에 추가하세요.

프로파일 선택은 모델 클래스를 바꾸지 않아요. OpenAIChatModel은 여전히 OpenAI Chat Completions 요청을 구성해요. 게이트웨이가 받는 것에 따라 capability 플래그를 설정하세요. 모델군 헬퍼는 그 요청 번역이나 API 제한을 고려할 수 없어요.

불완전한 스트리밍 응답 탐지 (Detect incomplete streamed responses)

일부 OpenAI 호환 API는 종료 finish_reason 없이 Chat Completions 스트림을 깨끗하게 닫아 부분 응답이 완전해 보이게 할 수 있어요. 프로바이더가 완전한 스트림이 finish reason을 포함한다고 보장하면 모델 프로파일에서 openai_chat_streaming_requires_finish_reason=True을 설정하세요. 그러면 스트림이 finish reason 없이 EOF에 도달하면 Pydantic AI가 ModelAPIError를 발생시켜요. 옵션은 기본 False인데, 일부 호환 API가 그 필드를 보장하지 않기 때문이에요.

선행 시스템 메시지를 하나만 받는 모델 (Models that accept only one leading system message)

일부 모델은 (서버 측에서 적용되는, 예: vLLM, LiteLLM, TGI의) 채팅 템플릿으로 서빙되는데, 대화 시작에서 단일 시스템 메시지만 받고 추가 메시지를 거부해요. 하나 이상 보내면 System message must be at the beginning.이나 Conversation roles must alternate ... 같은 400 오류로 실패하는데, 일부 최신 Qwen, Mistral, Gemma, Command-R 모델에서 보여요. 선행 시스템 메시지가 여러 방식으로 만들어질 수 있으므로 의도하지 않고도 쉽게 맞닥뜨려요.

(위와 같이) 모델의 OpenAIModelProfileopenai_chat_supports_multiple_system_messages=False를 설정해 요청을 보내기 전에 선행 시스템 메시지 실행부를 두 개의 새 줄로 이어 붙인 하나로 병합하세요. 병합은 무손실이므로 백엔드가 여러 시스템 메시지를 거부할 때마다 켜도 안전해요.

DeepSeek

DeepSeek 프로바이더를 사용하려면 Quick Start 가이드에 따라 먼저 API 키를 만드세요.

그 다음 DEEPSEEK_API_KEY 환경 변수를 설정하고 DeepSeekProvider를 이름으로 사용하세요:

from pydantic_ai import Agent

agent = Agent('deepseek:deepseek-v4-flash')
...

또는 모델과 프로바이더를 직접 초기화하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.deepseek import DeepSeekProvider

model = OpenAIChatModel(
    'deepseek-v4-flash',
    provider=DeepSeekProvider(api_key='your-deepseek-api-key'),
)
agent = Agent(model)
...

커스텀 http_client로 프로바이더를 커스터마이즈할 수도 있어요:

from httpx2 import AsyncClient

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.deepseek import DeepSeekProvider

custom_http_client = AsyncClient(timeout=30)
model = OpenAIChatModel(
    'deepseek-v4-flash',
    provider=DeepSeekProvider(
        api_key='your-deepseek-api-key', http_client=custom_http_client
    ),
)
agent = Agent(model)
...

OpenAI 호환 프로바이더는 Pydantic AI v2 동안 레거시 httpx.AsyncClient도 받지만 deprecation 경고를 방출해요. 새 코드는 httpx2.AsyncClient를 사용하세요. 레거시 HTTPX 클라이언트 지원은 Pydantic AI v3에서 제거될 거예요.

DeepSeek의 V4 모델은 기본으로 생각하고, DeepSeek는 thinking이 켜진 동안 강제 도구 선택을 거부하며 Thinking mode does not support this tool_choice라고 답해요. 그래서 Pydantic AI는 그 요청에 tool_choice='auto'를 보내고, 모델이 출력 도구를 호출하는 대신 산문으로 답하게 해요. deepseek-v4-pro에서는 그게 재시도 예산을 소진할 만큼 자주 재시도를 쓰게 해요. 구조적 출력이 신뢰할 만해야 하면 thinking을 끄고, 그러면 강제가 다시 사용돼요:

from pydantic import BaseModel

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel, OpenAIChatModelSettings


class Answer(BaseModel):
    text: str


agent = Agent(
    OpenAIChatModel('deepseek-v4-pro', provider='deepseek'),
    output_type=Answer,
    model_settings=OpenAIChatModelSettings(thinking=False),
)
...

thinking이 켜진 동안 tool_choice='required'를 명시적으로 전달하면 API에서 실패하는 대신 UserError가 발생해요.

위에 보인 Chat Completions API의 대안으로, DeepSeek는 두 V4 모델 모두에 OpenAI 호환 Responses API도 서빙해요. OpenAIResponsesModelDeepSeekProvider와 짝지어 사용하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel
from pydantic_ai.providers.deepseek import DeepSeekProvider

model = OpenAIResponsesModel(
    'deepseek-v4-flash',
    provider=DeepSeekProvider(api_key='your-deepseek-api-key'),
)
agent = Agent(model)
...

DeepSeek는 Responses API의 어떤 부분을 구현하는지 문서화하고, 지원되지 않는 필드는 거부되는 대신 조용히 무시돼요. 그래서 무엇이 아무것도 하지 않는지 아는 것이 중요해요:

  • API는 상태가 없으므로 openai_conversation_id, 백그라운드 모드, 메시지 압축은 사용할 수 없어요. 대신 각 실행에 메시지 히스토리를 다시 전달하세요.
  • openai_previous_response_id는 미설정으로 두세요. 설정하면 Pydantic AI가 서버가 이미 보유한다고 가정하는 이전 턴을 버리고, DeepSeek는 아무것도 저장하지 않으므로, 모델이 오류 없이 조용히 대화를 잃어요.
  • 네이티브 도구 중 DeepSeek는 WebSearchTool만 실행해요. 나머지는 오류를 보고하지 않고 무시해요.
  • 이미지·문서 입력은 거부되는 대신 자리 표시자 텍스트로 대체돼요.
  • reasoning은 openai_reasoning_effort(또는 통합 thinking 설정)로 구성돼요. openai_reasoning_summary는 받아지지만 요약을 만들지 않아요.
  • NativeOutput는 여기서는 사용할 수 있지만 Chat Completions에서는 안 돼요. DeepSeek는 Responses API에서 엄격한 JSON Schema를 존중하지만, Chat Completions 엔드포인트는 This response_format type is unavailable now로 그것을 거부해요.

Pydantic AI가 대신 처리하는 한 가지 차이: DeepSeek는 각 함수 호출을 인접한 어시스턴스 메시지에 병합해요. thinking이나 텍스트와 호출을 섞는 턴을 재생하면 답 없는 호출이 있는 별개 메시지가 만들어져, DeepSeek가 No tool output found for tool call ...으로 거부해요. Pydantic AI는 요청을 만들 때 호출을 다른 항목 뒤로 옮겨요. 이것은 요청만 재정렬하지, 당신의 메시지 히스토리는 그대로예요.

재정렬은 모든 함수 호출에 결과가 있고 턴이 프로바이더 소유 네이티브 도구나 압축 항목을 포함하지 않을 때만 적용돼요. DeepSeek는 어떤 순서든 해결 안 된 호출을 거부하고, 프로바이더 소유 항목은 그대로 둬요. 다른 엔드포인트에서 DeepSeek의 Responses 형태를 서빙하거나 재정렬을 끄려면 자신의 프로파일에 OpenAIModelProfile.openai_responses_supports_interleaved_function_calls을 설정하세요.

Alibaba Cloud Model Studio (DashScope)

Alibaba Cloud Model Studio (DashScope)로 Qwen 모델을 사용하려면 ALIBABA_API_KEY(또는 DASHSCOPE_API_KEY) 환경 변수를 설정하고 AlibabaProvider를 이름으로 사용하세요:

from pydantic_ai import Agent

agent = Agent('alibaba:qwen-max')
...

또는 모델과 프로바이더를 직접 초기화하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.alibaba import AlibabaProvider

model = OpenAIChatModel(
    'qwen-max',
    provider=AlibabaProvider(api_key='your-api-key'),
)
agent = Agent(model)
...

AlibabaProvider는 기본적으로 국제 DashScope 호환 엔드포인트 https://dashscope-intl.aliyuncs.com/compatible-mode/v1을 사용해요. 커스텀 base_url을 전달해 이를 재정의할 수 있어요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.alibaba import AlibabaProvider

model = OpenAIChatModel(
    'qwen-max',
    provider=AlibabaProvider(
        api_key='your-api-key',
        base_url='https://dashscope.aliyuncs.com/compatible-mode/v1',  # 중국 리전
    ),
)
agent = Agent(model)
...

문서 입력 미지원 — DashScope 호환 모드 Chat Completions API는 문서 콘텐츠 부분을 받지 않으므로, AlibabaProvider에 의해 뒷받침되는 OpenAIChatModelDocumentUrl이나 문서 BinaryContent를 전달하면 UserError가 발생해요.

Ollama

전용 Ollama 문서(구조적 출력·Ollama Cloud 한도 포함)는 Ollama를 참고하세요.

Azure AI Foundry

Azure AI Foundry를 프로바이더로 사용하려면 AZURE_OPENAI_ENDPOINT을 경로가 /v1로 끝나는 URL(예: https://<resource>.openai.azure.com/openai/v1/ 또는 https://<resource>.services.ai.azure.com/openai/v1/)로 설정하고 AZURE_OPENAI_API_KEY를 설정한 뒤 AzureProvider를 이름으로 사용하세요:

from pydantic_ai import Agent

agent = Agent('azure:gpt-5.2')
...

또는 모델과 프로바이더를 직접 초기화하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.azure import AzureProvider

model = OpenAIChatModel(
    'gpt-5.2',
    provider=AzureProvider(
        azure_endpoint='https://your-resource.openai.azure.com/openai/v1/',
        api_key='your-api-key',
    ),
)
agent = Agent(model)
...

이것은 Microsoft가 모든 새 프로젝트에 권장하는 Azure OpenAI v1 API를 대상으로 해요. 또한 Responses API와 자연스럽게 짝을 이루며, 아래 Azure와 Responses API 사용을 참고하세요.

AzureProviderhttps://<model>.<region>.models.ai.azure.comAzure AI Foundry 서버리스 모델 배포도 인식해 같은 방식으로 연결해요.

기존 api-version 기반 배포에 연결 (Connecting to an existing api-version-based deployment)

리소스가 여전히 날짜가 붙은 api-version API를 사용하면 api_version을 전달하고(또는 OPENAI_API_VERSION 환경 변수 설정) azure_endpoint를 리소스 루트에 지정하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.azure import AzureProvider

model = OpenAIChatModel(
    'gpt-5.2',
    provider=AzureProvider(
        azure_endpoint='https://your-resource.openai.azure.com/',
        api_version='2024-12-01-preview',
        api_key='your-api-key',
    ),
)
agent = Agent(model)
...
Azure와 Responses API 사용 (Using Azure with the Responses API)

Azure AI Foundry는 OpenAIResponsesModel을 통해 OpenAI Responses API도 지원해요. Azure의 Chat Completions API가 문서 입력(DocumentUrlBinaryContent)을 지원하지 않으므로 문서 입력 작업 시 특히 권장돼요.

azure-responses: 접두사로 Responses API를 이름으로 선택하세요(azure: 접두사는 Chat Completions API를 사용):

from pydantic_ai import Agent

agent = Agent('azure-responses:gpt-5.2')
...

참고 — Azure의 Responses API는 OpenAI Responses API의 모든 기능을 아직 지원하지 않아요. 예를 들어 네이티브 웹 검색은 사용할 수 없고, 이미지 편집·파일 업로드에 한도가 있어요. 현재 목록은 Microsoft의 Responses API 문서를 참고하세요. azure-responses: 약어를 쓰든 AzureProviderOpenAIResponsesModel을 직접 구성하든 동일하게 적용돼요.

또는 모델과 프로바이더를 직접 초기화하세요 — Responses API로 Azure를 사용한 문서 처리:

from pydantic_ai import Agent, BinaryContent
from pydantic_ai.models.openai import OpenAIResponsesModel
from pydantic_ai.providers.azure import AzureProvider

pdf_bytes = b'%PDF-1.4 ...'  # 당신의 PDF 콘텐츠

model = OpenAIResponsesModel(
    'gpt-5.2',
    provider=AzureProvider(
        azure_endpoint='https://your-resource.openai.azure.com/openai/v1/',
        api_key='your-api-key',
    ),
)
agent = Agent(model)
result = agent.run_sync([
    'Summarize this document',
    BinaryContent(data=pdf_bytes, media_type='application/pdf'),
])

Vercel AI Gateway

Vercel의 AI Gateway를 사용하려면 먼저 문서의 API 키나 OIDC 토큰 획득 지침을 따르세요.

VERCEL_AI_GATEWAY_API_KEYVERCEL_OIDC_TOKEN 환경 변수를 설정하고 VercelProvider를 이름으로 사용하세요:

from pydantic_ai import Agent

agent = Agent('vercel:anthropic/claude-sonnet-4-5')
...

또는 모델과 프로바이더를 직접 초기화하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.vercel import VercelProvider

model = OpenAIChatModel(
    'anthropic/claude-sonnet-4-5',
    provider=VercelProvider(api_key='your-vercel-ai-gateway-api-key'),
)
agent = Agent(model)
...

MoonshotAI

Moonshot Console에서 API 키를 만드세요.

MOONSHOTAI_API_KEY 환경 변수를 설정하고 MoonshotAIProvider를 이름으로 사용하세요:

from pydantic_ai import Agent

agent = Agent('moonshotai:kimi-k2-0711-preview')
...

또는 모델과 프로바이더를 직접 초기화하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.moonshotai import MoonshotAIProvider

model = OpenAIChatModel(
    'kimi-k2-0711-preview',
    provider=MoonshotAIProvider(api_key='your-moonshot-api-key'),
)
agent = Agent(model)
...

GitHub Models

GitHub Models 폐지됨 — GitHub Models는 2026년 7월 30일에 폐지됐어요. 플레이그라운드, 모델 카탈로그, 추론 API는 더 이상 사용할 수 없어요. 따라서 GitHubProvider는 deprecated이며 v3에서 제거될 거예요. 모델 접근은 앞으로 Azure AI FoundryGitHub Copilot을 권장하며, Pydantic AI는 GitHubCopilotModel으로 지원해요.

Perplexity

Perplexity 시작 안내를 따라 API 키를 만든 뒤 모델과 프로바이더를 직접 초기화하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.openai import OpenAIProvider

model = OpenAIChatModel(
    'sonar-pro',
    provider=OpenAIProvider(
        base_url='https://api.perplexity.ai',
        api_key='your-perplexity-api-key',
    ),
)
agent = Agent(model)
...

Fireworks AI

Fireworks.AI에 가서 계정 설정에서 API 키를 만드세요.

FIREWORKS_API_KEY 환경 변수를 설정하고 FireworksProvider를 이름으로 사용하세요:

from pydantic_ai import Agent

agent = Agent('fireworks:accounts/fireworks/models/qwq-32b')
...

또는 모델과 프로바이더를 직접 초기화하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.fireworks import FireworksProvider

model = OpenAIChatModel(
    'accounts/fireworks/models/qwq-32b',  # 모델 라이브러리: https://fireworks.ai/models
    provider=FireworksProvider(api_key='your-fireworks-api-key'),
)
agent = Agent(model)
...

Together AI

Together.ai에 가서 계정 설정에서 API 키를 만드세요.

TOGETHER_API_KEY 환경 변수를 설정하고 TogetherProvider를 이름으로 사용하세요:

from pydantic_ai import Agent

agent = Agent('together:meta-llama/Llama-3.3-70B-Instruct-Turbo-Free')
...

또는 모델과 프로바이더를 직접 초기화하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.together import TogetherProvider

model = OpenAIChatModel(
    'meta-llama/Llama-3.3-70B-Instruct-Turbo-Free',  # 모델 라이브러리: https://www.together.ai/models
    provider=TogetherProvider(api_key='your-together-api-key'),
)
agent = Agent(model)
...

deepseek-ai/DeepSeek-V4-* 모델은 thinking이 켜진 동안 강제 도구 선택을 거부하고, thinking이 기본이에요. 그래서 Pydantic AI는 Together에서 그 모델에 대해 도구 선택을 절대 강제하지 않아요. 명시적 tool_choice='required'나 도구 목록은 UserError를 발생시키고, 해결된 출력 도구 강제는 tool_choice='auto'로 보내져요. DeepSeekProvider와 달리, Together가 DeepSeek의 thinking 토글을 존중하는지는 검증되지 않았으므로 그 제한은 무조건이에요.

Heroku AI

Heroku AI를 사용하려면 먼저 API 키를 만드세요.

HEROKU_INFERENCE_KEY와 (선택) HEROKU_INFERENCE_URL 환경 변수를 설정하고 HerokuProvider를 이름으로 사용하세요:

from pydantic_ai import Agent

agent = Agent('heroku:claude-sonnet-4-5')
...

또는 모델과 프로바이더를 직접 초기화하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.heroku import HerokuProvider

model = OpenAIChatModel(
    'claude-sonnet-4-5',
    provider=HerokuProvider(api_key='your-heroku-inference-key'),
)
agent = Agent(model)
...

LiteLLM

LiteLLM을 사용하려면 문서에 요약된 대로 configs를 설정하세요. LiteLLMProvider에서 api_baseapi_key를 전달할 수 있어요. 이 configs의 값은 설정에 따라 달라져요. 예를 들어 OpenAI 모델을 쓰면 https://api.openai.com/v1api_base로, OpenAI API 키를 api_key로 전달해야 해요. 로컬 머신에서 LiteLLM 프록시 서버를 쓰면 http://localhost:<port>api_base로, LiteLLM API 키(또는 자리 표시자)를 api_key로 전달해야 해요.

커스텀 LLM을 사용하려면 모델 이름에 custom/ 접두사를 사용하세요.

configs가 있으면 LiteLLMProvider를 다음과 같이 사용하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.litellm import LiteLLMProvider

model = OpenAIChatModel(
    'openai/gpt-5.2',
    provider=LiteLLMProvider(
        api_base='<api-base-url>',
        api_key='<api-key>'
    )
)
agent = Agent(model)

result = agent.run_sync('What is the capital of France?')
print(result.output)
...

참고 — 모델이 선행 시스템 메시지가 둘 이상인 요청을 거부하면(예: System message must be at the beginning.), 그 프로파일에 openai_chat_supports_multiple_system_messages=False를 설정하세요. 자세한 내용은 선행 시스템 메시지를 하나만 받는 모델을 참고하세요.

vLLM

vLLM은 OpenAI 호환 API를 가진 고처리량 추론 서버예요. VLLMProvider로 연결하고, base_url을 직접 또는 VLLM_BASE_URL로 설정하세요. 인증된 서버에서는 api_keyVLLM_API_KEY를 설정하세요.

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.vllm import VLLMProvider

model = OpenAIChatModel(
    'Qwen/Qwen3.8-27B',
    provider=VLLMProvider(base_url='http://localhost:8000/v1'),
)
agent = Agent(model)

result = agent.run_sync('What is the capital of France?')
print(result.output)

그 환경 변수들이 설정되어 있으면 프로바이더를 이름으로 참조할 수도 있어요:

from pydantic_ai import Agent

agent = Agent('vllm:Qwen/Qwen3.8-27B')

result = agent.run_sync('What is the capital of France?')
print(result.output)

도구 호출에는 서버 구성 필요 — 모델이 도구를 호출할지 결정하게 하는 에이전트에서는 --enable-auto-tool-choice로 vLLM을 시작하고 --tool-call-parser로 모델별 파서를 선택하세요. 지원 모델·파서 값은 vLLM 도구 호출 가이드를 참고하세요.

여러 시스템 메시지는 기본으로 병합 — 일부 vLLM 채팅 템플릿은 여러 선행 시스템 메시지를 거부하므로 VLLMProvider는 기본으로 그것들을 병합해요. 탈퇴하려면 openai_chat_supports_multiple_system_messages=TrueOpenAIModelProfile을 전달하세요. 선행 시스템 메시지를 하나만 받는 모델 참고.

Nebius AI Studio

Nebius AI Studio에 가서 API 키를 만드세요.

NEBIUS_API_KEY 환경 변수를 설정하고 NebiusProvider를 이름으로 사용하세요:

from pydantic_ai import Agent

agent = Agent('nebius:Qwen/Qwen3-32B-fast')
result = agent.run_sync('What is the capital of France?')
print(result.output)

또는 모델과 프로바이더를 직접 초기화하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.nebius import NebiusProvider

model = OpenAIChatModel(
    'Qwen/Qwen3-32B-fast',
    provider=NebiusProvider(api_key='your-nebius-api-key'),
)
agent = Agent(model)
result = agent.run_sync('What is the capital of France?')
print(result.output)

OVHcloud AI Endpoints

OVHcloud AI Endpoints를 사용하려면 새 API 키를 만들어야 해요. OVHcloud 매니저의 Public Cloud > AI Endpoints > API keys로 가서 Create a new API key를 클릭하고 새 키를 복사하세요.

카탈로그에서 어떤 모델이 가능한지 탐색할 수 있어요.

OVHCLOUD_API_KEY 환경 변수를 설정하고 OVHcloudProvider를 이름으로 사용하세요:

from pydantic_ai import Agent

agent = Agent('ovhcloud:gpt-oss-120b')
result = agent.run_sync('What is the capital of France?')
print(result.output)

프로바이더를 구성해야 하면 OVHcloudProvider 클래스를 사용할 수 있어요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.ovhcloud import OVHcloudProvider

model = OpenAIChatModel(
    'gpt-oss-120b',
    provider=OVHcloudProvider(api_key='your-api-key'),
)
agent = Agent(model)
result = agent.run_sync('What is the capital of France?')
print(result.output)

SambaNova

SambaNova Cloud를 사용하려면 SambaNova Cloud 대시보드에서 API 키를 얻으세요.

SambaNova는 Meta Llama, DeepSeek, Qwen, Mistral 모델을 포함한 여러 모델군에 빠른 추론 속도로 접근을 제공해요.

SAMBANOVA_API_KEY 환경 변수를 설정하고 SambaNovaProvider를 이름으로 사용하세요:

from pydantic_ai import Agent

agent = Agent('sambanova:Meta-Llama-3.1-8B-Instruct')
result = agent.run_sync('What is the capital of France?')
print(result.output)

또는 모델과 프로바이더를 직접 초기화하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.sambanova import SambaNovaProvider

model = OpenAIChatModel(
    'Meta-Llama-3.1-8B-Instruct',
    provider=SambaNovaProvider(api_key='your-api-key'),
)
agent = Agent(model)
result = agent.run_sync('What is the capital of France?')
print(result.output)

가용 모델의 전체 목록은 SambaNova 지원 모델 문서를 참고하세요.

필요하면 base URL을 커스터마이즈할 수 있어요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.sambanova import SambaNovaProvider

model = OpenAIChatModel(
    'DeepSeek-R1-0528',
    provider=SambaNovaProvider(
        api_key='your-api-key',
        base_url='https://custom.endpoint.com/v1',
    ),
)
agent = Agent(model)
...

Atlas Cloud

Atlas Cloud는 DeepSeek, Qwen, Claude, GPT, Gemini를 포함한 300+ 모델에 단일 엔드포인트로 접근을 제공하는 OpenAI 호환 API 게이트웨이예요.

Atlas Cloud는 전용 프로바이더 클래스가 없으므로 base_urlapi_key를 설정해 OpenAIProvider로 사용할 수 있어요. non-OpenAI 모델 ID에는 모델 프로파일이나 커스텀 프로바이더를 모델·게이트웨이 동작에 맞게 구성하세요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.openai import OpenAIProvider

model = OpenAIChatModel(
    'deepseek-ai/deepseek-v4-pro',
    provider=OpenAIProvider(
        base_url='https://api.atlascloud.ai/v1',
        api_key='your-atlas-cloud-api-key',
    ),
)
agent = Agent(model)
...

Rapid-MLX (Apple Silicon)

Rapid-MLX는 Apple의 MLX 프레임워크 위에 구축된 Apple Silicon용 OpenAI 호환 추론 서버예요.

pip install rapid-mlx
rapid-mlx serve mlx-community/Qwen3.5-4B-MLX-4bit

서버는 http://localhost:8000/v1에서 듣고 OpenAI 채팅 완성 API를 구현하므로 OpenAIProvider를 가리킬 수 있어요:

from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.openai import OpenAIProvider

rapid_mlx_model = OpenAIChatModel(
    model_name='default',
    provider=OpenAIProvider(
        base_url='http://localhost:8000/v1',
        api_key='not-needed',
    ),
)
agent = Agent(rapid_mlx_model)

더 알아보기 (Learn more)