에이전트 실패를 줄이는 통제 장치
도구를 쓰는 에이전트의 실패는 보통 한 문장의 오답으로 끝나지 않는다. 한 번 잘못 호출한 검색, 한 번 불필요하게 반복한 조회, 한 번 성급하게 실행한 쓰기 작업이 이어지면 실패는 곧 비용, 지연, 보안 사고, 운영 혼선으로 번진다. 더구나 여러 시스템을 가로질러 행동하는 에이전트는 단순한 채팅 인터페이스가 아니라 작은 제어면처럼 행동하기 쉽다.1 그래서 고급 설계에서 먼저 물어야 할 질문은 "이 에이전트가 얼마나 똑똑한가"가 아니라 "망가질 때 얼마나 작게 망가지는가"다.
유능한 에이전트보다 먼저 필요한 것은 망가지지 않는 에이전트다. 똑똑한데 멈추지 못하는 시스템은, 조금 덜 똑똑하지만 확실히 멈출 줄 아는 시스템보다 실무에서 더 위험하다.

먼저 막아야 할 실패는 오답보다 폭주다
사람은 보통 AI 실패를 "틀린 답변"으로 상상한다. 하지만 에이전트 운영에서는 더 비싼 실패가 따로 있다. 같은 도구를 다섯 번 반복 호출한다든지, 이미 충분한 근거가 있는데도 또 검색한다든지, 읽기 작업만으로 끝낼 일을 쓰기 작업으로 밀어붙인다든지 하는 식의 실패다.
이런 실패가 무서운 이유는 겉으로는 그럴듯해 보이기 때문이다. 마지막 답변만 보면 큰 문제가 없어 보일 수 있다. 그런데 내부에서는 도구 호출 수가 늘고, 지연이 커지고, 승인 경계를 자꾸 건드리고, 사람 검토 대기열만 쌓인다. 다시 말해 에이전트의 실패는 종종 정답률보다 먼저 운영 품질에서 드러난다.
그래서 통제 장치는 모델을 덜 자유롭게 만드는 족쇄가 아니다. 오히려 시스템이 오래 버티게 만드는 서스펜션에 가깝다. 도로가 완벽하지 않다는 사실을 인정하고, 충격을 견디도록 설계하는 일이다.
무한 루프는 왜 생기는가
무한 루프는 대개 모델이 특별히 멍청해서가 아니라, "계속해도 되는 조건"과 "멈춰야 하는 조건"이 흐리기 때문에 생긴다. 에이전트는 기본적으로 다음 행동을 계속 제안하는 쪽으로 기운다. 무엇이 진전인지, 무엇이 실패 반복인지, 언제 사람에게 넘겨야 하는지가 명확하지 않으면 시스템은 쉽게 제자리걸음을 시작한다.
실무에서 자주 보는 루프는 대체로 세 종류다.
동일 호출 반복 루프: 같은 질의를 거의 그대로 다시 호출한다. 실패 원인이 인증 오류인데도 검색어만 조금 바꿔 다시 시도하는 식이다.
유사 호출 우회 루프: 겉보기에는 다른 행동 같지만 목적이 같다. 서로 다른 검색 도구를 번갈아 쓰며 같은 정보를 찾는 경우가 여기에 들어간다.
복구 시도 루프: 실패를 복구하려고 재시도하다가 오히려 더 오래 헤맨다. 특히 외부 API 오류나 권한 부족 상황에서 자주 나타난다.
이 세 종류의 공통점은 하나다. 환경 상태가 거의 바뀌지 않았는데도 에이전트만 계속 움직인다는 점이다. 그러니 루프 방지는 "몇 번까지 허용할까"만의 문제가 아니다. "무엇이 실제 진전인가"를 먼저 정의해야 한다.
루프를 끊는 브레이크는 숫자 하나가 아니다
가장 먼저 넣어야 할 브레이크는 예산이다. 최대 단계 수, 최대 재시도 수, 최대 도구 호출 수를 정하지 않으면 루프는 언젠가 반드시 생긴다. 많은 프레임워크가 아예 도구 호출 상한을 별도 옵션으로 제공하는 이유도 여기에 있다.2 하지만 상한만으로는 부족하다. 다섯 번 안에 충분히 크게 망가질 수도 있기 때문이다.
정말 중요한 것은 진행 판정이다. 에이전트는 매 단계 뒤에 "새로운 검증 가능한 사실을 얻었는가", "환경 상태가 바뀌었는가", "불확실성이 줄었는가"를 확인해야 한다. 이 셋 중 하나도 충족하지 못했다면, 그 실행은 사실상 제자리걸음일 가능성이 크다.
루프를 줄이는 핵심 장치는 네 가지다.
단계 예산: 한 번의 실행에서 몇 단계까지 갈 수 있는지 제한한다. 단계 수는 에이전트의 체력이자 브레이크다.
상태 중복 감지: 최근 몇 단계의 도구 이름, 주요 인자, 결과 요약을 묶어 상태 서명을 만들고, 같은 서명이 반복되면 중단한다.
재시도 분류: 네트워크 일시 장애처럼 재시도 가치가 있는 실패와, 권한 부족처럼 재시도해도 소용없는 실패를 구분한다.
진행률 검사: 새 근거, 새 상태 변화, 새 승인 중 하나라도 없으면 다음 행동 대신 중단 또는 에스컬레이션을 택한다.
여기서 특히 중요한 것은 재시도 분류다. 모든 실패를 "다시 한 번 해 보자"로 처리하면 에이전트는 부지런하게 폭주한다. 반대로 실패를 유형별로 나누면 훨씬 차분해진다. 예를 들어 일시적 타임아웃은 1회 재시도, 인증 오류는 즉시 중단, 권한 부족은 사람 승인 요청, 입력 부족은 사용자에게 질문으로 연결하는 식이다.
좋은 에이전트는 많이 시도하는 에이전트가 아니다. 실패의 종류에 따라 다르게 멈추는 에이전트다.
불필요한 도구 호출은 똑똑함이 아니라 낭비다
도구를 많이 쓰는 에이전트가 더 유능해 보일 수 있다. 하지만 실제 운영에서는 반대인 경우가 많다. 쓸데없는 조회가 늘수록 비용은 올라가고, 지연은 길어지고, 외부 시스템 의존성은 커진다. 심지어 잘못된 도구를 한 번 고르는 것만으로도 뒤의 판단 전체가 흔들릴 수 있다.
그래서 도구 호출은 "할 수 있으면 한다"가 아니라 "정말 필요할 때만 한다"가 기본 원칙이어야 한다. 도구 사용을 평가할 때도 단순히 실행 성공 여부만 보면 안 된다. 올바른 도구를 골랐는지, 인자가 적절했는지, 사용자의 의도와 맞았는지, 이전 맥락을 반영했는지, 실패했을 때 제대로 복구했는지까지 함께 봐야 한다.3
불필요한 호출을 줄이려면 먼저 에이전트에게 한 가지 습관을 심어야 한다. 답변, 질문, 도구 호출 중 무엇이 지금 가장 싼 다음 행동인지 먼저 고르게 하는 것이다. 정보가 이미 충분하면 답변해야 하고, 핵심 입력이 빠졌다면 질문해야 하며, 외부 세계의 사실이 정말 필요할 때만 도구를 불러야 한다.
이때 도구 호출 전 점검표가 큰 효과를 낸다. 지금 필요한 정보가 정말 내부 컨텍스트 밖에 있는가. 이미 같은 정보를 조금 전에 얻지 않았는가. 읽기 전용 호출만으로 충분한가. 이 도구가 아니면 안 되는가. 이 네 질문만 거쳐도 도구 남발이 크게 줄어든다.
또 하나 중요한 것은 모델에게 사소한 반복 조회를 하나하나 맡기지 않는 것이다. 예를 들어 스무 건의 레코드를 조회하고 그중 조건에 맞는 몇 건만 골라야 한다면, 모델이 스무 번의 도구 호출을 계획하게 두는 것보다 프로그램이 일괄 조회와 필터링을 끝낸 뒤 요약 결과만 모델에 넘기는 편이 훨씬 안정적이다. 실제로 프로그램 방식의 도구 호출은 모델이 다뤄야 할 맥락을 크게 줄여 준다.4
결국 좋은 도구 사용은 "도구를 잘 부른다"가 아니라 "도구를 아껴서 정확히 부른다"에 가깝다.
도구는 열어 두되, 자격은 좁게 줘야 한다
에이전트 설계에서 흔한 착각이 있다. 도구를 많이 연결해 두면 에이전트가 더 강해진다고 믿는 것이다. 하지만 실무에서는 연결된 도구 수보다 더 중요한 것이 있다. 각 도구를 어떤 조건에서, 어떤 범위까지, 누구 대신 사용할 수 있는가다.
특히 읽기와 쓰기를 같은 수준의 권한으로 다루면 금방 사고가 난다. 조회는 되돌릴 수 있지만, 수정은 흔적을 남긴다. 초안 작성은 제안이지만, 발송은 실행이다. 검색은 정보 획득이지만, 계정 잠금 해제는 상태 변경이다. 이 차이를 프롬프트 문구 하나로만 관리하면 언젠가 무너진다.
실무적으로는 도구를 네 부류로 나누는 편이 안전하다.
observe: 조회, 검색, 읽기처럼 상태를 바꾸지 않는 도구
propose: 초안 작성, 추천안 생성처럼 실행 전 제안을 만드는 도구
mutate: 생성, 수정, 삭제처럼 실제 상태를 바꾸는 도구
export: 외부 전송, 다운로드, 공유처럼 경계 밖으로 데이터를 내보내는 도구
이 네 부류는 이름 장난이 아니다. 승인 규칙과 예산 규칙을 붙이기 위한 최소 단위다. observe는 비교적 넓게 허용할 수 있어도, mutate와 export는 훨씬 좁게 묶어야 한다.
권한 경계의 핵심은 "모델 출력은 제안일 뿐"이라는 원칙이다
에이전트가 안전해지려면, 모델이 도구 호출을 제안할 수는 있어도 스스로 허가할 수는 없어야 한다. 다시 말해 모델 출력은 권한의 근거가 아니라 검토 대상이어야 한다.5 이 원칙이 빠지면 프롬프트 한 줄이 곧 실행 권한처럼 작동하게 된다.
여기서 중요한 것은 높은 가치의 정보를 모델이 직접 만들어 내지 못하게 하는 것이다. 예를 들어 tenant_id, user_id, 작업 환경, 허용된 리소스 범위 같은 값은 사용자 세션이나 인증 계층에서 가져와야 한다. 모델은 그것을 참조할 수는 있어도, 임의로 생성하거나 바꿔서는 안 된다. 계정 번호, 저장소 이름, 승인 상태, 운영 환경 같은 값이 자연어 문맥 속에서 슬쩍 결정되기 시작하면 권한 경계는 사실상 무너진다.
이 구조를 더 단단하게 만들려면 planner와 executor 사이뿐 아니라, 정책 판단기와 실행기를 분리해야 한다. 에이전트는 "무엇을 하고 싶은지"를 말하고, 정책 계층은 "해도 되는지"를 판단하며, 실행기는 "허용된 요청만 실제로 보낸다"는 식이다. 이때 동일한 요청 형식을 기준으로 정책과 실행이 움직여야 나중에 재현과 감사도 가능해진다.5
이 원칙은 보안만을 위한 것이 아니다. 운영 품질에도 직접 연결된다. 권한 경계가 분명하면 에이전트는 스스로를 덜 과신한다. 할 수 없는 일은 빨리 승인 요청으로 넘기고, 허용되지 않은 시스템 경계는 건드리지 않는다. 영리함은 조금 줄어드는 것처럼 보여도, 실패 비용은 훨씬 작아진다.
사람 검토는 실패 뒤의 사후 처리 장치가 아니다
많은 팀이 사람 검토를 "마지막에 한 번 확인하는 절차" 정도로 생각한다. 하지만 제대로 설계된 사람 검토는 마지막 장식이 아니다. 실행 경계를 정의하는 핵심 장치다. 어떤 경우에 자동으로 진행하고, 어떤 경우에 반드시 멈추고, 어떤 경우에 사람이 최종 거부권을 행사하는지 미리 정하는 일이 바로 사람 검토 설계다.67
여기서 중요한 단어는 "의미 있는 검토"다. 사람 이름만 찍혀 있다고 검토가 되는 것은 아니다. 검토자는 충분한 정보, 적절한 권한, 실제로 반려할 수 있는 독립성, 그리고 따라야 할 체크리스트를 가져야 한다.6 그렇지 않으면 사람 검토는 자동화의 책임을 가리는 장식으로 전락한다.
사람 검토 지점은 보통 다음 상황에 두는 것이 효과적이다.
고위험 쓰기 작업 직전: 계정 변경, 결제 실행, 티켓 발행, 외부 발송처럼 되돌리기 어렵거나 비용이 큰 작업
정책 충돌 또는 권한 경계 접촉 시점: 금지 범위 가능성이 있거나, 다른 시스템 경계로 넘어가려는 순간
불확실성이 높을 때: 근거가 충돌하거나, 필요한 정보가 빠졌거나, 모델이 여러 가설을 좁히지 못했을 때
반복 실패 뒤: 같은 원인으로 여러 번 막혔을 때 더 자동화하지 않고 사람에게 넘기는 지점
예외 케이스 감지 시: 평소와 다른 입력 형식, 드문 업무, 민감정보 포함 가능성이 큰 요청
좋은 검토 지점은 단순히 "여기서 승인받아"가 아니다. 검토자가 무엇을 보고 판단할지까지 함께 설계해야 한다. 이상적인 검토 패키지에는 사용자 요청 요약, 에이전트가 제안한 행동, 근거 데이터, 적용된 정책 결과, 예상되는 부작용, 승인 유효시간이 함께 들어 있어야 한다. 그래야 검토자가 처음부터 다시 추리하지 않고도 책임 있는 판단을 할 수 있다.
그리고 한 가지를 더 분명히 해야 한다. 사람이 시스템의 거부를 무시하고 실행을 강행할 수는 있다. 하지만 그 순간 책임도 함께 넘어와야 한다.7 override는 편의 기능이 아니라 책임 이전 행위다. 이 원칙이 빠지면 누구도 최종 결정자가 아닌 위험한 회색지대가 생긴다.
승인 지점은 적을수록 좋은 것이 아니라, 정확할수록 좋다
사람 검토를 너무 많이 넣으면 에이전트는 느려지고, 너무 적게 넣으면 사고가 난다. 그래서 핵심은 개수가 아니라 위치다. 모든 단계에 승인 버튼을 달아 두는 것은 통제가 아니라 마찰일 뿐이다. 반대로 정말 위험한 전환점에만 검토를 배치하면, 사람의 시간을 적게 쓰면서도 실패 비용을 크게 줄일 수 있다.
가장 실용적인 방식은 단계 전체가 아니라 전환점에 검토를 두는 것이다. 읽기에서 쓰기로 넘어가는 순간, 내부 검토에서 외부 발송으로 넘어가는 순간, 단일 시스템 작업에서 다중 시스템 체인으로 넘어가는 순간, 자동 판단에서 예외 처리로 넘어가는 순간이 대표적이다. 에이전트는 대부분 이런 전환점에서 사고를 낸다.
이 관점으로 보면 사람 검토는 에이전트의 반대편에 있는 존재가 아니다. 에이전트가 다룰 수 있는 영역과 다루면 안 되는 영역의 경계석에 가깝다.
실패를 작게 만드는 운영 루프
통제 장치는 많아 보이지만, 실제 운영 루프는 의외로 단순하게 만들 수 있다.
첫째, 요청을 받으면 곧바로 도구를 고르지 말고 작업 유형을 판별한다. 바로 답변 가능한지, 사용자에게 먼저 물어야 하는지, 읽기 도구가 필요한지, 쓰기 작업이 필요한지를 먼저 가른다.
둘째, 이번 실행의 예산을 정한다. 최대 단계 수, 최대 도구 호출 수, 허용 도구 등급, 승인 필요 여부를 이 시점에 함께 묶는다.
셋째, 도구 호출 전 사전 점검을 한다. 같은 정보가 이미 있는지, 더 싼 방법이 있는지, 지금 필요한 것이 조회인지 실행인지 확인한다.
넷째, 한 단계만 실행하고 결과를 정규화한다. 원본 로그를 그대로 넘기지 말고, 핵심 사실과 실패 유형과 재시도 가능 여부를 짧게 구조화한다.
다섯째, 진행 여부를 판정한다. 새로운 근거가 생겼는지, 상태 변화가 있었는지, 불확실성이 줄었는지를 보고 다음 단계로 갈지 멈출지 결정한다.
여섯째, 쓰기·전송·권한 상승 같은 경계에 도달하면 자동 진행을 멈추고 사람 검토 또는 별도 승인 계층으로 넘긴다.
이 루프의 장점은 화려하지 않다는 데 있다. 하지만 바로 그 점이 중요하다. 실무에서 필요한 것은 멋진 추론 데모가 아니라, 실패해도 설명 가능하고 중단 가능하며 감사 가능한 흐름이다.
망가지지 않는 에이전트의 최소 조건
마지막으로 이번 장의 요점을 가장 실무적으로 줄이면 이렇다.
에이전트는 멈춤 규칙이 있어야 한다.
도구 호출은 필요성 판정을 거쳐야 한다.
모델 출력은 권한이 아니라 제안으로 취급해야 한다.
사람 검토는 장식이 아니라 최종 경계여야 한다.
이 네 가지가 없으면 에이전트는 똑똑해 보일 수는 있어도 운영하기 어렵다. 반대로 이 네 가지가 갖춰지면, 에이전트가 완벽하지 않아도 실무 안에서 다룰 수 있는 시스템이 된다.
결국 통제 장치의 목적은 모델을 믿지 않겠다는 선언이 아니다. 믿음이 흔들리는 순간에도 시스템이 버틸 수 있게 만드는 것이다. 좋은 에이전트는 계속 달리는 에이전트가 아니라, 어디서 멈춰야 하는지 아는 에이전트다.
참고
1Agentic AI Has a Control Plane Problem — Because It Became the Control Plane
3Tool Call Evaluation - Multi-agent Reference Architecture
4Programmatic tool calling - Claude API Docs
5Designing a Replayable Authorization Control Plane for Agentic Systems
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.