OpenAI
OpenAI
PydanticAI에서 가장 기본이 되는 모델 통합이에요. OpenAI 공식 모델은 물론이고, OpenAI API와 호환되는 다른 제공자들의 API까지도 같은 방식으로 붙일 수 있죠. 우선 설치 방법부터, 이름으로 모델을 쓰는 방법, 그리고 유용하게 쓸 수 있는 세부 설정들을 차례대로 살펴볼게요.
출처: 공식문서
설치
OpenAI 모델이나 OpenAI 호환 API를 쓰려면 pydantic-ai를 설치하거나, pydantic-ai-slim을 openai 옵션 그룹과 함께 설치해야 해요.
Terminal
pip install "pydantic-ai-slim[openai]"
Terminal
uv add "pydantic-ai-slim[openai]"
설정
OpenAI API로 모델을 쓰려면 platform.openai.com에서 API 키를 만들면 돼요.
TIP: API 키 대신 ChatGPT/Codex 구독을 쓸 수도 있어요. openai-codex: 프리픽스는 공식 Codex CLI와 같은 OAuth 흐름으로 Codex 백엔드에 인증하거든요.
환경 변수
API 키를 받았으면 환경 변수로 설정해요.
Terminal
export OPENAI_API_KEY='your-api-key'
그냥 'openai:' 프리픽스를 쓰면 최신 Responses API를 쓰는 OpenAIResponsesModel로 연결돼요.
from pydantic_ai import Agent
agent = Agent('openai:gpt-5.6-sol')
...
대신 예전 Chat Completions API로 고정하고 싶다면 'openai-chat:' 프리픽스를 쓰면 되고, 이건 OpenAIChatModel로 연결돼요.
아니면 모델 이름만으로 직접 초기화할 수도 있어요.
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIResponsesModel
model = OpenAIResponsesModel('gpt-5.6-sol')
agent = Agent(model)
...
기본적으로 이 모델은 base_url이 https://api.openai.com/v1로 설정된 OpenAIProvider를 사용해요.
Provider 설정하기
코드에서 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 클라이언트
OpenAIProvider는 openai_client 파라미터로 커스텀 AsyncOpenAI 클라이언트도 받아요. OpenAI API 문서에 정의된 organization, project, base_url 등을 원하는 대로 바꿀 수 있죠.
이 클라이언트는 에이전트의 재시도 예산과 별개로 실패한 요청을 자체적으로 재시도해요. 기본값이 max_retries=2라서 하나의 모델 요청이 네트워크까지 최대 세 번 도달할 수 있어요. x-should-retry 응답 헤더를 존중하고, 그 헤더가 없으면 408, 409, 429 또는 5xx 상태와 타임아웃·연결 에러를 재시도하지만, 400이나 401 같은 다른 4xx 응답은 재시도하지 않아요. 재시도 정책을 오직 transport에만 두고 싶다면 max_retries=0으로 설정하면 돼요. 레이어가 어떻게 겹치는지는 Retry multiplication 문서에서 확인할 수 있어요.
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)
...
Azure OpenAI API를 쓰려면 AsyncAzureOpenAI 클라이언트를 쓰면 돼요. 참고로 AsyncAzureOpenAI는 AsyncOpenAI의 하위 클래스예요.
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)
...
이미지 생성
openai: 이미지 모델과 함께 ImageGenerator를 쓰면 직접 생성과 참조 이미지 편집이 가능해요. 이건 대화형 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는 참조 입력으로 BinaryImage와 ImageUrl를 받아요. 이미지 편집 엔드포인트는 파일 내용이 필요해서 UploadedFile provider 파일 ID는 받지 않아요. 투명 배경 지원은 모델마다 다르고 PNG나 WebP 출력이 필요해요. Provider별 설정은 OpenAI로 전달되기 때문에 새로 지원되는 값이 낡은 클라이언트 측 검사에 막히지 않아요. 생성·편집·지오메트리·정규화 설정은 image-generation 가이드에서 확인하세요.
GPT Image 모델은 유료 사용 등급에 검증된 조직이 필요해요. 검증되지 않은 조직에서는 모든 요청이 생성 전에 rate-limit 에러로 실패해요. 복잡한 프롬프트는 처리에 최대 2분까지 걸릴 수 있어요.
모델 설정
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)
...
서비스 티어
OpenAI는 service tier를 제어해서 지연 시간과 비용을 조절할 수 있게 해줘요. 통합된 service_tier 필드나 provider별 openai_service_tier 필드를 쓸 수 있는데, 둘 다 'auto', 'default', 'flex', 'priority'를 그대로 통과시켜요. 둘 다 설정되면 openai_service_tier가 우선해요.
프롬프트 캐싱
GPT-5.6 이후 모델(GPT-6 Astra 포함)은 Responses API와 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가 프롬프트 캐시 쓰기를 보고하면 PydanticAI는 이를 result.usage.cache_write_tokens로 노출해요. 캐시 읽기는 result.usage.cache_read_tokens로 볼 수 있어요. GPT-5.6 이후 모델군에서는 OpenAI가 캐시 쓰기를 캐시되지 않은 입력 토큰 단가의 1.25배로 청구해요.
심사 (Moderation)
Responses API와 Chat Completions API 모두 요청의 입력·출력에 moderation을 돌릴 수 있어요. 기본적으로 꺼져 있고, 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' 키에 저장돼요. input과 output 항목 각각이 플래그 상태, 카테고리별 플래그, 카테고리 점수를 담고 있어요.
OpenAIChatModel에서는 대신 OpenAIChatModelSettings를 써요. 결과는 비스트리밍·스트리밍 경로 모두 같은 방식으로 표면화되는데, 다만 Chat Completions API는 각 항목을 results 리스트 아래에 한 단계 더 깊이 중첩해요.
Responses API 기능
아래 기능들은 Responses API에 특화된 것으로 기본값 모델인 OpenAIResponsesModel에서만 쓸 수 있어요. Responses API가 Chat Completions와 어떻게 다른지에 대한 배경은 OpenAI API 문서를 보세요.
추론 모드
지원하는 모델(현재 GPT-5.6군과 GPT-6 Astra)은 OpenAI의 standard와 pro 추론 모드를 쓸 수 있어요. standard가 기본이고, pro는 어려운 작업에서 신뢰성을 높이기 위해 더 많은 모델 작업을 수행하지만 지연 시간과 토큰 사용량이 늘어나요. 모드는 추론 노력과 독립적이에요. 모드와 노력의 어떤 조합도 유효하고, 통합된 thinking 설정은 단지 노력에만 영향을 주기 때문에 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에 따라 추론 모드를 지원하지 않는 모델에서는 무시돼요.
추론 컨텍스트
추론 모델은 OpenAI의 reasoning context로 샘플링할 때 이전 턴의 어떤 추론 항목을 사용할 수 있게 할지 제어할 수 있어요. auto는 모델 자체의 기본값에 맡기고(OpenAI는 필드를 보내지 않는 것과 똑같이 취급해요), current_turn은 현재 턴의 추론만 사용 가능하게 하며, all_turns는 이전 턴의 호환 추론 항목을 다음 샘플에 렌더링해요. all_turns는 previous_response_id나 대화, 재생된 히스토리를 통해 이전 응답 항목에 접근해야 해요. 첫 요청에서는 current_turn처럼 동작해요.
PydanticAI는 지원하는 모델에서 기본적으로 all_turns를 보내요. 그래서 이전 턴 추론이 별도 설정 없이 계속 사용 가능해요. 다른 모델에 이전 thinking을 다시 보내는 것과 일관된 동작이죠. 이렇게 하면 각 후속 샘플에 이전 추론이 렌더링돼서 추가 입력 토큰이 들어요. 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)
...
auto와 current_turn은 추론을 지원하는 모든 모델에 보내져요. all_turns는 프로필이 OpenAIModelProfile.openai_responses_supports_reasoning_context를 설정한 모델(현재 GPT-5.4, GPT-5.5, GPT-5.6, GPT-6 Astra 군)에만 보내지고, 다른 모델에서는 무시돼요.
네이티브 도구
Responses API에는 직접 만들지 않아도 쓸 수 있는 네이티브 도구들이 있어요.
- 웹 검색: 응답 생성 전에 모델이 웹에서 최신 정보를 검색하게 해요.
- 코드 인터프리터: 모델이 샌드박스 환경에서 파이썬 코드를 작성·실행하게 해요.
- 이미지 생성: 모델이 텍스트 프롬프트로 이미지를 생성하게 해요.
- 파일 검색: 모델이 파일에서 관련 정보를 검색하게 해요.
- 컴퓨터 사용: 모델이 사용자를 대신해 컴퓨터로 작업을 수행하게 해요.
웹 검색, 코드 인터프리터, 이미지 생성, 파일 검색은 Native tools 기능으로 네이티브하게 지원돼요.
컴퓨터 사용은 OpenAIResponsesModelSettings의 openai_native_tools 설정에 openai.types.responses.ComputerToolParam을 넘기면 켤 수 있어요. 현재는 메시지 히스토리나 스트리밍 이벤트에서 NativeToolCallPart나 NativeToolReturnPart를 만들지 않아요. 이 네이티브 도구에 대한 네이티브 지원이 필요하면 이슈를 올려주세요.
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)
이전 응답 참조하기
Responses API는 previous_response_id 파라미터로 새 요청에서 이전 모델 응답을 참조할 수 있게 해줘요. 추론 항목을 포함한 전체 대화 상태를 다시 보내지 않고도 컨텍스트에 유지할 수 있죠. 이건 OpenAIResponsesModelSettings의 openai_previous_response_id 필드로 쓸 수 있어요.
이 필드가 'auto'로 설정되면 PydanticAI가 메시지 히스토리에서 가장 최근 provider_response_id를 자동으로 골라내고 그 이전 메시지들은 생략해요. 그러면 OpenAI가 서버 측 상태에서 그 메시지들을 재구성해요. 같은 체이닝이 한 번의 실행 안에서도 도구 호출 연속과 재시도에 걸쳐 적용되기 때문에 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)
#> Did you hear about the toothpaste scandal? They called it Colgate.
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)
#> This is an excellent joke invented by Samuel Colvin, it needs no explanation.
message_history를 넘기는 대안으로, 이전 실행의 구체적인 provider_response_id를 시드로 넘길 수도 있어요. PydanticAI는 새 실행의 첫 요청에 그 시드를 쓰고, 이후 실행 내 호출에서는 그 요청에 대해 반환된 응답으로 자동 체이닝해요. 그래서 실행에 도구 호출 연속이나 재시도가 포함돼도 체인은 여전히 올바르게 이어져요.
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을 켠 상태라면 체이닝은 불가능하고, 매 요청마다 전체 메시지 히스토리를 보내야 해요.
영속 대화 사용하기
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)
응답이 대화에 속하면 PydanticAI는 반환된 ID를 ModelResponse.provider_details['conversation_id']에 저장해요. openai_conversation_id='auto'로 설정하면 메시지 히스토리에서 가장 최근의 같은 provider 대화 ID를 쓰고 그 응답 이후의 새 입력 항목만 보내요.
메시지 수준의 conversation_id 값이 있으면 auto는 현재 PydanticAI 대화의 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)
PydanticAI가 OpenAI 대화를 만들어 주지는 않아요. OpenAI 클라이언트로 대화를 만든 뒤 그 ID를 openai_conversation_id로 넘겨야 해요. OpenAI API에서 conversation과 previous_response_id 파라미터는 상호 배타적이라 openai_conversation_id는 openai_previous_response_id와 함께 쓸 수 없어요.
메시지 컴팩션
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()],
)
기본적으로 OpenAICompaction은 stateful 모드로 동작해요. 일반 /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)],
)
대안으로 OpenAICompaction은 before_model_request 훅을 통해 <stateless=True>를 써서 무상태 /responses/compact 엔드포인트를 호출하는 stateless 모드도 지원해요. OpenAI가 대화 데이터를 보관해선 안 되는 ZDR 환경, openai_store=False를 쓸 때, 또는 컴팩션 실행 시점을 명시적·대역 외로 제어해야 할 때 유용해요. Stateless 모드에서는 message_count_threshold나 커스텀 trigger 콜러블 중 하나를 지정해야 해요.
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_threshold나 trigger를 주면 stateless 모드, 아니면 stateful 모드예요. stateless=True나 stateless=False를 명시적으로 넘길 수도 있어요. 서로 다른 모드의 파라미터를 섞으면 UserError가 나요.
TIP: Stateful 컴팩션은 openai_previous_response_id='auto'나 openai_conversation_id와 특히 잘 어울려요. 둘 다 OpenAI의 서버 측 대화 상태에 의존하므로, OpenAI가 이전에 압축된 컨텍스트를 다음 턴의 시작점으로 쓸 수 있어요. 다시 보내지 않아도 되죠.
더 낮은 수준의 사용 사례라면 모델에서 compact_messages를 직접 호출할 수 있어요.
텍스트 단계 (Text phases)
지원하는 모델은 각 어시스턴트 메시지에 phase를 붙여요. commentary는 모델이 작업하면서 쓰는 서두, final_answer는 답변 자체예요. PydanticAI는 이를 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):
# Indexes are scoped to a single model response and start over on the
# next one, so a new part at an index supersedes what was there before.
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)
'phase' 키는 모델이 출력에 레이블을 붙일 때마다 provider_details에 나타나지만, OpenAIModelProfile.openai_supports_phase가 받아들이는 모델에서만 다시 보내져요. 다른 모든 모델에서는 레이블이 사용자에게 표면화되고 후속 요청에서는 빠져요.
백그라운드 모드
큰 추론이나 도구가 많은 작업처럼 동기 요청의 실질적 지속 시간을 넘길 수 있는 장시간 요청을 위해 OpenAI Responses API는 background mode를 제공해요. 요청을 서버 측에서 실행하고 준비되면 결과를 가져오는 방식이죠. 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')으로 오면 PydanticAI가 투명하게 완료까지 계속해요. 뭘 해줄 필요 없어요. 이건 agent.run과 agent.run_stream 모두에서 동작하고, 결과는 하나의 ModelResponse로 이어져요. 스트리밍할 때는 만들어진 라이브 토큰 활동이 하나의 연속 스트림으로 도착해요.
요청이 서버 측에서 큐에 들어가기 때문에 첫 토큰까지의 시간은 동기 요청보다 길어요. 백그라운드 응답이 아직 보류 중인 동안 PydanticAI는 고정된 간격으로 완료를 폴링해요.
참고: 실행이 요청 중간에 중단되고(최종 ModelResponse.state가 'suspended') 메시지 히스토리에 저장된 경우, 그 히스토리를 다시 넘기면 새 요청을 시작하는 대신 같은 백그라운드 응답을 재개해요. provider의 보존 기간이 지난 후 재개하면 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 호환 provider도 지원해요. 전부 Chat Completions 와이어 형식을 쓰므로 같은 모델 클래스가 적용되죠.
OpenAI 호환 모델
많은 provider와 모델이 OpenAI API와 호환돼서 PydanticAI의 OpenAIChatModel로 쓸 수 있어요. 시작 전에 위의 설치·설정 지침을 확인하세요.
다른 OpenAI 호환 API를 쓰려면 OPENAI_BASE_URL과 OPENAI_API_KEY 환경 변수를 설정하거나, OpenAIProvider의 base_url과 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)
...
여러 provider는 자체 provider 클래스도 제공해서 base URL을 직접 쓸 필요 없고 표준 <PROVIDER>_API_KEY 환경 변수로 API 키를 설정할 수 있어요. provider에 자체 클래스가 있으면 Agent("<provider>:<model>") 축약형을 쓸 수 있어요. 예를 들어 Agent("deepseek:deepseek-v4-flash")나 Agent("moonshotai:kimi-k2-0711-preview")처럼요. OpenAIChatModel을 명시적으로 만들지 않아도 되죠. 마찬가지로 OpenAIChatModel의 provider 인자에 provider 클래스를 직접 인스턴스화하는 대신 provider 이름 문자열을 넘길 수 있어요.
모델 프로필
가끔 쓰는 provider나 모델이 OpenAI API·모델과 약간 다른 요구사항을 가질 수 있어요. 예를 들어 도구 정의의 JSON 스키마에 대한 제약이 다르거나, 도구 정의가 strict로 표시되는 것을 지원하지 않을 수 있죠.
PydanticAI가 제공하는 대체 provider 클래스를 쓸 때는 보통 모델 이름에 따라 적절한 모델 프로필이 자동 선택돼요. 쓰는 모델이 기본적으로 제대로 동작하지 않는다면, 직접 만든 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, # Supported by any model class via the base ModelProfile
openai_supports_strict_tool_definition=False, # Supported by OpenAIChatModel and OpenAIResponsesModel
openai_chat_supports_multiple_system_messages=False, # Supported by OpenAIChatModel only -- for strict providers (e.g. some vLLM/LiteLLM setups) that require exactly one initial system message
openai_chat_supports_max_completion_tokens=False, # Supported by OpenAIChatModel only -- for providers (e.g. OpenRouter) that only accept the older `max_tokens` field instead of `max_completion_tokens`
)
)
agent = Agent(model)
불완전한 스트리밍 응답 감지
일부 OpenAI 호환 API는 종료 finish_reason 없이 Chat Completions 스트림을 깨끗하게 닫을 수 있어서 부분 응답이 완전해 보일 수 있어요. provider가 완전한 스트림에 finish reason이 포함되도록 보장한다면 모델 프로필에 openai_chat_streaming_requires_finish_reason=True를 설정하세요. 그러면 PydanticAI는 스트림이 finish reason 없이 EOF에 도달하면 ModelAPIError를 일으켜요. 일부 호환 API가 그 필드를 보장하지 않기 때문에 기본값은 False예요.
선행 시스템 메시지를 하나만 받는 모델
일부 모델은 대화 시작 부분에서 시스템 메시지를 하나만 받고 추가 메시지는 거부하는 채팅 템플릿으로 서빙돼요(예: vLLM, LiteLLM, TGI가 서버 측에서 적용). 하나 이상 보내면 System message must be at the beginning.이나 Conversation roles must alternate ... 같은 400 에러가 나요. 일부 최신 Qwen, Mistral, Gemma, Command-R 모델에서 볼 수 있죠. 선행 시스템 메시지가 여러 방식으로 만들어질 수 있기 때문에 의도치 않게 부딪히기 쉬워요.
가져온 이유로 모델의 OpenAIModelProfile에 openai_chat_supports_multiple_system_messages=False를 설정하면 요청 전에 선행 시스템 메시지들을 두 줄바꿈으로 이어붙여 하나로 합쳐요. 합침은 무손실이라 백엔드가 여러 시스템 메시지를 거부할 때마다 켜도 안전해요.
DeepSeek
DeepSeek provider를 쓰려면 Quick Start 가이드를 따라 API 키를 먼저 만들어요.
그다음 DEEPSEEK_API_KEY 환경 변수를 설정하고 DeepSeekProvider를 이름으로 쓸 수 있어요.
from pydantic_ai import Agent
agent = Agent('deepseek:deepseek-v4-flash')
...
또는 모델과 provider를 직접 초기화할 수도 있어요.
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)
...
어떤 provider든 커스텀 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 호환 provider는 Pydantic AI v2 동안 레거시 httpx.AsyncClient도 받지만 deprecation 경고를 내요. 새 코드에서는 httpx2.AsyncClient를 쓰고, 레거시 HTTPX 클라이언트 지원은 Pydantic AI v3에서 제거될 예정이에요.
DeepSeek의 V4 모델은 기본적으로 추론을 하고, 추론이 켜진 상태에서는 강제 도구 선택을 거부해요. Thinking mode does not support this tool_choice라고 답하죠. 그래서 PydanticAI는 그 요청들에 tool_choice='auto'를 보내요. 그러면 모델이 출력 도구를 호출하는 대신 산문으로 답할 자유가 생기는데, deepseek-v4-pro에서는 재시도 예산을 소진할 만큼 자주 재시도가 들 수 있어요. 구조화된 출력을 안정적으로 만들어야 한다면 추론을 끄면 강제가 다시 쓰여요.
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),
)
...
추론이 켜진 상태에서 tool_choice='required'를 명시적으로 넘기면 API에서 실패하는 대신 UserError가 나요.
위에서 본 Chat Completions API 대신, DeepSeek는 두 V4 모델 모두에 대해 OpenAI 호환 Responses API도 제공해요. OpenAIResponsesModel과 DeepSeekProvider를 짝지어 쓰면 돼요.
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, background mode, 메시지 컴팩션을 쓸 수 없어요. 매 실행마다 메시지 히스토리를 다시 넘겨야 해요. openai_previous_response_id는 설정하지 마세요. 설정하면 PydanticAI가 서버가 이미 가진 것으로 가정한 이전 턴을 버리는데, DeepSeek는 아무것도 저장하지 않으므로 모델이 에러 대신 조용히 대화를 잃어요.- 네이티브 도구 중에서 DeepSeek는
WebSearchTool만 실행하고 나머지는 에러 대신 무시해요. - 이미지·문서 입력은 거부가 아니라 플레이스홀더 텍스트로 대체돼요.
- 추론은
openai_reasoning_effort(또는 통합된thinking설정)로 구성해요.openai_reasoning_summary는 받지만 요약을 만들지는 않아요. NativeOutput는 여기서 쓸 수 있지만 Chat Completions에서는 쓸 수 없어요. DeepSeek는 Responses API에서는 strict JSON 스키마를 존중하지만, Chat Completions 엔드포인트는This response_format type is unavailable now로 거부해요.
PydanticAI가 처리해 주는 차이점이 하나 있어요. DeepSeek는 각 함수 호출을 인접한 어시스턴스 메시지로 합쳐요. 추론이나 텍스트와 호출이 섞인 턴을 재생하면 답이 없는 호출이 있는 별도 메시지가 만들어지는데, DeepSeek는 No tool output found for tool call ...로 거부해요. PydanticAI는 요청을 만들 때 호출들을 다른 항목 뒤로 옮겨요. 이건 요청만 재정렬하고 메시지 히스토리는 바뀌지 않아요.
재정렬은 모든 함수 호출에 결과가 있고 그 턴에 provider 소유 네이티브 도구나 컴팩션 항목이 없을 때만 적용돼요. DeepSeek는 어떤 순서에서든 해결되지 않은 호출을 거부하고, provider 소유 항목은 그대로 둬요. 다른 엔드포인트에서 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')
...
또는 모델과 provider를 직접 초기화할 수도 있어요.
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', # China region
),
)
agent = Agent(model)
...
문서 입력은 지원되지 않아요. DashScope 호환 모드의 Chat Completions API는 문서 콘텐츠 파트를 받지 않아서, AlibabaProvider로 뒷받침된 OpenAIChatModel에 DocumentUrl이나 문서 BinaryContent를 넘기면 UserError가 나요.
Ollama
Ollama에 대한 전용 문서는 Ollama를 보세요. 구조화된 출력과 Ollama Cloud 제한 사항이 포함돼요.
Azure AI Foundry
Azure AI Foundry를 provider로 쓰려면 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')
...
또는 모델과 provider를 직접 초기화할 수도 있어요.
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와도 자연스럽게 짝을 이루는데, 아래 Responses API와 Azure 사용하기를 보세요.
AzureProvider는 https://<model>.<region>.models.ai.azure.com의 Azure AI Foundry serverless 모델 배포도 인식하고 같은 방식으로 연결해요.
기존 api-version 기반 배포에 연결하기
리소스가 여전히 날짜가 있는 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)
...
Responses API와 Azure 사용하기
Azure AI Foundry는 OpenAIResponsesModel을 통해 OpenAI Responses API도 지원해요. 특히 문서 입력(DocumentUrl과 BinaryContent)으로 작업할 때 권장돼요. Azure의 Chat Completions API는 이런 입력 타입을 지원하지 않기 때문이에요.
이름으로 Responses API를 선택하려면 azure-responses: 프리픽스를 쓰세요(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: 축약형을 쓰든 AzureProvider로 OpenAIResponsesModel을 직접 만들든 동일하게 적용돼요.
또는 모델과 provider를 직접 초기화할 수도 있어요.
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 ...' # Your PDF content
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_KEY와 VERCEL_OIDC_TOKEN 환경 변수를 설정하고 VercelProvider를 이름으로 쓰면 돼요.
from pydantic_ai import Agent
agent = Agent('vercel:anthropic/claude-sonnet-4-5')
...
또는 모델과 provider를 직접 초기화할 수도 있어요.
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')
...
또는 모델과 provider를 직접 초기화할 수도 있어요.
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는 2026년 7월 30일에 퇴역했어요. 플레이그라운드, 모델 카탈로그, 추론 API를 더 이상 쓸 수 없죠. GitHubProvider는 따라서 deprecated이며 v3에서 제거될 예정이에요.
앞으로 모델 접근은 GitHub가 Azure AI Foundry나 GitHub Copilot을 권장해요. PydanticAI는 둘 다 GitHubCopilotModel을 통해 지원해요.
Perplexity
Perplexity 시작 가이드를 따라 API 키를 만든 뒤 모델과 provider를 직접 초기화하면 돼요.
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')
...
또는 모델과 provider를 직접 초기화할 수도 있어요.
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', # model library available at 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')
...
또는 모델과 provider를 직접 초기화할 수도 있어요.
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', # model library available at https://www.together.ai/models
provider=TogetherProvider(api_key='your-together-api-key'),
)
agent = Agent(model)
...
deepseek-ai/DeepSeek-V4-* 모델은 추론이 켜진 상태에서 강제 도구 선택을 거부해요. 그리고 추론이 기본값이에요. 그래서 PydanticAI는 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')
...
또는 모델과 provider를 직접 초기화할 수도 있어요.
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을 쓰려면 문서에 나온 대로 config를 설정해요. LiteLLMProvider에서 api_base와 api_key를 넘길 수 있어요. 이 값은 설정에 따라 달라져요. 예를 들어 OpenAI 모델을 쓰면 https://api.openai.com/v1을 api_base로, OpenAI API 키를 api_key로 넘겨야 해요. 로컬 머신에서 돌아가는 LiteLLM 프록시 서버를 쓴다면 http://localhost:<port>를 api_base로, LiteLLM API 키(또는 플레이스홀더)를 api_key로 넘기면 돼요.
커스텀 LLM을 쓰려면 모델 이름에 custom/ 프리픽스를 쓰세요.
config를 준비했으면 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)
#> The capital of France is Paris.
...
참고: 모델이 선행 시스템 메시지를 하나보다 많이 거부한다면(예: 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_key나 VLLM_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)
#> The capital of France is Paris.
그 환경 변수들을 설정해 두면 provider를 이름으로 참조할 수도 있어요.
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)
#> The capital of France is Paris.
도구 호출에는 서버 구성이 필요해요. 모델이 도구를 호출할지 스스로 결정하게 하는 에이전트에서는 vLLM을 --enable-auto-tool-choice로 시작하고 --tool-call-parser로 모델 특화 파서를 선택하세요. 지원되는 모델과 파서 값은 vLLM 도구 호출 가이드를 보세요.
여러 시스템 메시지는 기본적으로 병합돼요. 일부 vLLM 채팅 템플릿이 여러 선행 시스템 메시지를 거부하므로 VLLMProvider는 기본적으로 그것들을 병합해요. 해제하려면 openai_chat_supports_multiple_system_messages=True인 OpenAIModelProfile을 넘기세요. 선행 시스템 메시지를 하나만 받는 모델을 보세요.
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)
#> The capital of France is Paris.
또는 모델과 provider를 직접 초기화할 수도 있어요.
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)
#> The capital of France is Paris.
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)
#> The capital of France is Paris.
provider를 구성해야 한다면 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)
#> The capital of France is Paris.
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)
#> The capital of France is Paris.
또는 모델과 provider를 직접 초기화할 수도 있어요.
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)
#> The capital of France is Paris.
사용 가능한 모델의 전체 목록은 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는 전용 provider 클래스가 없어서 OpenAIProvider로 base_url과 api_key를 설정해 쓰면 돼요.
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 호환 추론 서버예요.
Terminal
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)
- OpenAI 프롬프트 캐싱 — 캐시 중단점과 TTL 동작
- Responses vs Chat Completions 마이그레이션
- Retry multiplication — 클라이언트 재시도가 에이전트 재시도와 겹치는 방식