[AI 용어] Tool Calling - LLM이 쓸 도구와 입력값을 정해 호출을 요청하고, 실행은 에이전트가 맡는 방식
Claude Code 같은 AI 에이전트를 쓰실 때, 설치한 Skill이나 MCP가 어떻게 골라져서 쓰이는지 생각해 보신 적 있으십니까?
이 글에서는 그 답인 Tool Calling을, "샌프란시스코 날씨가 어때?" 질문 하나로 따라가 봅니다. 에이전트와 LLM 사이에 실제로 어떤 JSON이 누가 만들어서, 어디로 가고, 누가 읽는지 그대로 열어 봅니다.
Tool Calling(툴 콜링)
LLM이 쓸 도구와 입력값을 정해 호출을 요청하고, 실행은 에이전트가 맡는 방식. Function Calling, Tool use라고도 부릅니다.
(Claude 공식 문서: "Tool use (also called function calling) lets Claude call functions … It then returns a structured call that your application runs")
1. 설치한 Skill · MCP는 어떻게 골라질까?
요즘은 Skill과 MCP 서버를 모아 둔 마켓플레이스에서 클릭 몇 번이면 설치할 수 있습니다.
설치된 것은 Claude Code에서 /skills, /mcp 명령어로 확인할 수 있습니다.
그런데 이 많은 도구 중에서 무엇을 쓸지는 누가, 어떻게 정할까요?
2. Tool Calling이란
이 중에서 무엇을 쓸지 LLM이 정해서 호출을 요청하는 것, 이것이 Tool Calling입니다.
- LLM은 고르고 요청만 합니다. 어떤 도구를, 어떤 값으로 부를지 정해서 돌려줄 뿐입니다.
- 실행은 에이전트가 합니다. 에이전트는 Claude Code · OpenClaw · Hermes Agent처럼 사용자와 LLM 사이에서 일하는 프로그램입니다.
도구를 고르는 것도 결국 LLM이니까, LLM을 고를 때는 이 도구 선택 능력도 꼭 비교해 봐야 합니다. (7장에서 다시 다룹니다)
3. 예제 시나리오 — "샌프란시스코 날씨가 어때?"
사용자가 에이전트의 채팅창에 이렇게 묻습니다.
그런데 LLM은 글만 만들 뿐, 날씨를 직접 찾아볼 수는 없습니다. 그렇다면 날씨를 알려 주는 Skill이나 MCP는 어떻게 골라져서 쓰이게 될까요?
이 질문 하나에, 에이전트와 LLM 사이로 JSON이 네 번 오갑니다. 형식은 에이전트마다 조금씩 달라도 순서는 거의 같습니다. 아래는 Claude 공식 문서 「Tool use with Claude」의 예시입니다. (보기 쉽게 설명·질문·답·결과 값만 한국어로 옮겼습니다)
| 순서 | 데이터 | 만드는 쪽 → 읽는 쪽 | 읽고 하는 일 |
|---|---|---|---|
| ① | 요청 JSON (질문 + 도구 정의) | 에이전트 → LLM | 도구가 필요한지 판단 |
| ② | 응답 JSON (tool_use) |
LLM → 에이전트 | 어떤 도구를 실행할지 확인 |
| ③ | 도구 실행 | 에이전트 → 도구 | 결과를 돌려줌 |
| ④ | 요청 JSON (tool_result 붙임) |
에이전트 → LLM | 결과로 답을 씀 |
| — | 최종 응답 JSON (end_turn) |
LLM → 에이전트 | 글만 꺼내 채팅창에 표시 |
4. ① 요청: 에이전트가 요청 JSON을 만든다
{
"model": "claude-opus-5-5",
"max_tokens": 1024,
"tools": [{
"name": "get_weather",
"description": "지정한 위치의 현재 날씨를 알려 준다.",
"input_schema": {
"type": "object",
"properties": {"location": {"type": "string"}},
"required": ["location"]
}
}],
"messages": [
{"role": "user", "content": "샌프란시스코 날씨가 어때?"}
]
}
messages: 사용자 질문입니다.tools: 에이전트에 설치된 도구의 **이름 · 설명 · 입력값 형식(input_schema)**이 담겨 있습니다. LLM은 이것을 읽고 어떤 도구가 무슨 일을 하는지 판단해서 고릅니다.
그럼 LLM은 정확히 무엇을 보고 부를지 정할까요? 공식 문서에 그대로 나와 있습니다.
"Claude determines when to call a tool based on the user's request and the tool's description."
"It calls a tool when the request maps to that tool's described capability and the answer isn't already in context."
— Claude 공식 문서 「Tool use with Claude」
즉 요청이 도구 설명과 맞고, 답이 아직 대화에 없을 때 호출합니다. 그래서 공식 문서도 자세한 설명이 도구 성능에 가장 중요한 요소라고 강조합니다 ("This is by far the most important factor in tool performance." — 「Define tools」).
Skill이나 MCP를 직접 만드신다면, 이 설명을 정말 공들여서 써야 합니다.
5. ② 응답 · ③ 실행
LLM이 응답 JSON을 돌려줍니다. 답 대신 도구 호출이 들어 있습니다. 바로 여기가 Tool Calling입니다.
{
"stop_reason": "tool_use",
"content": [{
"type": "tool_use",
"id": "toolu_01…",
"name": "get_weather",
"input": {"location": "샌프란시스코"}
}]
}
stop_reason: "tool_use": 도구를 부르려고 여기서 멈췄다는 뜻입니다.tool_use블록: 어떤 도구를(name), 어떤 값으로(input) 부를지가 담겨 있고, 구분용id가 하나 붙습니다.
에이전트가 이것을 읽고 그 도구를 실행합니다. 내 컴퓨터의 명령일 수도 있고, 연결된 MCP 서버일 수도 있습니다.
실행을 에이전트가 하기 때문에 실행 전에 멈출 수도 있습니다. Claude Code가 명령을 실행하기 전에 허락을 묻는 화면이 바로 이 단계입니다.
6. ④ 결과와 최종 답
에이전트가 요청 JSON을 다시 만듭니다. 앞의 대화 뒤에 실행 결과를 담은 tool_result를 붙이고, 아까 받은 id로 어느 호출의 결과인지 짝을 맞춥니다.
{
"tools": [{"name": "get_weather", "description": "…", "input_schema": {…}}],
"messages": [
{"role": "user", "content": "샌프란시스코 날씨가 어때?"},
{"role": "assistant", "content": [
{"type": "tool_use", "id": "toolu_01…", "name": "get_weather", …}]},
{"role": "user", "content": [
{"type": "tool_result",
"tool_use_id": "toolu_01…",
"content": "섭씨 15도, 구름 조금"}]}
]
}
도구 정의까지 처음부터 모두 다시 보냅니다. LLM은 이전 요청을 기억하지 못하기 때문에, 매번 통째로 보내는 것입니다.
LLM은 결과를 읽고 최종 답을 만듭니다. 이번에는 stop_reason이 end_turn이고, 답 글이 들어 있습니다. 에이전트는 여기서 글만 꺼내 채팅창에 보여 줍니다.
- 도구가 더 필요하면 이 왕복을 몇 번이고 반복합니다.
- 한 응답에
tool_use가 여러 개 올 수도 있고, 그러면 결과도 다음 요청에 한꺼번에 돌려줍니다. (「Parallel tool use」)
⚠ 참고로 LLM은
tool_result에 담긴 내용을 그대로 받아들입니다. 그래서 공식 문서도 웹 페이지처럼 밖에서 가져온 결과는 믿을 수 없는 내용으로 다루라고 경고합니다.
"Tool results often carry content from sources outside your control … Treat that content as untrusted" — 「Handle tool calls」
7. 다시 Skill과 MCP로
처음 질문으로 돌아가 보겠습니다. 설치한 Skill과 MCP는 어떤 기준으로, 어떻게 쓰일까요?
MCP: MCP 공식 문서의 도구 정의도 이름 · 설명 · inputSchema, 앞에서 본 get_weather와 같은 구조입니다.
MCP를 지원하는 에이전트는 연결된 MCP 서버에서 도구 목록을 JSON으로 받아 와(tools/list), 요청 JSON의 tools에 넣어 LLM에게 보냅니다. LLM이 tool_use로 호출하면, 에이전트가 그 MCP 서버에 실행을 맡깁니다(tools/call).
Skill도 같습니다. Claude Code는 설치된 Skill의 설명을 읽어 늘 요청에 함께 넣어 두고, LLM이 Skill이라는 도구를 호출하면 그때 본문을 불러옵니다.
결국 보내는 것은 질문만이 아닙니다. 설치된 Skill의 이름과 설명, MCP 도구 이름이 매 요청마다 함께 LLM에게 갑니다.
LLM은 이것을 읽고 어떤 도구가 무슨 일을 하는지 판단해서 고릅니다. 그러니 결국 설명이 핵심입니다. Claude Code 공식 문서도 Skill 설명은 핵심 용도를 앞에 쓰라고 합니다. 목록에서는 설명 뒷부분이 잘리기 때문입니다 (1,536자 — 「Skills」).
8. 가성비 LLM 고르기
Hermes Agent나 OpenClaw 같은 에이전트는 LLM을 직접 골라서 연결합니다. API 키로 쓰면 쓴 만큼 요금이 나옵니다.
앞에서 본 것처럼, 도구를 한 번 부를 때마다 요청이 한 번 더 갑니다. 그래서 싼 LLM이라도 도구를 헛짚으면 왕복이 늘어납니다. 제 생각에는, 가성비 LLM을 고를 때 가장 먼저 볼 것이 바로 이 능력입니다.
이것을 재는 벤치마크도 있습니다. BFCL(Berkeley Function-Calling Leaderboard)이나 MCP-Atlas 같은 순위표에서는 점수와 비용, 그리고 업데이트 날짜를 같이 보시면 됩니다.
요즘 가성비 LLM으로는 Claude Haiku 5.5와 GPT-6 Luna가 있는데, 둘 다 순위표 마지막 업데이트(BFCL 2026-04-12, MCP-Atlas 2026-04-08) 이후에 나와서 아직 순위표에는 없습니다. (2026-11-01 확인)
대신 회사 발표를 보면:
- Anthropic 「Claude Haiku 5.5」 발표 표: 터미널 에이전트 시험(Terminal-Bench 4.0)에서 Haiku 5.5 39.2%, GPT-6 Luna 16.4%
- OpenAI 「GPT-6 Sol과 Luna 소개」: 도구 47개를 쓰는 업무 시험(AutomationBench)에서 GPT-6 Luna(High)가 이전 모델보다 5.4%포인트 높고, 작업당 비용은 58% 낮췄다
| 입력 / 출력 (100만 토큰당) | |
|---|---|
| Claude Haiku 5.5 | $0.10 / $0.50 (프롬프트 10만 토큰 이하) |
| GPT-6 Luna | $0.10 / $0.50 |
물론 회사 발표는 자기에게 유리한 시험을 고르기 마련입니다. 제가 직접 써 보니, 코딩만 아니라면 Luna 정도로도 꽤 쓸 만했습니다. 결국 내 작업으로 직접 돌려 보는 것이 가장 정확합니다.
정리: 세 줄 요약
- Tool Calling은 LLM이 어떤 도구를 어떤 값으로 쓸지 정해서 요청하고, 실행은 에이전트가 하는 방식입니다.
- LLM은 사용자 요청과 도구 설명을 보고 호출 여부를 정합니다.
- Skill도 MCP도, 결국 도구 정의로 LLM에게 전달되어 Tool Calling으로 쓰입니다.
김팔복
출처
- Claude 공식 문서 — Tool use with Claude
- Claude 공식 문서 — Define tools
- Claude 공식 문서 — Handle tool calls
- Claude 공식 문서 — Parallel tool use
- MCP 공식 문서 — Understanding MCP servers
- Claude Code 문서 — Skills · MCP
- BFCL 순위표 · MCP-Atlas 순위표 (2026-11-01 확인)
- Anthropic — Claude Haiku 5.5 · Pricing
- OpenAI — GPT-6 Sol과 Luna 소개
※ 글 속 이미지는 영상에서 캡처했습니다. 글 속 JSON은 Claude 공식 문서 예시이며, 설명·질문·답·결과 값을 한국어로 옮겼습니다.
아직 댓글이 없습니다.