Pydantic AI Core Concepts 정리


Pydantic AI 기본 세팅을 보고 나면 공식 문서에서 Core Concepts를 만나게 된다.

목록만 보면 Agents, Dependencies, Output, Capabilities, Hooks, Agent Specs, Messages and chat history, Direct Model Requests가 나오는데, 처음에는 뭐가 뭐랑 연결되는지 잘 안 보인다.

이번 글에서는 각 개념을 깊게 파기보다는, Agent를 실제 서비스 코드처럼 구성하려면 어떤 부품들이 필요한지 기준으로 정리해보려고 한다.

공식 문서:

전체 그림

Pydantic AI는 단순히 모델에게 프롬프트를 보내는 라이브러리라기보다는, LLM을 실제 Python 애플리케이션 안에서 다루기 위한 Agent 프레임워크에 가깝다.

큰 구조는 이렇게 보면 된다.

Agent
 ├─ instructions
 ├─ dependencies
 ├─ tools / capabilities
 ├─ output
 ├─ hooks
 ├─ messages / chat history
 └─ model request

Agent가 중심이고, 나머지 개념들은 Agent가 실행될 때 필요한 설정, 외부 값, 기능, 출력 형식, 대화 기록을 붙이는 방식이다.

Agents

Agent는 Pydantic AI에서 가장 중심이 되는 객체다.

쉽게 말하면 아래 요소들을 하나로 묶은 실행 단위다.

  • 어떤 모델을 쓸지
  • 어떤 역할을 줄지
  • 어떤 tool을 사용할 수 있는지
  • 실행할 때 어떤 외부 값이 필요한지
  • 최종 결과를 어떤 타입으로 받을지

가장 단순한 Agent는 이렇게 만든다.

from pydantic_ai import Agent

agent = Agent(
    'openai:gpt-5.2',
    instructions='너는 쇼핑몰 고객센터 상담원이야.',
)

result = agent.run_sync('배송 조회는 어디서 해?')
print(result.output)

이 정도면 그냥 LLM 호출처럼 보인다. 하지만 여기에 deps, tool, output_type이 붙기 시작하면 단순 호출이 아니라 하나의 서비스 로직에 가까워진다.

agent = Agent(
    'openai:gpt-5.2',
    deps_type=Deps,
    output_type=SupportAnswer,
    instructions='너는 쇼핑몰 고객센터 상담원이야.',
)

이렇게 되면 Agent는 “쇼핑몰 상담 역할을 하고, 실행 시점의 의존성을 받고, 최종 답변은 SupportAnswer 형태로 반환하는 객체”가 된다.

Dependencies

Dependencies는 Agent를 실행할 때 같이 넘기는 외부 값이다.

from dataclasses import dataclass

@dataclass
class Deps:
    user_id: int
    membership: str

이런 값은 사용자마다 달라진다.

result = agent.run_sync(
    '내 할인율 적용하면 얼마야?',
    deps=Deps(user_id=1, membership='gold'),
)

여기서 deps는 “이번 실행은 user_id가 1이고, 회원 등급은 gold인 상태로 실행한다”는 의미에 가깝다.

조금 더 실제 서비스에 가까워지면 DB 연결이나 API client도 들어갈 수 있다.

@dataclass
class Deps:
    user_id: int
    db: DatabaseConn
    payment_client: PaymentClient

@agent.tool 안에서는 RunContext를 통해 이 값을 꺼내 쓴다.

from pydantic_ai import RunContext

@agent.tool
def get_membership(ctx: RunContext[Deps]) -> str:
    """현재 사용자의 회원 등급을 가져온다."""
    return ctx.deps.membership

이렇게 넘긴 deps는 매 실행마다 달라질 수 있다. 예를 들어 같은 Agent라도 어떤 요청에서는 gold 회원으로, 다른 요청에서는 basic 회원으로 실행할 수 있다.

result = agent.run_sync(
    '내 회원 등급이 뭐야?',
    deps=Deps(user_id=1, membership='gold'),
)

핵심은 deps가 LLM에게 바로 보여주는 값이 아니라, tool이 실행될 때 참고하는 실행 context라는 점이다.

Output

Output은 Agent의 최종 결과를 어떤 형태로 받을지 정하는 개념이다.

