Pydantic AI 에이전트를 위한 Human-in-the-Loop 구현
요약
Pydantic AI 에이전트의 도구 호출 과정에서 인간의 승인을 강제하는 Human-in-the-Loop 구현 방법을 설명합니다. 시스템 프롬프트 대신 도구 함수 내부에 승인 로직을 삽입하여 모델의 주의력 분산 문제를 해결하고 실행 신뢰성을 높이는 방법을 다룹니다.
핵심 포인트
- 프롬프트 지시 대신 도구 함수 내부에 승인 로직을 구현하여 신뢰성 확보
- Impri의 approval_gate를 활용한 비동기 컨텍스트 매니저 방식 적용
- 예외 처리를 통해 에이전트가 거절된 요청을 재시도하지 않도록 제어
- 비동기 게이트 사용을 위한 에이전트 실행 환경의 비동기 전환 필요성
도구 경계(tool boundary)에서 Pydantic AI 에이전트를 위한 Human-in-the-Loop를 추가하세요: 환불 도구를 Impri의 approval_gate로 감싸면, 사람이 승인하기 전까지는 어떤 비용 청구도 취소되지 않습니다.
시스템 프롬프트가 아닌 도구 함수를 사용해야 하는 이유
stripe.refund 형태의 도구를 가진 Pydantic AI 에이전트는 결국 고객의 말만 듣고 해당 도구를 호출하게 될 것입니다. 왜냐하면 시스템 프롬프트(system prompt)가 그렇게 도움이 되는 역할을 하라고 지시했기 때문입니다. 프롬프트에 "환불하기 전에 항상 물어보세요"라고 모델에게 말하는 것은 대화가 길어지거나 고객이 완강하게 요구할 경우 유지되지 않습니다. 해당 지침이 모델의 주의력(attention)을 두고 나머지 컨텍스트와 경쟁하게 되기 때문입니다.
신뢰할 수 있는 버전은 체크 로직을 도구 함수(tool function) 자체에 넣는 것입니다. 이곳에서는 모델이 대화로 이를 우회할 방법이 없습니다. 에이전트는 여전히 issue_refund를 호출할 '시기'를 결정하지만, 환불이 실제로 일어날지 여부는 모델이 아닌 함수의 본문(body)이 결정합니다.
인간의 승인 게이트가 포함된 환불 도구
import os
import stripe
from dataclasses import dataclass
...
approval_gate는 SDK의 컨텍스트 매니저(context-manager) 형태입니다. 이는 동작을 밀어넣고(pushes), 사람이 결정할 때까지 차단(blocks)하며, 나가는 과정에서 report_result를 자동으로 호출합니다. 정상적으로 종료되면 executed를, 블록 내부의 stripe.Refund.create 호출에서 예외가 발생하면 execute_failed를 호출합니다. 전체 메서드 참조는 Python SDK를 참조하세요.
도구 외부가 아닌 도구 내부에서 거절 처리하기
try/except 문이 게이트 전체를 감싸며 issue_refund '내부'에 위치한다는 점에 주목하세요. 만약 ImpriRejected가 상위로 전파되도록 내버려 두면, Pydantic AI의 도구 호출 루프(tool-calling loop)는 도구 호출로부터 처리되지 않은 예외(unhandled exception)를 감지하게 됩니다. 재시도(retry) 설정에 따라 에이전트는 이를 일시적인 실패로 해석하고 동일한 인수로 issue_refund를 다시 호출할 수 있으며, 이는 사람이 명시적으로 거절한 이후에 결코 일어나서는 안 될 일입니다. 이를 잡아(Catching) 일반 문자열을 반환하면 "거절됨"이 일반적인 도구 출력(tool output)이 됩니다. 에이전트는 이를 읽고, 고객에게 환불이 진행되지 않았음을 알린 뒤 다음 단계로 넘어갑니다.
동기 에이전트, 비동기 게이트
approval_gate는 비동기 컨텍스트 매니저 (async context manager)이므로, issue_refund는 async def로 선언되어야 하며 실행 시 agent.run_sync(...) 대신 await agent.run(...)을 사용하여 구동해야 합니다. 에이전트의 나머지 부분이 동기적 (synchronous)이더라도, 이 도구 하나 때문에 진입점 (entry point)을 비동기 형태로 전환해야 할 수도 있습니다. Pydantic AI는 동일한 에이전트 내에서 동기 도구와 비동기 도구를 혼합하여 사용하는 것을 지원하지만, 게이트 (gate) 자체는 비동기로만 제공됩니다.
실제로 검증되는 것과 검증되지 않는 것
| 예외 (Exception) | 의미 | 도구가 수행하는 작업 |
|---|---|---|
| (없음 — 승인됨) | 사람이 카드를 읽고 승인함 | Stripe를 호출하고 executed를 보고함 |
| ... |
Impri는 사람이 표시된 카드(고객 ID, 금액, 사유)를 정확히 확인하고 승인했음을 검증했습니다. customer_id가 올바른지, 금액이 실제 초과 청구액과 일치하는지, 또는 Stripe의 응답에 관한 사항 등은 검증하지 않았습니다. 그러한 작업은 에이전트와 귀하의 결제 시스템 (billing system)의 역할입니다. 또한, 이 게이트는 issue_refund가 이 에이전트에서 stripe.Refund.create로 가는 유일한 경로일 때만 유효합니다. 자체적인 Stripe 키를 가진 두 번째 도구가 있다면 이를 완전히 우회할 수 있습니다.
다음 단계
기저에 깔린 REST 패턴에 대해서는 How to add human approval to an AI agent를 참조하거나, 이를 실제 에이전트에 연결하기 전에 API 키를 발급받으려면 Quickstart를 확인하세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기