k
korAI
고급 전체
🔥 고급2026-09-046~8분

멀티 에이전트 환경에서 안전한 Tool 실행 패턴

오케스트레이터-서브에이전트 구조에서 tool 호출은 권한 경계 없이 설계하면 prompt injection과 권한 에스컬레이션의 직접 경로가 된다. 실행 전 검증 레이어와 최소 권한 원칙을 코드로 구현하는 방법을 다룬다.

multi-agenttool-safetysecurity

왜 멀티 에이전트 tool이 위험한가

단일 에이전트와 달리 오케스트레이터가 서브에이전트에게 tool 호출을 위임할 때, 서브에이전트가 받은 외부 데이터(웹 스크래핑 결과, DB 레코드 등)에 악의적 명령이 포함될 수 있다. 서브에이전트는 이를 정상 지시로 오해하고 파일 삭제·외부 API 호출 등을 실행한다. 이것이 indirect prompt injection이다.

핵심 방어 원칙:

  • 각 에이전트에 최소 필요 tool만 바인딩
  • tool 실행 전 정책 검증 레이어 삽입
  • 오케스트레이터는 서브에이전트 결과를 신뢰하지 않고 재검증
import anthropic
from typing import Any

client = anthropic.Anthropic()

# 정책: 허용 tool × 허용 인자 범위 정의
TOOL_POLICY = {
    "read_file": {"allowed_dirs": ["/data/readonly"]},
    "send_email": {"allowed_domains": ["company.com"]},
}

def validate_tool_call(name: str, inputs: dict) -> bool:
    policy = TOOL_POLICY.get(name)
    if policy is None:
        return False  # 화이트리스트 외 tool 전면 차단
    if name == "read_file":
        path: str = inputs.get("path", "")
        return any(path.startswith(d) for d in policy["allowed_dirs"])
    if name == "send_email":
        to: str = inputs.get("to", "")
        domain = to.split("@")[-1]
        return domain in policy["allowed_domains"]
    return False

def run_subagent(task: str, tools: list) -> Any:
    response = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=512,
        system="당신은 제한된 권한의 서브에이전트입니다. 지시된 작업만 수행하세요.",
        messages=[{"role": "user", "content": task}],
        tools=tools,
    )
    for block in response.content:
        if block.type == "tool_use":
            if not validate_tool_call(block.name, block.input):
                raise PermissionError(
                    f"Tool 정책 위반: {block.name}({block.input})"
                )
            # 검증 통과 후 실제 실행
            print(f"[SAFE EXEC] {block.name} with {block.input}")
    return response

트레이드오프와 실패 모드

| 접근 방식 | 보안 | 유연성 | 운영 복잡도 | |---|---|---|---| | 화이트리스트 없음 | 낮음 | 높음 | 낮음 | | 화이트리스트만 | 중간 | 중간 | 중간 | | 화이트리스트 + 인자 검증 | 높음 | 중간 | 높음 | | 별도 샌드박스 실행 | 매우 높음 | 낮음 | 매우 높음 |

주요 실패 모드

  1. 오케스트레이터가 서브에이전트 출력을 그대로 system prompt에 삽입 → injection 전파
  2. tool 결과에 JSON 이스케이프 없이 외부 데이터 포함 → 파서 우회
  3. 에러 발생 시 전체 tool 권한으로 재시도 → 권한 에스컬레이션

운영 체크리스트

  • [ ] 서브에이전트별 tool 바인딩 목록 문서화 및 코드 리뷰 필수
  • [ ] validate_tool_call 실패 시 즉시 파이프라인 중단 (재시도 금지)
  • [ ] tool 실행 로그를 별도 감사 스트림으로 분리 (앱 로그와 혼용 금지)
  • [ ] 외부 데이터 수집 tool 결과는 반드시 sanitize 후 다음 에이전트 컨텍스트에 전달
  • [ ] 월 1회 tool 정책 리뷰: 실제 사용 tool과 허용 목록 일치 여부 확인