LLM 응답을 문자열로만 받으면 간단하긴 하지만, 서비스 코드에서 다시 쓰기 어렵다.

예를 들어 고객센터 Agent가 아래처럼 답한다고 해보자.

주문 상태는 배송 중이고, 위험도는 2입니다.

사람이 읽기엔 괜찮지만 코드에서는 배송 중, 2를 다시 파싱해야 한다.

그래서 Pydantic AI에서는 output_type으로 최종 응답 구조를 지정할 수 있다.

from pydantic import BaseModel, Field
from pydantic_ai import Agent

class SupportAnswer(BaseModel):
    message: str
    order_status: str | None
    risk: int = Field(ge=0, le=10)

agent = Agent(
    'openai:gpt-5.2',
    output_type=SupportAnswer,
    instructions='너는 쇼핑몰 고객센터 상담원이야.',
)

이렇게 하면 result.output은 그냥 문자열이 아니라 SupportAnswer 객체가 된다.

result = agent.run_sync('내 주문 어디까지 왔어?')

print(result.output.message)
print(result.output.order_status)
print(result.output.risk)

output_type은 “예쁘게 답변해줘”가 아니라, 최종 답변은 이 구조로 줘에 가깝다.

LLM 결과를 코드에서 믿고 쓰려면 이 부분이 꽤 중요하다.

Capabilities

Capabilities는 Agent에 붙일 수 있는 기능 묶음이다.

tool 하나를 직접 붙이는 것보다 더 큰 단위라고 보면 된다. 예를 들어 어떤 capability는 tool, instructions, hooks, model settings 같은 것을 한 번에 포함할 수 있다.

공식 문서의 예시는 이런 느낌이다.

from pydantic_ai import Agent
from pydantic_ai.capabilities import Thinking, WebSearch

agent = Agent(
    'anthropic:claude-sonnet-4-6',
    instructions='짧게 답해줘.',
    capabilities=[
        Thinking(),
        WebSearch(),
    ],
)

쉽게 말하면:

개념 느낌
tool Agent가 호출할 수 있는 함수 하나
capability Agent에 붙이는 재사용 가능한 기능 묶음

처음 공부할 때는 tool을 먼저 이해하고, capability는 “여러 기능을 재사용하기 좋게 묶는 방식” 정도로 보면 충분하다.

Hooks

Hooks는 Agent 실행 흐름 중간에 끼어드는 처리다.

웹 프레임워크의 middleware나 callback을 떠올리면 이해하기 쉽다.

예를 들어 이런 상황에서 쓸 수 있다.

  • 모델 요청 전에 로그 남기기
  • tool 호출 전에 권한 검사하기
  • tool 호출 결과를 기록하기
  • 특정 tool은 사용자 승인 후에만 실행하기
  • 실행 비용이나 토큰 사용량을 추적하기

즉 hook은 Agent의 본래 역할을 바꾸기보다는, 실행 과정의 관찰, 검사, 제어를 넣을 때 쓴다.

초반에는 필수 개념은 아니지만, 실제 서비스로 갈수록 중요해진다. 특히 결제, 주문 취소, 메일 발송처럼 상태를 바꾸는 tool이 있다면 hook이나 승인 흐름을 고민해야 한다.

Agent Specs

Agent Specs는 Agent를 Python 코드가 아니라 설정 파일 형태로 정의하는 방식이다.

보통은 이렇게 코드로 Agent를 만든다.

agent = Agent(
    'openai:gpt-5.2',
    instructions='너는 쇼핑몰 상담원이야.',
)

그런데 Agent 설정이 많아지면 코드 안에 전부 박아두는 게 부담스러울 수 있다. 이때 YAML이나 JSON 같은 설정 파일로 Agent를 정의하면 관리하기 편해진다.

이 개념은 처음부터 깊게 볼 필요는 없다.

다만 Agent가 여러 개 생기거나, 환경별로 설정을 다르게 관리하거나, 비개발자가 일부 설정을 조정해야 하는 상황에서는 의미가 있다.

쉽게 말하면:

Agent Specs = Agent 설정을 코드 밖으로 빼서 정의하는 방식

Messages and chat history

