함수 호출
모델에게 사용 가능한 함수(툴)의 이름·설명·입력 스키마를 알려주고, 모델이 직접 실행하는 대신 "이 함수를 이 인자로 불러달라"는 구조화된 요청만 돌려주게 하는 방식입니다. 기준 시점: 2026-10
왜 필요한가
LLM은 텍스트를 생성할 뿐 실제로 코드를 실행하거나 외부 API를 호출할 수 없습니다. 함수 호출이 없으면 "지금 날씨 알려줘" 같은 요청에 모델이 할 수 있는 건 추측해서 답하는 것뿐입니다.
함수 호출은 모델의 출력을 자연어 대신 {"name": "get_weather", "input": {"location": "Seoul"}} 같은 구조화된 형태로 받아, 실제 실행은 호출하는 쪽(애플리케이션 코드)이 맡는 구조로 이 문제를 풉니다. 모델은 "무엇을, 어떤 인자로" 결정만 하고, 실행과 그 결과를 모델에 되돌리는 흐름은 애플리케이션이 책임집니다. 에이전트 루프가 관찰-추론-행동을 반복하는 틀이라면, 함수 호출은 그 틀에서 "행동"을 모델이 실행 가능한 형태로 표현하게 하는 구체적인 메커니즘입니다.
구조
1. 애플리케이션이 요청에 tools(함수 스키마 목록)를 함께 보낸다
tools: [{ name, description, input_schema(JSON Schema) }, ...]
2. 모델이 응답으로 tool_use 블록을 돌려준다
{ type: "tool_use", id: "toolu_01", name: "get_weather",
input: { location: "Seoul" } }
(input은 해당 툴의 input_schema를 따르는 값)
3. 애플리케이션이 실제 get_weather(location="Seoul")를 실행한다
4. 실행 결과를 tool_result 블록으로 담아 다음 요청에 되돌린다
{ type: "tool_result", tool_use_id: "toolu_01",
content: "15도", is_error: false }
5. 모델이 tool_result를 읽고 최종 답변을 생성한다
(필요하면 2~4를 반복 — 한 턴에 여러 tool_use가 올 수도 있다)
툴 스키마 정의
툴 하나는 세 가지로 정의됩니다.
name— 툴 이름. 영문·숫자·_·-만 허용되는 식으로 제한하는 구현이 많습니다.description— 이 툴이 무엇을 하는지, 언제 써야(혹은 쓰지 말아야) 하는지, 각 인자가 어떤 의미인지 적는 평문 설명입니다. Anthropic 문서는 "툴 성능에 가장 큰 영향을 주는 요소"로 이 설명의 구체성을 꼽습니다. 설명이 부실하면("티커의 주가를 가져온다") 모델이 언제 어떻게 써야 할지 헷갈리고, 구체적이면("뉴욕거래소·나스닥의 상장 종목만 지원하며 최신 체결가 하나만 USD로 반환한다. 다른 정보는 주지 않는다") 호출 타이밍과 인자 선택이 정확해집니다.input_schema— 인자 형태를 정의하는 JSON Schema 객체. 모델은 응답을 생성할 때 이 스키마를 참고해input을 채웁니다.
인자 검증
모델이 만든 input이 스키마를 100% 지킨다는 보장은 기본적으로 없습니다. 필수 인자가 비거나 타입이 안 맞는 경우가 생길 수 있어, 애플리케이션은 함수를 실행하기 전에 input_schema로 직접 검증해야 합니다. 검증에 실패하면 is_error: true와 함께 "무엇이 왜 잘못됐는지"를 구체적으로 적은 tool_result를 돌려주면, 모델이 다음 턴에 고쳐서 다시 호출합니다. 이 재시도 비용을 아예 없애고 싶다면 입력이 스키마를 벗어날 수 없게 강제하는 strict 모드(제약 디코딩 기반)를 쓰는 구현도 있습니다.
결과를 모델에 되돌리는 흐름
tool_use 블록에는 id가 있고, 그 결과를 돌려주는 tool_result 블록은 tool_use_id로 어느 호출에 대한 응답인지 짝을 맺습니다. 한 턴에 여러 tool_use가 왔다면(병렬 툴 호출) 그만큼의 tool_result를 같은 메시지에 모아 보냅니다. 실행 중 에러가 나면 결과 대신 에러 메시지를 담고 is_error: true를 표시해, 모델이 그 사실을 알고 대응(재시도·대안 제시·사용자에게 보고)하게 합니다.
트레이드오프
- 툴이 많아질수록 모델이 어떤 툴을 골라야 할지 헷갈리는 선택 모호성이 커진다 — 서로 겹치는 기능의 툴을 줄이고 하나로 합치는 식으로 줄여야 한다
description을 길고 구체적으로 쓸수록 호출 정확도는 올라가지만 매 요청마다 프롬프트에 포함되는 토큰이 늘어난다- strict 모드로 스키마 위반을 막으면 인자 검증·재시도 비용은 줄지만, 모델이 선택할 수 있는 입력 표현이 그만큼 제약된다
주의사항
- 함수 실행 결과(
tool_result)는 외부 API·웹페이지·파일처럼 애플리케이션이 통제하지 않는 데이터를 담을 수 있다. 이 내용을 신뢰된 지시처럼 다루면 프롬프트 인젝션 통로가 된다 — 결과는 데이터로만 취급해야 한다 - 툴 이름과 설명이 모호하면 모델이 비슷한 툴 중 잘못된 것을 고르거나 불필요하게 자주 호출한다
- 결과를 너무 길게(예: 원본 API 응답 전체) 돌려주면 컨텍스트를 낭비하고 모델이 다음 판단에 필요한 정보를 찾기 어려워진다 — 핵심 필드만 추려 돌려주는 편이 낫다
핵심 정리
- 함수 호출은 모델이 "무엇을 어떤 인자로 부를지"만 결정하고, 실제 실행과 결과 반영은 애플리케이션이 맡는 구조다
- 툴 스키마는 name·description·input_schema(JSON Schema) 세 가지로 정의하며, description의 구체성이 호출 정확도에 가장 크게 영향을 준다
- 모델의 출력이 스키마를 완전히 보장하지 않으므로 애플리케이션 쪽 인자 검증이 필요하고, 실패 시 구체적인 에러를
tool_result로 돌려주면 모델이 스스로 고쳐 재시도한다 tool_use의id와tool_result의tool_use_id를 짝지어 어느 호출의 결과인지 구분하며, 병렬 호출 시에는 여러 결과를 한 번에 모아 보낸다