이미 돌아가고 있는 에이전트의 툴 구성을 감사해 과잉 권한과 과잉 선택지를 찾아냅니다. 툴을 어떻게 만드는지가 아니라, 이미 붙어 있는 툴 30개 중 무엇을 떼어낼지 판단하는 것이 이 수업의 주제입니다.
비대화는 두 층에서 일어난다
기능 비대화(capability bloat)라는 말은 두 가지 서로 다른 문제를 함께 가리킵니다. 진단할 때 이 둘을 분리하지 않으면 엉뚱한 처방이 나옵니다.
권한 비대화는 에이전트가 할 수 있는 일이 실제로 해야 할 일보다 넓은 상태입니다. 고객 지원 에이전트에 계정 삭제 툴이 붙어 있는 경우가 여기에 해당합니다. 위험은 보안입니다.
선택지 비대화는 에이전트에 제시된 툴 목록이 너무 길어 모델이 매번 무엇을 쓸지 헷갈리는 상태입니다. 서로 경계가 흐릿한 유사 툴이 여럿 있으면 선택 정확도가 떨어집니다. 위험은 품질과 비용입니다.
같은 "툴이 너무 많다"는 증상이지만 처방이 다릅니다.
| 층 | 증상 | 처방 |
|---|---|---|
| 권한 | 감사 로그에 쓰인 적 없는 파괴적 툴이 있다 | 제거한다 |
| 선택지 | 모델이 비슷한 툴 두 개를 번갈아 잘못 고른다 | 경계를 명확히 하거나 병합한다 |
| 선택지 | 툴이 수십 개인데 요청마다 쓰이는 건 두세 개다 | 점진적 로딩으로 옮긴다 |
공식 요강의 예시 문항이 묻는 것은 권한 층입니다. 지원 담당자가 티켓 읽기와 답변 초안 작성만 한다면, 환불과 계정 삭제 툴은 구성에서 아예 빼는 것이 정답입니다. 로깅을 붙이는 것도, 실행 전 확인 프롬프트를 넣는 것도 답이 아닙니다. 로깅은 사후에 알아차리게 해줄 뿐 사고 자체를 막지 못하고, 확인 프롬프트는 사람이 무심코 승인하면 뚫립니다. 최소 권한(least privilege)은 감시하는 것이 아니라 없애는 것입니다.
권한 층 감사: 되돌릴 수 있는가
툴 목록을 앞에 놓고 하나씩 두 질문을 던집니다.
- 이 역할이 실제로 이 능력을 쓰는가? (로그로 확인, 추측 금지)
- 이 툴이 잘못 호출되면 되돌릴 수 있는가?
두 질문의 답을 교차하면 처리 방침이 나옵니다.
| 되돌릴 수 있음 | 되돌리기 어려움 | |
|---|---|---|
| 쓴다 | 그냥 허용 | 실행 전 사람 확인 |
| 안 쓴다 | 제거 | 최우선 제거 |
되돌리기 어려운 행동은 외부로 나가는 것들입니다. 메일 발송, 결제, 데이터 삭제, 공개 게시. 이런 행동을 하는 툴은 범용 bash 툴 뒤에 숨겨두면 안 됩니다. bash 하나만 있으면 하네스(harness) 입장에서는 모든 행동이 똑같은 불투명한 명령 문자열로 보여서, 위험한 것만 골라 막을 방법이 없습니다.
같은 행동을 전용 툴로 승격시키면 하네스가 그 행동에만 훅을 걸 수 있습니다.
# 전: bash 하나로 모든 것을 한다 — 하네스는 무엇이 위험한지 모른다
tools = [{"type": "bash_20250124", "name": "bash"}]
# 후: 되돌리기 어려운 행동만 전용 툴로 승격
tools = [
{"type": "bash_20250124", "name": "bash"}, # 읽기·조회용
{
"name": "send_email", # 하네스가 여기에만 승인 게이트를 건다
"description": "고객에게 메일을 발송합니다. 발송 후 취소할 수 없습니다.",
"input_schema": {
"type": "object",
"properties": {
"to": {"type": "string"},
"subject": {"type": "string"},
"body": {"type": "string"},
},
"required": ["to", "subject", "body"],
},
},
]
승격의 이점은 승인만이 아닙니다. 읽기 전용 툴은 병렬 실행해도 안전하다고 표시할 수 있는 반면, bash 뒤에 섞여 있으면 하네스는 안전한 조회와 위험한 쓰기를 구별할 수 없어 전부 순차 실행해야 합니다.
선택지 층 감사: 툴 목록도 컨텍스트다
툴 정의는 요청마다 컨텍스트에 실립니다. 툴이 40개면 40개 분량의 스키마와 설명이 매 요청 앞부분을 차지합니다. 이것은 두 가지 비용을 만듭니다.
- 토큰 비용 — 쓰이지 않는 툴의 스키마도 매번 값을 치릅니다.
- 선택 비용 — 후보가 많을수록 모델이 잘못 고를 여지가 커집니다.
특히 위험한 것은 경계가 겹치는 유사 툴입니다. search_docs와 find_document가 나란히 있으면 모델은 매번 둘 중 하나를 골라야 하고, 어느 쪽을 골라도 그럴듯해 보이기 때문에 실수를 스스로 알아차리지 못합니다. 이럴 때는 툴을 합치거나, 각 툴의 description에 언제 쓰지 않아야 하는지까지 적어 경계를 세웁니다.
툴이 정말 많아야 하는 경우 — 사내 시스템 수십 개를 다루는 에이전트 — 에는 전부 상주시키는 대신 툴 검색(tool search) 으로 옮깁니다. 툴 정의에 defer_loading: true를 붙이면 그 툴은 요청에 선언되어 있되 필요해질 때까지 컨텍스트에 로드되지 않습니다.
tools = [
{"type": "tool_search_tool_regex_20251119", "name": "tool_search_tool_regex"},
# 아래 툴들은 검색으로 발견되기 전까지 컨텍스트를 차지하지 않는다
{"name": "query_billing", "description": "...", "input_schema": {...},
"defer_loading": True},
{"name": "query_inventory", "description": "...", "input_schema": {...},
"defer_loading": True},
]
두 가지 함정이 있습니다. 검색 툴 자체에는 defer_loading을 붙이면 안 되고, 전부 지연 로딩으로 돌리면 API가 400 오류를 냅니다. 최소 하나는 상주해야 합니다.
또 하나 알아둘 점은 툴 검색이 캐시를 보존한다는 것입니다. 발견된 툴 스키마는 기존 목록을 갈아치우는 대신 뒤에 덧붙는 방식이라, 앞쪽 프리픽스가 그대로 남습니다. 툴 목록을 직접 바꾸면 캐시가 통째로 무효화되는 것과 대비됩니다.
감사를 절차로 만들기
일회성 점검은 시간이 지나면 무너집니다. 툴은 항상 추가되는 방향으로만 움직이기 때문입니다. 누군가 한 번 필요해서 붙인 툴은 그 필요가 사라져도 아무도 떼지 않습니다.
실무에서 쓰는 절차는 다음과 같습니다.
1. 사용률을 계측한다. 툴별 호출 횟수를 기간 단위로 집계합니다. 30일간 호출 0회인 툴은 제거 후보입니다. 계측이 없으면 이 판단을 추측으로 하게 되고, 추측은 항상 "혹시 필요할지 모르니 두자"로 기웁니다.
2. 제거 실험을 한다. 후보 툴을 뺀 구성으로 평가 세트를 돌려 정확도가 떨어지는지 봅니다. 떨어지지 않으면 그 툴은 없어도 되는 것이 확인된 셈입니다.
3. 역할별로 구성을 나눈다. 하나의 거대한 에이전트에 모든 툴을 붙이는 대신, 역할별로 툴 집합을 좁힌 에이전트를 여럿 두는 편이 안전합니다. 지원 에이전트에는 읽기와 초안 작성만, 관리자 에이전트에만 환불과 삭제를 둡니다.
4. 신규 툴 추가에 근거를 요구한다. 툴을 붙이려면 어떤 작업이 이 툴 없이 실패하는지를 사례로 제시하도록 합니다.
주의할 점은 툴 설명(description)은 감사 대상이 아니라는 것입니다. 오히려 상세한 설명은 툴 성능에 가장 크게 기여하는 요소이고, 실무에서 훨씬 흔한 실패는 설명이 부족한 쪽입니다. 줄여야 할 것은 툴의 개수와 권한이지 각 툴의 설명 분량이 아닙니다. 시험에서는 이 둘을 뒤섞은 선택지가 나옵니다.
시험 함정
- 로깅과 확인 프롬프트를 최소 권한의 구현으로 제시하는 선택지 — 둘 다 탐지·보완 통제이고, 최소 권한은 불필요한 능력을 제거하는 것입니다.
- 툴이 많아 성능이 떨어질 때 더 큰 모델로 바꾸면 된다는 선택지 — 모델 크기는 권한 범위와 무관하고 선택지 혼동도 근본적으로 해결하지 못합니다.
- 툴 설명을 짧게 줄여 컨텍스트를 아끼라는 선택지 — 상세한 설명은 툴 성능의 핵심이며, 줄일 대상은 툴 개수와 권한입니다.
- 툴 검색을 쓰면서 모든 툴에 defer_loading을 붙이는 구성 — 최소 하나는 상주해야 하고 검색 툴 자체는 지연 로딩 대상이 아닙니다.
- 쓰이지 않는 툴을 그대로 두고 시스템 프롬프트에 쓰지 말라고 적는 처방 — 프롬프트 지시는 권한 경계가 아닙니다.
- 툴 목록을 대화 도중 바꿔도 비용에 영향이 없다는 서술 — 툴은 프롬프트 맨 앞에 렌더링되므로 목록 변경은 캐시를 통째로 무효화합니다.
실습 시나리오
실제 시험과 같은 형식의 시나리오 문제입니다.
사내 운영 에이전트에 툴 34개가 붙어 있습니다. 감사해 보니 30일간 호출 기록이 있는 툴은 9개뿐이고, 나머지 중에는 스토리지 버킷 삭제 툴도 포함되어 있습니다. 동시에 모델이 유사한 조회 툴 두 개를 자주 혼동합니다. 가장 적절한 조치 조합은 무엇입니까?
빌드 연습 · 운영 중인 에이전트의 툴 구성 감사
약 50분1.툴 인벤토리 작성
대상 에이전트의 모든 툴을 표로 옮기고 각 툴에 역할·되돌림 가능 여부·최근 사용 여부를 채웁니다.
기대 결과 · 툴마다 세 항목이 모두 채워지고, 추측으로 채운 칸에는 표시가 남아 있습니다.
2.권한 층 분류
되돌림 가능 여부와 사용 여부를 교차한 2×2 표에 각 툴을 배치합니다.
기대 결과 · 미사용이면서 되돌리기 어려운 칸에 들어간 툴이 최우선 제거 후보로 식별됩니다.
3.선택지 층 분류
설명만 보고 어느 상황에 쓰는지 구분되지 않는 툴 쌍을 찾아 표시합니다.
기대 결과 · 경계가 겹치는 툴 쌍이 목록화되고, 각 쌍에 병합 또는 경계 명시 중 하나가 배정됩니다.
4.제거 실험
제거 후보를 뺀 구성으로 평가 세트를 돌려 기준선과 비교합니다.
기대 결과 · 정확도 변화가 수치로 기록되고, 떨어지지 않은 툴은 제거가 확정됩니다.
5.지연 로딩 전환
남은 저빈도 툴에 defer_loading을 적용하고 툴 검색 툴을 추가합니다.
기대 결과 · 상주 툴이 최소 하나 남아 있고, 저빈도 툴이 필요한 요청에서 검색을 거쳐 호출됩니다.