프로덕션으로 가져가기 전에 점검할 것들
로컬에서 잘 돌아가는 에이전트를 실제 사용자 앞에 내놓기 전에 점검해야 할 것들입니다. 이 장의 항목들은 대부분 "있으면 좋은 것"이 아니라 "없으면 사고 나는 것"에 가깝습니다.
레이트리밋은 사용자당, 도구당 둘 다 걸어야 한다
API 프로바이더가 계정 단위로 레이트리밋을 걸어 주긴 하지만, 그것만 믿으면 사용자 한 명이 짧은 시간에 요청을 반복해서 다른 모든 사용자의 요청이 막히는 상황이 생깁니다.
from collections import defaultdict
import time
_last_call = defaultdict(float)
MIN_INTERVAL_SEC = 2.0
def check_rate_limit(user_id: str) -> bool:
now = time.time()
if now - _last_call[user_id] < MIN_INTERVAL_SEC:
return False
_last_call[user_id] = now
return True여기 예시는 인메모리 딕셔너리라 프로세스가 여러 개면 안 먹힙니다. 실제 배포에서는 Redis 같은 공유 저장소를 씁니다. 그리고 도구 레벨에서도 별도로 걸어야 합니다 — 특히 외부 유료 API를 호출하는 도구라면, 에이전트가 8장에서 본 재시도 패턴에 빠졌을 때 그 도구 하나가 외부 API 비용을 혼자 다 태울 수 있습니다.
로깅은 "무엇을 했는지"가 아니라 "왜 했는지"까지 남긴다
에이전트 로그에 tool_use: get_weather({"city": "서울"}) 정도만 남기면, 나중에 이상 동작을 재현할 때 턱없이 부족합니다. 최소한 다음을 같이 남겨야 합니다.
- 그 시점까지의 전체 메시지 배열(또는 최소한 직전 3턴)
- 6장에서 다룬 추론 텍스트(ReAct 텍스트 블록)
- 사용된 토큰 수와 턴 번호
logger.info("agent_turn", extra={
"turn": turn,
"user_id": user_id,
"tool_calls": [b.name for b in response.content if b.type == "tool_use"],
"reasoning_text": "".join(b.text for b in response.content if b.type == "text"),
"input_tokens": response.usage.input_tokens,
"output_tokens": response.usage.output_tokens,
})이 로그가 없으면 "사용자가 이상한 답을 받았다"는 신고가 들어왔을 때 재현이 거의 불가능합니다. 대화가 확률적이라 같은 입력을 다시 넣어도 같은 결과가 안 나올 수 있기 때문에, 실제로 벌어진 그 순간의 기록이 유일한 증거입니다.
사람이 개입할 지점을 미리 정해 둔다
모든 도구 호출을 자동 승인하면 안 되는 경우가 있습니다. 결제, 삭제, 외부 발송처럼 되돌리기 어려운 작업이 그렇습니다. 이런 도구는 실행 전에 확인 단계를 강제로 넣습니다.
DESTRUCTIVE_TOOLS = {"send_email", "delete_record", "charge_payment"}
def execute_tool(name: str, input: dict, require_confirmation) -> str:
if name in DESTRUCTIVE_TOOLS:
if not require_confirmation(name, input):
return "사용자 확인이 거부되어 실행하지 않았습니다."
return _actual_execute(name, input)"에이전트가 알아서 다 하게 두자"는 목표와 충돌하는 것처럼 보이지만, 실제로는 이 확인 단계가 있어야 에이전트를 더 과감한 작업에 붙일 수 있습니다. 되돌릴 수 없는 실수 하나가 나면 그 뒤로는 팀 전체가 에이전트를 못 믿게 되고, 결국 모든 자동화를 걷어내게 됩니다.
이 책에서 다루지 않은 것
솔직히 말하면 이 책은 멀티 에이전트 오케스트레이션, 벡터 검색을 이용한 RAG 결합, 파인튜닝으로 도구 호출 정확도를 높이는 법은 다루지 않았습니다. 각각이 책 한 권 분량입니다. 여기서 짠 순수 루프, Tool Use 계약, ReAct 패턴은 그 모든 것의 바닥에 깔리는 재료이고, 그 위에 뭘 얹을지는 실제로 부딪히는 문제에 따라 달라집니다. 프레임워크 문서를 다시 펼치기 전에, 이 책에서 만든 60줄짜리 루프를 한번 더 돌려 보길 권합니다 — 프레임워크가 뭘 대신해 주고 뭘 안 해 주는지가 그제서야 눈에 들어옵니다.