
Pydantic AI v2, 에이전트 확장을 'capability' 하나로 통합한 설계
요약
Pydantic AI v2는 에이전트 확장을 위한 'capability' 개념을 도입하여 도구, 프롬프트, 훅, 모델 설정을 하나의 단위로 통합했습니다. 이를 통해 복잡한 레이어 수정 없이 리스트에 capability를 추가하는 것만으로 에이전트의 기능을 간편하게 확장할 수 있습니다.
핵심 포인트
- capability 개념을 통해 도구, 프롬프트, 훅, 설정을 하나의 오브젝트로 통합
- 기능 추가 시 여러 레이어를 수정할 필요 없이 리스트에 추가하는 방식으로 단순화
- 실행 루프의 각 단계에 개입할 수 있는 정교한 라이프사이클 훅 제공
- Web 검색, 코드 실행 샌드박스, 확장 사고(Thinking) 등을 쉽게 탑재 가능
에이전트에 「Web 검색」과 「코드 실행 샌드박스(Code Execution Sandbox)」, 그리고 「세션을 넘나드는 기억」을 추가하고 싶다. 일반적인 프레임워크라면 이 작업은 한 곳에서 끝나지 않는다. 도구를 등록하는 곳, 시스템 프롬프트(System Prompt)를 추가하는 곳, 실행 중에 모델에 전달하는 문맥(Context)을 교체하는 훅(Hook), 모델 설정 노브(Knob) 등 각각이 서로 다른 레이어에 흩어져 있어, 기능을 하나 늘릴 때마다 4~5곳을 건드려야 한다.
Pydantic AI v2가 내놓은 답은 그 흩어진 요소들을 하나의 오브젝트로 통합하는 것이었다. 7번의 베타를 거쳐, v2.0.0이 2026년 6월 23일에 안정판(Stable version)이 되었다.
v2의 중심 개념은 capability(케이파빌리티)다. 이는 「명령문(Instructions) · 도구(Tools) · 라이프사이클 훅(Lifecycle Hooks) · 모델 설정(Model Settings)」이라는, 에이전트를 구성하는 4개의 층을 하나로 묶은 합성 가능한 단위를 가리킨다. 즉, 기능 추가란 「capability를 1개 Agent에 전달하는 것」으로 통일된다. 미들웨어(Middleware)를 앱에 use()하는 것과 비슷한 감각이라고 생각하면 된다.
예를 들어 코드 실행 · Hacker News의 MCP 서버 · Web 검색을 탑재한 에이전트는 공식 리포지토리(Repository)의 예시를 보면 다음과 같이 작성할 수 있다.
from pydantic_ai import Agent
from pydantic_ai.capabilities import MCP, WebSearch
from pydantic_ai_harness import CodeMode
...
capabilities=[...]에 나열된 것들이 각각 내부에서 도구도 프롬프트도 훅도 등록해 나간다. 호출하는 쪽은 리스트에 한 줄을 추가하는 것만으로 해당 기능이 요구하는 모든 레이어의 배선이 완료된다. WebSearch(native=False)에서 native는 프로바이더(Provider)가 네이티브 검색을 가지고 있다면 그것을 사용하고, 없다면 로컬 구현으로 폴백(Fallback)하도록 지정하는 것이다. CodeMode()는 Monty라는 샌드박스에서 동작하며, 본래 N번으로 나뉘어야 할 도구 호출을 한 번의 run_code로 통합한다. Thinking(effort='high')와 같이 프로바이더마다 제각각이었던 확장 사고(Extended Thinking)를 횡단적으로 통일하는 capability도 있다.
capability가 강력한 이유는 도구를 추가하는 것뿐만 아니라 에이전트의 실행 루프(Execution Loop) 자체에 개입할 수 있기 때문이다. v2의 훅은 층마다 정연하게 나뉘어 있으며 명명 규칙도 규칙적이다.
| 훅의 층 | 개입 대상 |
|---|---|
| Run | 에이전트의 실행 전체 |
| ... | 각 층에는 before_* / after_* / wrap_* / on_*_error의 4종류가 갖춰져 있다. wrap_*는 전후를 감싸는 미들웨어형이며, on_*_error는 실패 시에만 실행된다. 예를 들어 모델로 보내기 직전에 문맥을 교체한다면 다음과 같다. |
@hooks.on.before_model_request
async def log_request(ctx: RunContext, request_context: ModelRequestContext) -> ModelRequestContext:
print(f'Sending {len(request_context.messages)} messages to the model')
...
request_context를 받아 가공하여 반환한다. 여기서 메시지 목록을 줄이면 문맥 압축(Context Compression)이 되고, 기밀 정보를 가리면 마스킹(Masking)이 된다. 「모델이 실제로 보는 내용을 실행 중에 바꿔 쓰는」 처리를 외부 capability로서 배포할 수 있게 된 것이 v2의 핵심이다. 프롬프트 압축이나 가드레일(Guardrails)이 프레임워크 본체를 포크(Fork)하지 않고 하나의 pip 패키지로서 유통된다.
v2에서 또 하나 효과적인 것은 라이브러리를 두 개로 나눈 판단이다.
| 설치 | 내용 | |
|---|---|---|
core(pydantic-ai) | uv add pydantic-ai | 실행 루프(Execution loop), 각 프로바이더(Provider), capability 및 hooks의 API, 깊은 프로바이더 연동이 필요한 핵심 capability |
Harness(pydantic-ai-harness) | uv add pydantic-ai-harness | 메모리, 가드레일(Guardrails), 컨텍스트 관리(Context management), 파일 시스템, 코드 실행 등의 "배터리(batteries)" |
CodeMode의 Monty 샌드박스 등은 추가 의존성이 필요하므로, uv add "pydantic-ai-harness[codemode]"와 같이 extras를 통해 설치한다. Harness 측이 보유한 capability는 광범위하다. 파일 조작을 위한 FileSystem (경로 탐색(Path traversal) 방지 포함), 명령 실행을 위한 Shell (허용/거부 목록 및 타임아웃), 슬라이딩 윈도우(Sliding window)나 LLM을 이용한 컨텍스트 압축, 세션을 넘나드는 키-값(Key-value) 영구 메모리, 비용/토큰 예산·도구 액세스 제어·비밀 정보 마스킹·승인 플로우와 같은 가드레일 군이 나열되어 있다.
분리한 목적은 명확하다. core는 하위 호환성(Backward compatibility)을 엄격히 준수하여 안정화하고, 변화가 빠른 기능은 Harness에서 빠르게 회전시킨다. 그리고 널리 필수적이라고 판단된 capability는 core로 "승격"시킨다. React가 안정적인 API와 실험적인 API를 나누는 것과 마찬가지로, 성숙도에 따라 레이어를 나누는 발상이다.
이전(Migration)할 경우, 갑자기 v2로 건너뛰지 말고 먼저 v1의 최신 버전까지 올려서 deprecation 경고를 모두 제거하는 것이 공식 권장 사항이며, 파괴적 변경(Breaking changes)의 대부분은 그 과정에서 드러난다. OpenAI 계열의 모델명이 Responses API 준수를 위해 변경된 점, capability를 지연 로드(Lazy loading)하는 defer_loading=True가 있다는 점도 이전 시 유효하게 작용한다.
설계 측면에서 우려되는 점은, capability가 "명령·도구·훅·설정"을 모두 포함하는 만능 부품이기 때문에, 여러 capability가 동일한 before_model_request에서 프롬프트를 서로 건드렸을 때 최종적으로 모델에 무엇이 전달되었는지 추적하기 어려워질 수 있다는 것이다. 리스트에 나열된 순서가 동작을 좌우하는 만큼, 훅(Hook)의 실행 순서와 디버깅 수단은 팀 내에서 미리 합의해 두는 것이 좋다.
그럼에도 불구하고, 에이전트 확장을 "배포 가능한 하나의 부품"으로 떨어뜨린 추상화는 솔직히 훌륭하다. 자신의 에이전트에 기능을 추가할 때마다 설정 파일을 다섯 군데씩 수정해야 했던 사람일수록, 이 설계의 경쾌함이 큰 효과를 발휘할 것이다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기