8.제7장. 세션 5: Tool Use — Function Calling (이론·연습문제·해설)
출제 도메인: 도메인 2 (18%) · 작성자: 김재우 (jaewoo@claudcode.to)
① Claude Tool Use(Function Calling) 완벽 가이드 (CCA-F 세션 5): 에이전트 루프·툴 설계
지난 장 돌아보기
지난 장에서는 구조화 출력의 수단으로 Tool Use의 입구를 살짝 다뤘어요. 이번 장부터는 CCA-F 도메인 2(18%)에 해당하는 툴 설계와 MCP 통합을 다뤄요. 먼저 Tool Use(Function Calling)의 기본 구조와 에이전트 루프를 배워요.
주제 개요
LLM은 기본적으로 '텍스트를 넣으면 텍스트를 돌려주는' 존재지만, 외부 함수·API·데이터베이스를 호출할 수 있으면 세계의 상태를 가져오고 부수 효과를 실행하는 에이전트가 돼요. 이걸 실현하는 게 Tool Use(Function Calling)예요.
비유하자면 Claude는 '머리가 명석한 상담원'이지만, 스스로 전화를 걸거나 서류를 가져오지는 못해요. Tool Use는 '상담원 옆에 어시스턴트를 두고, 상담원의 지시로 어시스턴트가 실제 작업을 하는' 구조예요.
습득 포인트
- Tool Use의 3턴 교환(요청 → 툴 호출 → 결과 반환 → 최종 답변)을 그림으로 그릴 수 있다
- 툴 정의 스키마(name / description / input_schema)를 쓸 수 있다
- tool_use 블록과 tool_result 블록의 구조를 이해하고 있다
- 에이전트 루프의 구현 패턴(stop_reason으로 분기)을 설명할 수 있다
- 병렬 툴 호출(parallel_tool_use)의 동작과 무효화 방법을 이해하고 있다
- 툴 에러를 반환하는 법(is_error: true)과 Claude의 리커버리 동작을 파악하고 있다
- tool_choice의 3가지 형식(auto / any / 특정 툴)을 구분해 쓸 수 있다
1. Tool Use의 기본 흐름
Tool Use는 2~3턴의 API 호출로 구성돼요.
sequenceDiagram
participant App as 앱
participant Claude as Claude
participant Tool as 외부 도구<br/>(함수/API)
App->>Claude: 1. messages + tools 정의 전송
Claude-->>App: 2. tool_use 블록 반환<br/>stop_reason = tool_use
App->>Tool: 3. 앱 쪽에서 도구 실행
Tool-->>App: 4. 도구 결과 반환
App->>Claude: 5. messages에 tool_result 추가 후 재전송
Claude-->>App: 6. 최종 답변 반환<br/>(텍스트)
2. 툴 정의 스키마
tool_definition.py
tools = [
{
"name": "get_weather",
"description": "지정한 도시의 현재 날씨를 가져옵니다.",
"input_schema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "도시명(예: Seoul, New York)",
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "온도 단위",
},
},
"required": ["city"],
},
}
]
중요한 3요소
| 요소 | 역할 |
|---|---|
| name | 툴 식별자. snake_case 권장. Claude가 선택 시 사용 |
| description | Claude가 툴을 고르기 위한 판단 재료. 명확하고 구체적으로 작성 |
| input_schema | JSON 스키마. 인자의 타입·필수 항목·enum을 정의 |
Bad(description이 불충분)
bad.py
{"name": "search", "description": "검색한다", "input_schema": {...}}
# → 무엇을 검색하는지, 언제 써야 하는지 불명확
Good(description이 구체적)
good.py
{
"name": "search_documents",
"description": "사내 문서를 전문(全文) 검색합니다. 사용자가 규정·매뉴얼·과거 안건 정보를 요청할 때 사용하세요.",
"input_schema": {...},
}
왜 Good일까요: description은 툴 선정의 판단 재료예요. 모호하면 Claude가 부적절한 툴을 고를 리스크가 올라가요.
3. 에이전트 루프의 구현
agent_loop.py
import anthropic
import json
client = anthropic.Anthropic()
# tools 정의(섹션 2 '툴 정의 스키마'와 같은 내용)
tools = [
{
"name": "get_weather",
"description": "지정한 도시의 현재 날씨를 가져옵니다.",
"input_schema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "도시명(예: Seoul, New York)",
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "온도 단위",
},
},
"required": ["city"],
},
}
]
def get_weather(city: str, unit: str = "celsius") -> dict:
# 실제로는 외부 API를 호출한다. 여기서는 더미 데이터
return {"city": city, "temp": 22, "unit": unit, "condition": "Sunny"}
def run_agent(user_message: str, max_iterations: int = 5):
messages = [{"role": "user", "content": user_message}]
for i in range(max_iterations):
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=tools,
messages=messages,
)
# 어시스턴트 응답을 이력에 추가
messages.append({"role": "assistant", "content": response.content})
if response.stop_reason == "end_turn":
# 최종 답변
for block in response.content:
if block.type == "text":
return block.text
elif response.stop_reason == "tool_use":
# 툴 호출을 실행
tool_results = []
for block in response.content:
if block.type == "tool_use":
tool_name = block.name
tool_input = block.input
if tool_name == "get_weather":
result = get_weather(**tool_input)
else:
result = {"error": f"unknown tool: {tool_name}"}
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result, ensure_ascii=False),
})
# tool_results를 user 메시지로 반환
messages.append({"role": "user", "content": tool_results})
else:
break
raise RuntimeError("max iterations exceeded")
print(run_agent("서울 날씨 알려 줘"))
에이전트 루프의 요점
| 스텝 | 주의점 |
|---|---|
| 1. 어시스턴트 응답을 이력에 추가 | content 전체(텍스트 + tool_use)를 보존한다 |
| 2. stop_reason == "tool_use"로 분기 | 이 값으로 '툴 실행이 필요'하다고 판단 |
| 3. 툴을 실행하고 결과를 tool_result에 | tool_use_id로 대응지음 |
| 4. tool_result를 user 역으로 전송 | assistant가 아니라 user 역으로 반환하는 게 사양 |
| 5. max_iterations로 무한 루프 방지 | 보통 5~10회면 충분 |
4. tool_use와 tool_result의 구조
4.1 tool_use 블록(Claude → 앱)
tool_use_block.py
{
"type": "tool_use",
"id": "toolu_01ABC...", # 고유 ID
"name": "get_weather",
"input": {"city": "Seoul", "unit": "celsius"},
}
4.2 tool_result 블록(앱 → Claude)
tool_result_block.py
{
"type": "tool_result",
"tool_use_id": "toolu_01ABC...", # tool_use의 id와 일치
"content": "{\"temp\": 22, \"condition\": \"Sunny\"}",
"is_error": False, # 에러 시에는 True
}
5. 툴 에러 처리
툴 실행이 실패했을 때는 is_error: True로 Claude에게 알려요.
tool_error.py
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": "외부 API가 타임아웃됐습니다. 10초 후 재시도를 권장합니다.",
"is_error": True,
})
사용법과 주의점
- Claude는 is_error: True를 받으면, 자동으로 리커버리 판단(다른 툴을 시도·사용자에게 통지 등)을 시도한다
- 에러 메시지는 '무엇이 일어났는가', '어떻게 대처해야 하는가'를 구조적으로 전한다
- 보안: 스택 트레이스 같은 내부 정보를 그대로 반환하지 않는다
6. 병렬 툴 호출(parallel_tool_use)
Claude는 1턴에 여러 툴을 병렬로 호출할 수 있어요.
parallel_tool_use.py
# Claude는 날씨와 환율을 병렬로 요청할 수 있다
# response.content에 여러 tool_use 블록이 나란히 들어온다
병렬 호출을 무효화하려면 disable_parallel_tool_use를 지정해요.
tool_choice={"type": "auto", "disable_parallel_tool_use": True}
사용법과 주의점
- 병렬 호출은 여러 독립된 정보 취득에서 효과가 크다(날씨 + 환율 + 주가 등)
- 반면 순차 의존이 있는 경우에는 무효화해야 한다(A의 결과로 B의 인자가 정해지는 경우 등)
7. tool_choice의 3가지 형식
| 지정 방식 | 동작 | 유스케이스 |
|---|---|---|
{"type": "auto"}(기본값) | Claude가 판단 | 일반적인 대화 에이전트 |
{"type": "any"} | 반드시 어떤 툴이든 쓴다 | 툴 호출이 필수인 플로 |
{"type": "tool", "name": "<name>"} | 특정 툴을 반드시 쓴다 | 구조화 출력 |
8. 툴 설계의 원칙
8.1 툴 경계의 관리
툴은 '단일 책무'로 설계해요.
Bad(복합 책무)
bad.py
{
"name": "everything_tool",
"description": "사용자 정보의 취득, 갱신, 삭제, 검색, 메일 발송, SMS 발송 등을 한다",
"input_schema": {
"properties": {
"action": {"type": "string"}, # "get" "update" "delete" 등
...
}
}
}
# → description이 비대해지고, Claude가 오용하기 쉬움
Good(단일 책무)
good.py
[
{"name": "get_user", "description": "사용자 정보를 취득"},
{"name": "update_user", "description": "사용자 정보를 갱신"},
{"name": "delete_user", "description": "사용자를 삭제"},
{"name": "search_users", "description": "사용자를 검색"},
]
왜 Good일까요: 단일 책무로 하면 툴 선택 정확도가 오르고, 오용도 줄어요.
8.2 추론 부하의 최적화
툴 수가 너무 많으면 Claude의 판단 부하가 늘어, 레이턴시·비용·정확도가 모두 나빠져요. Claude는 매 턴, 등록된 모든 툴 정의를 읽어 들여 '어느 것을 쓸지'를 판단해요. 그래서 툴이 늘수록 비교 대상(선택지)이 늘고, 비슷한 툴끼리 헷갈리거나 선택 실수가 나기 쉬워져요.
| 툴 수 | 영향 |
|---|---|
| 5개 이하 | 최적 |
| 6~15개 | 허용 범위 |
| 16개 이상 | 정확도 저하·토큰 소비 증가 |
| 30개 이상 | 설계의 근본적 재검토가 필요 |
대책: 툴의 '수' 자체를 줄인다
여기서 효과적인 건 Claude가 한 번에 보는 툴의 수를 줄이는 거예요.
- 관련 툴을 서브에이전트로 떼어낸다(세션 9에서 상세히): 상위 에이전트는 '예약 담당을 부른다', '검색 담당을 부른다' 같은 소수의 툴만 갖고, 세세한 툴 무리는 각 서브에이전트 내부에 숨긴다
- 계층화(고수준 툴 → 저수준 툴): 입구를 좁히고, 상세한 조작은 하위에 위임한다
레스토랑에 빗대면, 메뉴가 100가지나 되면 손님은 다 고르지 못해요. 이걸 해결하는 건 코스 요리로 만들어 카테고리 단위로 좁히는 것(= 서브에이전트로 위임)이지, 각 요리의 설명문을 한 단어로 줄이는 게 아니에요. 설명을 줄여도 품목 수는 하나도 안 줄고, 오히려 요리의 차이를 알 수 없어 선택이 나빠져요.
주의: '툴이 너무 많다'는 건 수(count)의 문제이지, description 길이의 문제가 아니에요. description을 일률적으로 줄여도 툴 수는 하나도 안 줄어서 선택 실수는 해소되지 않아요. 오히려 섹션 2에서 봤듯이 description은 툴 선정의 판단 재료라, 너무 깎으면 "검색한다"처럼 모호해져 선택 정확도가 되레 떨어져요. 8.1의 '비대해지지 않게'는 1툴 1역(단일 책무)으로 한다는 뜻이지, 필요한 구체성까지 깎아내라는 뜻이 아니에요.
[보완 ] 최신 옵션을 덧붙입니다. Anthropic은 '툴이 너무 많은' 문제를 겨냥한 어드밴스드 툴 사용 기능을 추가했어요. Tool Search Tool은 수천 개의 툴 정의를 처음부터 컨텍스트에 다 넣지 않고, Claude가 필요할 때 검색해 온디맨드로 로딩하게 해 줍니다. Programmatic Tool Calling은 Claude가 코드 실행 환경에서 툴을 코드로 호출·집계하게 해, 매 호출마다 모델을 왕복하지 않고 토큰 소비와 레이턴시를 줄여요. 서브에이전트·계층화(8.2)와 함께 대규모 툴 환경의 실전 대안으로 검토해 볼 만합니다(둘 다 베타 단계이니 도입 전 최신 상태를 확인하세요).
자주 하는 오해와 개념 정리
❌ 자주 하는 오해: 'tool_result는 assistant 역으로 반환한다'
- 오해: 툴 결과는 Claude의 응답이니 assistant 역이라고 여기기 쉬움
- 실제: tool_result는 user 역 메시지 내용으로 반환한다(API 사양)
- 확인 방법: role을 assistant로 하면 API 에러
❌ 자주 하는 오해: '툴이 많을수록 고기능이다'
- 오해: 툴 수를 늘리면 에이전트의 능력이 오른다
- 실제: 너무 많으면 판단 부하로 정확도 저하. 5~15개가 현실적인 상한
- 확인 방법: 툴 수를 바꿔 가며 정확도·레이턴시를 비교
❌ 자주 하는 오해: '툴이 너무 많으면 description을 줄이면 해결된다'
- 오해: 툴 선택 실수가 늘면, 각 description을 한 줄로 줄이면 판단 부하가 내려간다
- 실제: 문제는 툴의 수(count)이지 description 길이가 아니다. 줄여도 툴 수는 하나도 안 줄고, 너무 깎으면 판단 재료(섹션 2)가 사라져 선택 정확도가 오히려 떨어진다. 올바른 대책은 서브에이전트로 떼어내기·계층화로 툴 수 자체를 줄이는 것(8.2). description을 간결하게 하는 건 '비대해진 복합 책무를 단일 책무로 나누기' 위함이지, 툴 과다의 해결책이 아니다
- 확인 방법: 툴 수를 그대로 둔 채 description만 줄여도 정확도가 돌아오지 않음을 확인한다
❌ 자주 하는 오해: '병렬 툴 호출은 항상 고속화된다'
- 오해: 병렬이면 전체 시간이 단축된다
- 실제: 의존 관계가 있는 툴에서는 잘못된 병렬 실행이 일어나 결과가 이상해진다
- 확인 방법: 순차 의존이 있는 처리에서는 disable_parallel_tool_use: True
자주 나는 에러와 대처법
- 에러 예시: tool_use_id가 일치하지 않음
- 원인: tool_result의 tool_use_id를 tool_use의 id와 대응짓지 않음
- 대처법: 1대1로 대응하는 id를 엄밀하게 세팅
- 에러 예시: Claude가 같은 툴을 계속 호출함
- 원인: 에러 처리가 불충분하거나, description이 모호함
- 대처법: is_error: True + 명확한 에러 메시지로 반환. max_iterations로 중단
- 에러 예시: 의도치 않은 툴이 호출됨
- 원인: description의 모호함, 또는 중복
- 대처법: description을 구체화하고, 툴 경계를 정리
정리와 다음 한 걸음
- Tool Use는 '앱 쪽이 툴 실행을 맡고, Claude는 판단과 통합에 집중하는' 분업 모델
- tool_use → 툴 실행 → tool_result → 최종 답변의 흐름을 stop_reason == "tool_use"로 분기
- 툴 정의는 name / description / input_schema의 3요소. description이 판단 재료
- 에러는 is_error: True + 구조적 메시지로 반환
- 병렬 툴 호출은 독립 태스크용. 순차 의존 태스크에서는 무효화
- 단일 책무 + 적절한 수(5~15개)가 툴 설계의 원칙
다음 세션에서는 툴 설계를 표준 사양으로 끌어올린 MCP(Model Context Protocol)를 배웁니다.
② CCA-F 세션 5 연습문제 9선: Claude Tool Use·에이전트 루프·툴 설계 완전 대비
습득 포인트와 문제 매칭
| 습득 포인트 | 해당 문제 |
|---|---|
| Tool Use의 기본 흐름 | 문제 1 |
| 툴 정의 스키마 | 문제 2 |
| tool_use / tool_result의 구조 | 문제 3, 문제 4 |
| 에이전트 루프 | 문제 5 |
| 병렬 툴 호출 | 문제 6 |
| 툴 설계 원칙 | 문제 7, 문제 8 |
문제 1: Tool Use의 흐름
- 카테고리: 기초
- 난이도: ★☆☆☆☆
- 예상 소요 시간: 5분
Tool Use의 전형적인 흐름으로 올바른 것은 무엇인가요?
- (A) 앱 → Claude(tool_use) → 앱(툴 실행) → Claude(tool_result 수신 → 최종 답변)
- (B) Claude가 직접 외부 API를 호출한다
- (C) 앱 → 외부 API → Claude(최종 답변)
- (D) Claude가 SSH를 거쳐 서버에 접속한다
문제 2: 툴 description의 중요성
- 카테고리: 기초
- 난이도: ★☆☆☆☆
- 예상 소요 시간: 5분
툴 정의의 description 필드의 가장 중요한 역할은 무엇인가요?
- (A) Anthropic 대시보드에 표시되는 설명
- (B) 개발자용 내부 코멘트
- (C) Claude가 툴을 고르는 판단 재료가 된다
- (D) 감사 로그용 라벨
문제 3: tool_result의 role 지정
- 카테고리: 응용
- 난이도: ★★☆☆☆
- 예상 소요 시간: 5분
툴 실행 결과를 Claude에게 반환할 때, tool_result 블록을 담은 메시지의 role로 올바른 것은 무엇인가요?
- (A) system
- (B) assistant
- (C) user
- (D) tool
문제 4: tool_use_id의 역할
- 카테고리: 응용
- 난이도: ★★☆☆☆
- 예상 소요 시간: 5분
tool_use_id의 역할로 올바른 것은 무엇인가요?
- (A) 툴 정의의 name과 같은 식별자
- (B) 파이썬의 내부 변수명
- (C) Anthropic 계정의 API 키
- (D) tool_use 블록과 tool_result 블록을 1대1로 대응짓는 ID
문제 5: 에이전트 루프의 분기
- 카테고리: 응용
- 난이도: ★★★☆☆
- 예상 소요 시간: 10분
에이전트 루프에서 '툴 실행으로 진행할지, 최종 답변을 반환할지'를 판단할 때의 근거로 올바른 것은 무엇인가요?
- (A) 응답의 길이
- (B) response.stop_reason의 값이 tool_use인지 end_turn인지
- (C) tools 리스트가 비어 있는지
- (D) Claude의 발화에 '툴'이라는 단어가 포함되어 있는지
문제 6: 병렬 툴 호출의 무효화
- 카테고리: 응용
- 난이도: ★★★☆☆
- 예상 소요 시간: 5분
A의 결과로 B의 인자가 정해지는 순차 의존이 있는 경우, 병렬 툴 호출을 무효화하기 위한 적절한 지정은 무엇인가요?
- (A)
tool_choice={"type": "auto", "disable_parallel_tool_use": True} - (B)
parallel=False - (C) 툴 정의에서 병렬 플래그를 삭제
- (D) max_tokens를 1로 한다
문제 7: 툴 수의 최적화
- 카테고리: 응용
- 난이도: ★★★☆☆
- 예상 소요 시간: 10분
에이전트에 30개의 툴을 등록했더니 툴 선택 실수가 늘었습니다. 가장 적절한 대응은 무엇인가요?
- (A) 툴 수를 더 늘린다
- (B) 관련 툴을 서브에이전트로 떼어내고, 상위 에이전트는 소수의 툴만 갖도록 재설계한다
- (C) 모든 툴 description을 한 줄로 단축
- (D) Claude 모델을 Haiku로 변경
문제 8: 툴 책무의 단일화
- 카테고리: 응용
- 난이도: ★★★☆☆
- 예상 소요 시간: 10분
다음 툴 설계에 가장 큰 문제가 있습니다. 가장 적절한 개선안은 무엇인가요?
{
"name": "user_action",
"description": "사용자 조작(생성·갱신·삭제·검색)을 실행",
"input_schema": {
"properties": {
"action": {"type": "string"},
"user_data": {"type": "object"},
}
}
}
- (A) description을 더 길게 한다
- (B) 이대로 쓴다
- (C) action을 enum으로 고정한다
- (D) 여러 개의 단일 책무 툴(create_user / update_user / delete_user / search_users)로 분할한다
문제 9 (고급): 추론 부하의 최적화
- 카테고리: 고급
- 난이도: ★★★★☆
- 예상 소요 시간: 20분
고객 지원 에이전트에 50개의 툴을 등록했더니, 레이턴시가 2초 → 8초로 나빠지고 툴 선택 정확도도 떨어졌습니다. CCA-F 시험 범위의 개념을 사용해, 단계적인 개선 계획을 3스텝으로 서술하세요.
정답은 이 장 후반의 정답·해설편에서 확인하세요.
③ CCA-F 세션 5 연습문제 정답·해설: Claude Tool Use·에이전트 루프·서브에이전트 완전 풀이
정답 일람
| 문제 | 정답 |
|---|---|
| 문제 1 | (A) |
| 문제 2 | (C) |
| 문제 3 | (C) |
| 문제 4 | (D) |
| 문제 5 | (B) |
| 문제 6 | (A) |
| 문제 7 | (B) |
| 문제 8 | (D) |
| 문제 9 | 후술 |
문제 1: Tool Use의 흐름 — 정답 (A)
해설
Tool Use는 'Claude는 판단하는 사람, 앱은 툴 실행 담당'이라는 분업 모델이에요. Claude 자신은 외부 API를 호출하지 않아요.
◆ 설계와 운용 포인트
- 설계 사상: 이 분업 덕분에 외부 I/O의 제어권이 앱 쪽에 남아, 감사·샌드박스·타임아웃 제어가 쉬워져요.
- 운용 시 주의점: Claude가 '외부 API를 호출했습니다'라고 말해도, 그건 Tool Use를 거쳐 앱이 호출한 거예요.
문제 2: 툴 description의 중요성 — 정답 (C)
해설
description은 Claude가 툴을 선정할 때의 판단 재료예요. 모호하면 오선택이 늘어나요.
◆ 설계와 운용 포인트
- 설계 사상: description은 '프롬프트의 일부'로 여겨요. Claude에게는 '언제 이 툴을 써야 하는가'의 가이드라인이에요.
- 운용 시 주의점: 툴을 늘리기 전에 description의 질을 개선하는 편이 정확도 면에서 더 잘 듣는 경우가 많아요.
문제 3: tool_result의 role 지정 — 정답 (C)
해설
tool_result는 user 역 메시지 내용으로 반환해요. API 사양상의 규칙이에요.
◆ 설계와 운용 포인트
- 설계 사상: Claude에게 tool_result는 '사용자가 제시한 추가 정보'와 같은 카테고리로 다뤄져요.
- 운용 시 주의점: assistant나 system으로 하면 invalid_request_error가 나요.
문제 4: tool_use_id의 역할 — 정답 (D)
해설
tool_use_id는 tool_use와 tool_result를 1대1로 대응짓는 ID예요. 병렬 툴 호출이 있을 때, 어느 결과가 어느 호출에 대응하는지를 나타내요.
◆ 설계와 운용 포인트
- 계산량과 리소스 사용: 병렬 실행 시 결과는 순서 없이 돌아올 수 있어서 tool_use_id로 대응짓는 게 필수예요.
문제 5: 에이전트 루프의 분기 — 정답 (B)
해설
에이전트 루프에서는 response.stop_reason의 값으로 다음 처리를 분기해요.
- tool_use → 툴 실행으로 진행
- end_turn → 최종 답변으로 반환
- max_tokens → 출력 잘림 가능성, 이어받기 처리를 검토
◆ 설계와 운용 포인트
- 운용 시 주의점: stop_reason을 보지 않고 content 내용만으로 판단하면, 복잡한 에이전트에서 오작동이 나요.
문제 6: 병렬 툴 호출의 무효화 — 정답 (A)
해설
tool_choice 안에서 disable_parallel_tool_use: True를 지정하면, Claude가 한 번에 툴을 하나씩 호출하게 돼요.
◆ 설계와 운용 포인트
- 설계 사상: 병렬 호출은 레이턴시 단축에 효과적이지만, 의존 관계가 있으면 깨져요.
- 운용 시 주의점: '은행 계좌에서 인출 → 메일 통지'처럼 순차가 필수인 처리에서는 반드시 무효화해요.
문제 7: 툴 수의 최적화 — 정답 (B)
해설
툴 수가 너무 많은 경우는 서브에이전트로 떼어내 계층화하는 게 왕도예요. 이렇게 하면 상위 에이전트의 판단 부하를 낮출 수 있어요.
여기서 헷갈리기 쉬운 게 (C) '모든 description을 한 줄로 단축'이에요. 문제의 본질은 툴의 수(count)이지 description의 길이가 아니에요. 단축해도 툴 수는 하나도 안 줄고, 게다가 description은 툴 선정의 판단 재료(문제 2)라 너무 깎으면 선택 정확도가 되레 떨어져요. (A)는 문제를 악화시킬 뿐이고, (D)의 모델 변경은 수의 문제를 해결하지 못해요.
◆ 설계와 운용 포인트
- 설계 사상: 'Divide and Conquer'의 원칙이에요. 자세한 내용은 세션 9(멀티에이전트)에서 다뤄요.
- 계산량과 리소스 사용: 상위 에이전트의 판단 토큰 수가 줄어, 레이턴시·비용이 개선돼요.
문제 8: 툴 책무의 단일화 — 정답 (D)
해설
복합 책무 툴은 description이 비대해져, Claude가 오용하기 쉬워져요. 단일 책무 툴로 분할하는 게 원칙이에요.
◆ 설계와 운용 포인트
- 설계 사상: 소프트웨어 설계의 SRP(Single Responsibility Principle)와 같아요. 툴도 단일 책무가 바람직해요.
- 운용 시 주의점: '너무 잘게 나눠도 판단 부하가 늘'기 때문에, 적절한 입도(5~15개)를 의식해요.
문제 9 (고급): 추론 부하의 최적화 — 개선 계획 예시
Step 1: 현황 분석과 카테고리 분류
- 50개의 툴을 기능별 카테고리로 분류한다
- 예: '사용자 관리(10개)', '주문 관리(8개)', '재고 관리(7개)', '외부 연동(15개)', '분석·리포트(10개)'
- 각 툴의 이용 빈도와 의존 관계를 시각화한다
Step 2: 서브에이전트화를 통한 계층화
- 카테고리마다 서브에이전트를 만들고, 각 서브에이전트가 자기 툴 무리를 가진다
- 상위 에이전트(허브)는 '어느 카테고리에 위임할지'를 판단하기만 한다(툴 수 5개 정도)
flowchart TD
A["상위 에이전트<br/>도구 5개"]
B["사용자 관리 에이전트<br/>도구 10개"]
C["주문 관리 에이전트<br/>도구 8개"]
D["재고 관리 에이전트<br/>도구 7개"]
E["외부 연동 에이전트<br/>도구 15개"]
F["분석 에이전트<br/>도구 10개"]
A --> B
A --> C
A --> D
A --> E
A --> F
Step 3: 툴 정의의 리팩터링
- 단일 책무화: 복합 툴을 분할
- description 개선: 언제 써야 하는지·쓰지 말아야 하는지를 명시
- 고빈도 툴로 좁히기: 저빈도 툴은 다른 수단(직접 API 호출 등)으로 빼낸다
기대되는 효과
| 지표 | 개선 전 | 개선 후 | 개선 폭 |
|---|---|---|---|
| 레이턴시 | 8초 | 3초 | -62% |
| 툴 선택 정확도 | 70% | 92% | +22pt |
| 토큰 소비 | 큼 | 작음 | 비용 절감 |
이 세션 돌아보기
- Tool Use는 Claude가 판단, 앱이 실행의 분업 모델
- 주요 블록: tool_use(Claude 출력), tool_result(user 역으로 반환)
- 에이전트 루프는 stop_reason으로 분기하고, max_iterations로 중단한다
- 병렬 툴 호출은 독립 태스크용, 순차 의존 태스크에서는 무효화
- 툴 설계의 원칙: 단일 책무, 적절한 수(5~15개), 명확한 description
- 툴 수가 늘면 서브에이전트화로 계층화
다음 세션(제8장)에서는 이 툴 설계를 표준 사양으로 삼은 Model Context Protocol(MCP)로 넘어갑니다.
©2024-2026 ClaudeCode.to, Hand-crafted & made with Jaewoo Kim.
- 이메일문의: jaewoo@claudecode.to
- AI 에이전트 만드는 사람
- 기업 AI 강의 · 에이전트 개발 · 기술자문
- "AI한테 일 시키는 법, 제대로 알려드립니다"
