함수 호출

모델에게 사용 가능한 함수(툴)의 이름·설명·입력 스키마를 알려주고, 모델이 직접 실행하는 대신 "이 함수를 이 인자로 불러달라"는 구조화된 요청만 돌려주게 하는 방식입니다. 기준 시점: 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가 올 수도 있다)

툴 스키마 정의

툴 하나는 세 가지로 정의됩니다.

인자 검증

모델이 만든 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를 표시해, 모델이 그 사실을 알고 대응(재시도·대안 제시·사용자에게 보고)하게 합니다.

트레이드오프

주의사항

핵심 정리

참고

CSLOG에서 보기