V1 → V2 마이그레이션 맵
V1 → V2 마이그레이션 맵
Pydantic AI V1에서 V2로 업그레이드하기 위한 조회 인덱스예요. 코드에 있는 V1 이름을 찾아서, 그걸 대체할 V2 이름을 읽어내면 돼요.
업그레이드 가이드는 각 변경이 왜 이뤄졌는지, 함께 오는 동작 변경, 권장 업그레이드 경로에 대한 표준 출처예요. 이 페이지는 가이드가 산문으로 답하는 단 한 가지 질문, 무엇이 무엇을 대체했는가에 대한 빠른 경로예요.
출처: 문서
본문
먼저 최신 V1로 업그레이드하세요
V2가 제거하는 것의 대부분은 v1.100.0 기준으로 deprecated이며, 각 deprecation 경고가 그 대체를 이름 붙여요. 최신 V1로 업그레이드하고 모든 경고를 해결하면 이 페이지의 대부분이 기계적으로 적용되고, 기본 동작 변경에 대해서만 추론하면 돼요. V1으로 직렬화된 메시지 이력은 V2에서 여전히 역직렬화돼요.
에이전트 구성
동작을 구성했던 대부분의 V1 Agent(...) 인자는 에이전트의 툴, 훅, 지시문, 모델 설정을 묶는 단일 합성 가능한 원시 타입인 capabilities로 옮겼어요.
| V1 | V2 |
|---|---|
Agent(builtin_tools=[...]) |
Agent(capabilities=[NativeTool(...)]) |
Agent(event_stream_handler=...) |
Agent(capabilities=[ProcessEventStream(...)]) (run()/run_sync()/run_stream()/iter()의 event_stream_handler= 인자는 그대로) |
Agent(history_processors=...) |
Agent(capabilities=[ProcessHistory(...)]) |
Agent(instrument=...), Agent.from_spec(instrument=...), Agent.from_file(instrument=...), AgentSpec.instrument |
Agent(capabilities=[Instrumentation(...)]) |
Agent(mcp_servers=[...]) |
Agent(toolsets=[...]) |
Agent(prepare_tools=...) |
Agent(capabilities=[PrepareTools(...)]) |
Agent.run_mcp_servers() |
async with agent: |
Agent.sequential_tool_calls() |
Agent.parallel_tool_call_execution_mode('sequential') |
Agent.to_a2a() |
fasta2a.pydantic_ai.agent_to_a2a (fasta2a[pydantic-ai]>=0.6.1 설치) |
Agent.to_ag_ui(), AGUIApp, pydantic_ai.ag_ui |
pydantic_ai.ui.ag_ui.AGUIAdapter |
Agent('gpt-5') (프로바이더 프리픽스 없음) |
Agent('openai:gpt-5') — 프리픽스 없는 폴백은 이제 UserError 발생 |
deps가 실제로 None이 아닌데 Agent[None, ...], RunContext[None], Tool[None] |
Agent[object, ...], RunContext[object], Tool[object] — 제네릭 기본값이 None에서 object로 변경됨 |
모델과 프로바이더
| V1 | V2 |
|---|---|
pydantic_ai.models.gemini.GeminiModel |
pydantic_ai.models.google.GoogleModel |
pydantic_ai.models.openai.OpenAIModel |
pydantic_ai.models.openai.OpenAIChatModel |
pydantic_ai.models.openai.OpenAIModelSettings |
pydantic_ai.models.openai.OpenAIChatModelSettings |
OpenAIChatModel(system_prompt_role=...) |
OpenAIChatModel(profile=OpenAIModelProfile(openai_system_prompt_role=...)) — 모델이 이미 프로필을 해석한다면 아래 참고 |
OpenAICompaction(instructions=...) |
제거됨 |
pydantic_ai.models.outlines.OutlinesModel, pydantic_ai.providers.outlines.OutlinesProvider |
제거됨, 대체 없음 |
pydantic_ai.models.cached_async_http_client |
pydantic_ai.models.create_async_http_client() |
pydantic_ai.providers.google.GoogleProvider(vertexai=, location=, project=, credentials=) |
pydantic_ai.providers.google_cloud.GoogleCloudProvider(...) |
pydantic_ai.providers.google.GoogleGLAProvider |
pydantic_ai.providers.google.GoogleProvider |
pydantic_ai.providers.google.GoogleVertexProvider |
pydantic_ai.providers.google_cloud.GoogleCloudProvider |
pydantic_ai.providers.grok.GrokProvider, GrokModelName |
pydantic_ai.providers.xai.XaiProvider with pydantic_ai.models.xai.XaiModel / XaiModelName |
GoogleModelSettings['google_vertex_service_tier'], ['google_service_tier'] |
GoogleModelSettings['google_cloud_service_tier'] |
StreamedResponse.usage() (커스텀 Model 서브클래스) |
StreamedResponse.usage 속성 |
모델 이름 프리픽스
| V1 프리픽스 | V2 프리픽스 |
|---|---|
openai: (Chat Completions) |
openai:는 이제 Responses API를 뜻함. Chat Completions는 openai-chat:, 명시적으로 하려면 openai-responses: 사용 |
google-gla: |
google: |
google-vertex:, vertexai: |
google-cloud: |
gateway/gemini:, gateway/google-vertex: |
gateway/google-cloud: |
grok: |
xai: |
모델 프로필
ModelProfile과 그 서브클래스는 이제 dataclass가 아니라 TypedDict예요. 하나를 구성하는 것(OpenAIModelProfile(field=value))은 그대로지만, 읽기, 변경, 병합은 다르지 않아요. 전체 레시피 표는 업그레이드 가이드의 ModelProfile is now a TypedDict 아래 있어요.
| V1 | V2 |
|---|---|
profile.field |
profile.get('field', <default>) — 기본값은 pydantic_ai.profiles에서 export됨 |
profile.field = value |
profile['field'] = value |
dataclasses.replace(profile, field=value) |
{**profile, 'field': value} |
profile.update(other) |
merge_profile(profile, other) |
OpenAIModelProfile.from_profile(p) |
p |
isinstance(profile, OpenAIModelProfile) |
TypedDict에서는 지원되지 않음 — 키 존재를 확인할 것 |
OpenAIModelProfile.openai_supports_sampling_settings |
OpenAIModelProfile.openai_unsupported_model_settings — 이름 변경이 아님, 아래 참고 |
OpenAIModelProfile.openai_builtin_tools |
OpenAIModelProfile.openai_native_tools |
단순 이름 변경이 아님
위 OpenAI 행 중 둘은 찾기-바꾸기 이상이 필요해요:
openai_supports_sampling_settings→openai_unsupported_model_settings는 이름뿐 아니라 형태가 바뀌어요. V1 필드는 샘플링 설정을 그룹으로 다루는bool이었어요. V2 필드는 버릴 특정 설정 이름들의 시퀀스예요.openai_supports_sampling_settings=False는 모델이 받아들이지 않는 것의 명시적 목록이 되는데, 예를 들어openai_unsupported_model_settings=('temperature', 'top_p').True는 기본값이었으므로 그냥 사라져요.system_prompt_role은 모델 인자에서 프로필로 이동해요. 이미profile=을 모델에 전달하고 있었다면, 바꾸는 대신 그 설정을 그 프로필에 병합하세요. 두 번째OpenAIModelProfile(...)는 첫 번째를 통째로 덮어써요. 프로필은 V2에서TypedDict이므로 병합은{**existing_profile, 'openai_system_prompt_role': 'user'}또는merge_profile()이에요.
MCP
전송별 서버 클래스들이 전송을 전달하는 인자에서 추론하는 단일 MCPToolset으로 수렴했어요. 그 기본값은 V1 클래스들과 달라요. 특히 max_retries, read_timeout, init_timeout, elicitation_handler가 달라요. 그래서 V1 타임아웃이 그대로 이어졌다고 가정하지 말고 MCP Client를 다시 읽으세요.
| V1 | V2 |
|---|---|
MCPServerStdio, MCPServerSSE, MCPServerStreamableHTTP, MCPServerHTTP |
pydantic_ai.mcp.MCPToolset |
FastMCPToolset (및 fastmcp extra) |
MCPToolset |
load_mcp_servers |
pydantic_ai.mcp.load_mcp_toolsets |
Agent.run_mcp_servers() |
async with agent: |
기본적으로 원격으로 실행되는 MCP(url=...) |
V1 동작을 유지하려면 MCP(url=..., native=True); MCP(url=...)는 이제 서버를 로컬로 실행 |
툴과 툴셋
| V1 | V2 |
|---|---|
pydantic_ai.builtin_tools |
pydantic_ai.native_tools |
AgentBuiltinTool |
AgentNativeTool |
pydantic_ai.native_tools.UrlContextTool |
pydantic_ai.native_tools.WebFetchTool |
builtin= 인자 |
native= |
pydantic_ai.output.DeferredToolCalls |
DeferredToolRequests |
DeferredToolCalls.tool_calls |
DeferredToolRequests.calls |
DeferredToolCalls.tool_defs |
제거됨 — V1에서 항상 빈 dict를 반환했음 |
pydantic_ai.toolsets.external.DeferredToolset |
ExternalToolset |
컨텍스트 없는 callable에서 FunctionToolset.tool() |
FunctionToolset.tool_plain() — tool()은 이제 첫 매개변수가 RunContext가 아니면 예외 발생 |
pydantic_ai.ext.aci.tool_from_aci, ACIToolset |
제거됨; Tool.from_schema로 툴 스키마를 감쌀 것 |
None을 반환하는 prepare 콜백 |
[] 반환 — None 반환은 이제 툴을 모두 제거하는 대신 TypeError 발생 |
로컬 구현으로 폴백하는 WebSearch() / WebFetch() |
WebSearch(local='duckduckgo') / WebFetch(local=True) — 둘 다 기본적으로 네이티브 전용이며 이제 지원하지 않는 모델에서 예외 발생 |
메시지, 이벤트, 사용량
직렬화된 part_kind 와이어 값과 옛 필드 이름의 검증 별칭은 유지돼요. 그래서 V1이 쓴 메시지 이력은 V2에서도 역직렬화돼요.
| V1 | V2 |
|---|---|
BuiltinToolCallPart, BuiltinToolReturnPart |
NativeToolCallPart, NativeToolReturnPart |
BuiltinToolCallEvent, BuiltinToolResultEvent |
제거됨 — 네이티브 툴 호출은 PartStartEvent/PartDeltaEvent로만 드러남 |
출력 툴용 FunctionToolCallEvent/FunctionToolResultEvent |
OutputToolCallEvent/OutputToolResultEvent |
FunctionToolCallEvent.call_id |
FunctionToolCallEvent.tool_call_id |
FunctionToolResultEvent(result=...), .result |
FunctionToolResultEvent(part=...), .part |
ModelResponse.vendor_details |
ModelResponse.provider_details |
ModelResponse.vendor_id, ModelResponse.provider_request_id |
ModelResponse.provider_response_id |
ModelResponse.builtin_tool_calls |
ModelResponse.native_tool_calls |
ModelResponse.price() |
ModelResponse.cost() |
Usage |
RunUsage |
usage.request_tokens, usage.response_tokens |
usage.input_tokens, usage.output_tokens |
UsageLimits(request_tokens_limit=), (response_tokens_limit=) |
UsageLimits(input_tokens_limit=), (output_tokens_limit=) |
결과와 스트리밍
| V1 | V2 |
|---|---|
result.usage(), result.timestamp() |
result.usage, result.timestamp (속성) |
stream.get() |
stream.response |
StreamedRunResult.stream |
stream_output |
StreamedRunResult.stream_structured |
stream_response |
StreamedRunResult.stream_responses() (복수, (response, is_last) 산출) |
stream_response() (단수, 알몸의 ModelResponse 산출; 옛 is_last는 response.state != 'incomplete'로 읽음) |
StreamedRunResult.validate_structured_output |
validate_response_output |
async for event in agent.run_stream_events(...) |
async with agent.run_stream_events(...) as events: 후 반복 — async 컨텍스트 매니저로만 사용 |
Pydantic Graph
| V1 | V2 |
|---|---|
from pydantic_graph.beta import GraphBuilder |
from pydantic_graph import GraphBuilder |
pydantic_graph.persistence |
대응하는 pydantic_graph 없음 — 빌더 API는 그래프 상태를 스냅샷하지 않음. 에이전트 실행 상태를 저장·재개·포크하려면 Pydantic AI Harness가 StepPersistence를 제공 |
pydantic_graph.mermaid |
제거됨 — Graph.render()로 다이어그램 렌더링 |
Pydantic Evals
| V1 | V2 |
|---|---|
Evaluator.name (classmethod) |
Evaluator.get_serialization_name() |
evaluation_name 클래스 속성 |
Evaluator.get_default_evaluation_name() |
evaluator_version 클래스 속성 |
Evaluator.get_evaluator_version() |
이름 없는 Dataset(...) |
Dataset(name=...) — 이제 필수 |
Dataset.evaluate()/evaluate_sync()의 위치 name/max_concurrency/progress/retry_task/retry_evaluators |
키워드 전용 |
EvaluationResult / EvaluatorFailure의 위치 생성 |
키워드 전용 |
인스트루멘테이션
| V1 | V2 |
|---|---|
InstrumentationSettings(version=1), event_mode=, logger_provider= |
제거됨; 버전 2-4는 여전히 작동하지만 경고함. 기본은 버전 5 |
gen_ai.usage.*에서 실행 스팬 토큰 사용량 읽기 |
실행 스팬은 gen_ai.aggregated_usage.*를 보고. V1 이름을 유지하려면 use_aggregated_usage_attribute_names=False 설정 |
패키징
알몸의 uv add pydantic-ai / pip install pydantic-ai는 이제 더 슬림한 extra 집합을 설치해요. bedrock, groq, mistral, cohere, xai, huggingface, temporal, ag-ui, ui, spec은 더 이상 기본으로 포함되지 않아요. 사용하는 것을 추가하세요(예: uv add 'pydantic-ai[bedrock,groq]'). outlines-*, vertexai, fastmcp, a2a extra는 아예 제거됐어요. 전체 목록은 설치 가이드를 참고하세요.
코드 변경 없는 동작 변경
이것들은 어떤 심볼도 이름을 바꾸지 않고 뒤집혀서, 옛 이름을 grep으로 찾을 수 없어요. 각각은 업그레이드 가이드의 deprecation 경고로 덮이지 않는 변경 아래에 완전히 설명돼 있어요.
- 기본
end_strategy가'early'에서'graceful'로 바뀌어서, 성공적인 출력 툴과 함께 요청된 함수 툴이 이제 건너뛰는 대신 실행돼요. 병렬 출력 툴 호출 참고. - 툴의
sequential=True는 이제 배치 전체 직렬 스위치가 아니라 툴별 장벽이고, 출력 툴에도 적용돼요. capture_run_messages()는 이제 중단된 실행의 부분 요청/응답도 포착하며,state='interrupted'로 표시돼요.- 해석된 모델 프로필은 이제 V1이 걸러냈던 다른 프로필 클래스의 필드도 담아요.