LLM은 이전 대화를 자동으로 영원히 기억하지 않는다.

대화형 Agent를 만들려면 이전 메시지를 같이 넘겨줘야 한다.

예를 들어 이런 흐름을 생각해보자.

사용자: 내 이름은 홍길동이야.
AI: 알겠어.

사용자: 내 이름 뭐였지?

두 번째 질문에 답하려면 첫 번째 대화 기록이 필요하다.

Pydantic AI에서는 이전 실행에서 나온 messages를 다음 실행에 넘겨서 대화를 이어갈 수 있다.

first = agent.run_sync('내 이름은 홍길동이야.')

second = agent.run_sync(
    '내 이름 뭐였지?',
    message_history=first.all_messages(),
)

이런 메시지 기록은 챗봇을 만들 때 거의 필수다.

다만 대화가 길어질수록 토큰이 늘어나기 때문에, 실제 서비스에서는 어느 정도 요약하거나 필요한 메시지만 남기는 전략도 필요하다.

Direct Model Requests

Direct Model Requests는 Agent를 거치지 않고 모델에 직접 요청하는 방식이다.

Agent는 많은 걸 관리해준다.

  • instructions
  • deps
  • tools
  • output validation
  • message history
  • hooks

그런데 아주 단순한 모델 호출에는 이 모든 게 필요 없을 수 있다.

예를 들어 짧은 문장 하나를 분류하거나, 내부 테스트용으로 모델 응답만 빠르게 보고 싶을 수 있다. 이런 경우에는 Agent를 만들지 않고 모델에 직접 요청하는 방식이 더 가볍다.

쉽게 말하면:

방식 언제 쓰는지
Agent 역할, tool, deps, output 검증이 필요한 흐름
Direct Model Request Agent까지 필요 없는 단순 모델 호출

초반에는 Agent 중심으로 공부하면 된다. Direct Model Request는 “Agent 없이도 모델만 직접 부를 수 있구나” 정도로 잡아두면 충분하다.

같이 보면 좋은 관계

각 개념을 따로 보면 흩어져 보이는데, 실제로는 이렇게 연결된다.

Agent
 ├─ instructions: 역할 정의
 ├─ deps_type: 실행에 필요한 외부 값 타입
 ├─ tools: LLM이 호출할 수 있는 실제 코드
 ├─ output_type: 최종 결과 구조
 ├─ capabilities: 재사용 가능한 기능 묶음
 ├─ hooks: 실행 중간 처리
 └─ message_history: 이전 대화 기록

예를 들어 쇼핑몰 상담 Agent를 만든다면 이렇게 나눌 수 있다.

개념 쇼핑몰 예시
Agent 쇼핑몰 상담원
instructions 친절하게 주문/배송/환불 문의에 답하라
deps 현재 user_id, DB 연결, 회원 등급
tools 주문 조회, 재고 조회, 장바구니 추가
output 답변 문구, 위험도, 추가 확인 필요 여부
capabilities 웹 검색, thinking, 공통 정책 묶음
hooks 결제/취소 전 승인, 로그 기록
messages 이전 상담 대화

정리

Pydantic AI의 Core Concepts는 전부 Agent를 중심으로 이해하면 된다.

처음부터 모든 기능을 외울 필요는 없다. 우선순위를 잡으면 이 정도가 좋다.

  1. Agent: 실행의 중심
  2. Output: 최종 답변 구조화
  3. Dependencies: 실행마다 달라지는 config + 외부 의존성
  4. Tools: LLM이 호출할 수 있는 실제 코드
  5. Messages: 대화 기록
  6. Capabilities: 기능 묶음
  7. Hooks: 실행 중간 제어
  8. Agent Specs: 설정 파일 기반 Agent 정의
  9. Direct Model Requests: Agent 없이 모델 직접 호출

핵심은 이거다.

Pydantic AI는 LLM에게 모든 걸 맡기는 도구가 아니다. Agent를 중심으로 역할, 외부 데이터, 실행 가능한 코드, 출력 검증, 대화 기록을 묶어서 LLM을 실제 서비스 코드 안에서 안정적으로 쓰게 해주는 프레임워크에 가깝다.


Author: Ruby Kim
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source Ruby Kim !
Comments
  TOC