🔥 고급2026-06-256~8분
멀티 에이전트 환경에서 안전한 Tool 실행: 격리·타임아웃·감사 로그 설계
에이전트가 코드 실행·파일 쓰기·외부 API 호출을 병렬로 수행할 때 발생하는 경쟁 조건과 무한 루프를 차단하는 실전 아키텍처를 다룬다.
multi-agenttool-safetyreliability
멀티 에이전트 Tool 실행의 실패 모드
단일 에이전트도 위험하지만 멀티 에이전트는 실패가 연쇄된다. 대표적 패턴은 다음 세 가지다.
- 무한 tool 루프: 에이전트 A가 에이전트 B를 호출하고, B가 다시 A의 tool을 호출하는 순환. 실제 사례에서 3분 안에 API 비용이 $40 초과했다.
- 경쟁 쓰기: 두 에이전트가 동일 파일·DB 레코드를 동시에 수정해 데이터 손상.
- 탈출 없는 재시도: tool 오류 시 에이전트가 자체 판단으로 무제한 재시도.
격리 레이어 설계
안전한 멀티 에이전트 시스템은 Orchestrator → Tool Gateway → Executor 3계층으로 분리한다.
- Orchestrator: Claude API 호출 및 tool_use 블록 파싱만 담당. 실제 IO 없음.
- Tool Gateway: 허용 tool 목록 화이트리스트, 호출 횟수 한도(예: 세션당 50회), 중복 호출 디바운스.
- Executor: 샌드박스(Docker/subprocess)에서 실행, 타임아웃 강제.
아래는 Gateway 레이어에서 타임아웃과 호출 한도를 강제하는 예시다.
import anthropic
import asyncio
from collections import defaultdict
client = anthropic.Anthropic()
class ToolGateway:
def __init__(self, max_calls: int = 50, timeout_sec: float = 10.0):
self.max_calls = max_calls
self.timeout_sec = timeout_sec
self.call_count: dict[str, int] = defaultdict(int)
async def execute(self, session_id: str, tool_name: str, tool_input: dict) -> dict:
self.call_count[session_id] += 1
if self.call_count[session_id] > self.max_calls:
raise RuntimeError(f"[{session_id}] tool 호출 한도 초과: {self.max_calls}회")
try:
result = await asyncio.wait_for(
self._run_tool(tool_name, tool_input),
timeout=self.timeout_sec
)
return {"status": "ok", "result": result}
except asyncio.TimeoutError:
return {"status": "error", "reason": f"{tool_name} timeout after {self.timeout_sec}s"}
async def _run_tool(self, name: str, inputs: dict) -> str:
# 실제 tool 로직 (파일 읽기, API 호출 등)
await asyncio.sleep(0.1) # placeholder
return f"{name} 실행 완료"
gateway = ToolGateway(max_calls=50, timeout_sec=10.0)
Orchestrator는 tool_use 블록을 받으면 Gateway를 통해서만 실행하고, Gateway 응답을 tool_result로 반환한다. Claude API를 직접 재호출하는 로직은 Orchestrator에만 존재해야 한다.
감사 로그와 조기 종료 조건
감사 로그는 최소한 다음 필드를 포함해야 한다: session_id, tool_name, input_hash, duration_ms, status, agent_depth. agent_depth가 5를 초과하면 강제 종료한다.
수치 기준선 (실험 기반)
- tool 타임아웃: 10초 (LLM 기반 tool은 30초)
- 세션당 최대 tool 호출: 50회
- 최대 에이전트 중첩 깊이: 5
- 에러율 > 30% 시 자동 circuit break
운영 체크리스트
- [ ] 모든 tool 실행이 Gateway를 경유하는지 코드 리뷰로 확인
- [ ]
agent_depth카운터를 context 객체로 하위 에이전트에 전달 - [ ] tool 호출 로그를 세션 단위로 집계해 비용 이상 감지 알람 설정
- [ ] 타임아웃 에러는 재시도 없이
tool_result로 에이전트에 반환 (재시도는 에이전트가 판단) - [ ] 동일
input_hash의 tool이 1분 내 3회 이상 호출되면 순환 감지로 종료