콘텐츠로 이동

3. 도구 호출

“"3. 도구 호출"” 챕터 컨셉 일러스트

한 줄 정의. 도구 호출은 모델이 직접 코드를 실행하는 게 아니라, “어떤 도구를 어떤 인자로 부르고 싶다”는 구조화된 요청을 내놓고 그 실행은 하네스가 맡는, 모델과 바깥 세계 사이의 계약이다.

도구 호출 시퀀스: 모델→스키마→실행→결과 반환

도구가 없는 모델은 자기가 학습한 지식 안에 갇혀 있습니다. 도구를 주는 순간 모델은 검색하고, 파일을 읽고, 코드를 돌리고, 외부 API를 호출할 수 있게 됩니다.

Anthropic은 도구 사용 개요에서 기본적인 도구만 더해도 큰 폭의 성능 향상이 나타난다고 적습니다.1 도구 호출은 에이전트 루프에서 모델이 실제로 세상에 손을 뻗는 유일한 통로이고, 그래서 하네스 설계의 핵심입니다.

도구 호출의 최소 단위 — 요청·실행·결과 반환 사이클

섹션 제목: “도구 호출의 최소 단위 — 요청·실행·결과 반환 사이클”

핵심을 헷갈리면 안 됩니다. 모델은 도구를 실행하지 않습니다. 모델이 하는 일은 “get_weather{location: "서울"}로 부르고 싶다”는 구조화된 요청을 내놓는 것까지입니다. 그 호출을 받아 실제로 함수를 돌리고, 결과를 다시 모델에게 돌려주는 일은 모델을 감싼 하네스의 몫입니다.

Anthropic 문서가 설명하는 클라이언트 도구 흐름은 정확히 한 바퀴입니다.1 Claude가 stop_reason"tool_use"로 채우고 하나 이상의 tool_use 블록을 담아 응답하면, 내 코드가 그 작업을 실행하고, 그 결과를 user role 메시지로 되돌려보냅니다.

이 한 바퀴(요청 → 실행 → 결과 반환)가 도구 호출의 최소 단위이고, 에이전트는 완료 조건이 충족될 때까지 이 바퀴를 반복합니다. 이 반복이 어떻게 한 세션으로 엮이는지는 4. 하네스 실행 루프에서 다룹니다.

모델이 내놓는 호출 요청은 정해진 모양의 블록입니다. {type: "tool_use", id, name, input} 네 필드로 이루어지고, idtoolu_ 접두사를 가집니다(예: toolu_01A09q90qw90lq917835lq9).1id가 나중에 결과를 어느 호출에 묶을지 결정하는 열쇠입니다.

결과를 되돌릴 때는 user 메시지의 content 배열 안에 {type: "tool_result", tool_use_id, content} 블록을 넣습니다. 여기서 tool_use_id가 앞서 받은 tool_use 블록의 id와 일치해야 어느 호출에 대한 응답인지 연결됩니다.1

이 짝이 어긋나면 API는 어떤 호출이 아직 응답되지 않았다고 보고 요청을 거부합니다.

실행이 실패했을 때는 결과를 누락시키지 말고 tool_resultis_error: true를 넣어 모델에 알립니다.1 그러면 모델은 에러를 인지하고 다른 접근을 시도하거나 사용자에게 명확화를 요청합니다. 실패한 호출의 결과를 아예 빼버리면 위에서 말한 tool_use_id 짝 규칙을 깨뜨려 다음 요청 자체가 400으로 막힙니다.

선행 text 블록에 포맷을 의존하지 말 것

섹션 제목: “선행 text 블록에 포맷을 의존하지 말 것”

Claude는 tool_use 블록 앞에 자연어 text 블록을 함께 내놓는 경우가 많습니다. 예를 들어 날씨 도구를 부르기 직전에 “I’ll help you check the current weather…” 같은 문장을 먼저 내놓습니다.1

코드는 이것을 일반 assistant 텍스트처럼 다뤄야 하며, 특정 문구나 포맷이 반드시 온다고 가정하면 안 됩니다.

서버 도구는 이 사이클이 다릅니다. web_searchcode_execution 같은 서버 도구는 Anthropic 인프라에서 실행되어 결과가 같은 응답 안에 블록으로 돌아오므로, 내가 실행을 처리하지 않습니다.1 다음 절에서 이 두 부류의 경계를 짚습니다.

클라이언트 도구 vs 서버 도구 — 실행 위치 기준 2분류

섹션 제목: “클라이언트 도구 vs 서버 도구 — 실행 위치 기준 2분류”

도구를 나누는 Anthropic의 1차 분류 축은 정확히 코드가 어디서 도는가입니다. 둘로 갈립니다.

클라이언트 도구는 내 애플리케이션에서 실행됩니다. 내가 직접 정의한 함수가 여기 속하고, bash·text_editor처럼 Anthropic이 스키마를 정의한 도구도 실행은 내 환경에서 일어나므로 클라이언트 도구입니다.1

이 도구들은 stop_reason: "tool_use"를 받아 내가 실행하고 결과를 되돌리는, 앞 절의 사이클을 그대로 탑니다.

서버 도구는 Anthropic 인프라에서 실행되어 결과를 직접 받습니다. web_search, code_execution, web_fetch, 그리고 뒤에서 다룰 tool_search가 서버 도구입니다.1 내가 실행 처리를 하지 않고, 결과가 응답 블록으로 돌아옵니다.

서버 도구는 type에 버전 날짜가 박힌다는 점이 눈에 띕니다. 예를 들어 웹 검색은 web_search_20260209, 도구 검색은 tool_search_tool_regex_20251119·tool_search_tool_bm25_20251119처럼 적습니다.12 날짜가 박힌 type은 그 도구의 동작이 고정된 특정 버전임을 가리킵니다.

갈래스키마를 누가 정의어디서 실행공식 분류
function calling내가 정의내 코드클라이언트
hosted/built-in제공자가 정의제공자 인프라대개 서버
셸·컴퓨터 사용제공자 스키마내 환경클라이언트
MCP 도구MCP 서버가 정의MCP 서버(별도 프로토콜)

MCP가 하나의 프로토콜 계층으로 어떻게 표준화되는지는 따로 다룹니다.

도구 정의 스키마 — name·description·input_schema와 선택 속성

섹션 제목: “도구 정의 스키마 — name·description·input_schema와 선택 속성”

모든 도구의 공통 뼈대는 세 가지 필수 필드입니다. Anthropic 도구 정의는 name, description, input_schema(JSON Schema)를 받습니다.3

name은 정규식 ^[a-zA-Z0-9_-]{1,64}$를 만족해야 합니다 — 영숫자와 밑줄·하이픈만, 1~64자입니다. 이 규칙을 어긴 이름은 요청 단계에서 거부됩니다.

필수 외에 여러 선택 속성이 있습니다. input_examples, cache_control, strict, defer_loading, allowed_callers가 그렇습니다.3

이 중 input_examplesinput_schema에 valid한 예시 입력의 배열로, 모델이 복잡한 스키마의 인자를 어떻게 채우는지 보여 주는 단서입니다. 단, 예시가 스키마에 맞지 않으면 400 에러가 나고, 서버 도구에는 지원되지 않습니다.

토큰 비용도 듭니다 — 단순 예시는 2050 토큰, 복잡한 중첩 예시는 100200 토큰 정도입니다.3

다른 생태계도 골격은 같지만 이름이 다릅니다. MCP 도구 정의는 name(필수 식별자), title(선택, 표시용), description, inputSchema(JSON Schema), outputSchema(선택), annotations(선택)로 이루어집니다.4

OpenAI 함수 도구 정의는 type: "function", name, description, parameters(JSON Schema), strict입니다.5 표시용 title을 식별용 name과 분리한 점, 출력 스키마를 따로 둘 수 있는 점이 MCP의 특징입니다.

도구를 고르는 일은 모델이 합니다. 그 판단의 근거가 바로 description이므로, 공통 베스트프랙티스는 한결같습니다. 설명은 최소 3~4문장으로, 무엇을 하는지뿐 아니라 언제 쓰는지·언제 쓰지 않는지, 각 파라미터의 의미, 제약을 담으라는 것입니다.3 설명이 모호하면 모델은 엉뚱한 도구를 부르거나, 불러야 할 때 부르지 않습니다.

인자 설명도 모델이 값을 올바르게 채우게 만드는 단서입니다. OpenAI 문서가 드는 "City and country e.g. Bogotá, Colombia",5 Anthropic 문서의 "The city and state, e.g. San Francisco, CA"1 같은 형식 예시가 그것입니다.

추상적 설명보다 구체적 예시 한 줄이 더 강한 신호입니다.

설계 차원의 권장도 둘 있습니다. 첫째, 관련 동작은 별도 도구로 쪼개지 말고 action 파라미터를 둔 하나의 도구로 통합하라는 것입니다(예: create_pr/review_pr/merge_pr 대신 action을 받는 단일 도구).3 둘째, 도구명에 서비스 네임스페이스 접두를 붙이라는 것입니다(github_, slack_).3 이름 충돌을 막고, 모델이 도구의 출신을 파악하도록 돕습니다.

스키마 자동 생성 — OpenAI Agents SDK @function_tool

섹션 제목: “스키마 자동 생성 — OpenAI Agents SDK @function_tool”

스키마를 손으로 다 적을 필요는 없습니다. OpenAI Agents SDK의 @function_tool 데코레이터는 파이썬 함수에서 도구 정의를 자동으로 만들어 냅니다.

이름은 파이썬 함수명에서, 설명은 docstring에서, 입력 스키마는 함수 인자에서 뽑아냅니다.6 내부적으로는 inspect로 시그니처를, griffe로 docstring을, Pydantic으로 스키마를 처리합니다.

즉 함수 시그니처와 docstring을 잘 쓰면 그게 곧 도구 계약이 됩니다.

docstring 포맷은 google·sphinx·numpy 세 가지를 지원하며, 어느 포맷인지 자동으로 감지하지만 그 감지는 best-effort입니다.6 의도와 다르게 파싱될 여지가 있다는 뜻입니다.

자동 동작을 덮어쓸 오버라이드도 있습니다. name_override로 이름을, description_override로 설명을 바꾸고, use_docstring_info=False로 docstring 파싱을 아예 끌 수 있습니다.6

자동 생성을 쓰지 않고 도구를 수동으로 만들 때는 FunctionTool 객체를 직접 구성합니다. 필드는 name, description, params_json_schema, 그리고 on_invoke_tool입니다 — 마지막 필드는 ToolContextarguments를 받는 async 함수입니다.6

에러 처리도 SDK가 책임집니다. failure_error_function을 지정하면 도구가 크래시했을 때 LLM에 에러 응답을 제공합니다.

기본값인 default_tool_error_function이 LLM에 에러를 알리고, 이 값을 None으로 주면 예외를 그대로 re-raise합니다.6 즉 “모델에게 에러를 알려 회복시킬지” 아니면 “예외를 위로 던질지”를 한 파라미터로 고를 수 있습니다.

스키마 검증 — strict 모드와 MCP outputSchema

섹션 제목: “스키마 검증 — strict 모드와 MCP outputSchema”

모델이 스키마를 어겨 엉뚱한 인자를 넣는 일을 막는 장치가 strict 모드입니다. Anthropic 쪽에서는 도구 정의에 strict: true를 더하면 Claude의 도구 호출이 스키마와 정확히 일치하도록 보장됩니다.3

이를 tool_choice: {type: "any"}와 결합하면 ‘도구가 반드시 호출됨’과 ‘입력이 스키마를 준수함’ 둘 다를 보장할 수 있습니다.3

OpenAI의 strict: true는 동작 방식이 더 명시적입니다. required를 모두 명시하게 하고 additionalProperties: false를 강제해, 예상 외의 인자를 막고 모델이 스키마를 정확히 따르도록 합니다.5 같은 목표를 스키마 자체의 제약으로 달성하는 셈입니다.

MCP는 출력 쪽까지 검증을 넓힙니다. 도구 정의에 outputSchema가 있으면 서버는 그 스키마에 맞는 structuredContent를 반드시(MUST) 제공해야 하고, 클라이언트는 그것을 검증하는 게 좋습니다(SHOULD).4 구조화된 결과는 structuredContent 필드(JSON 객체)로 반환하되, 하위호환을 위해 같은 JSON을 직렬화한 TextContent 블록으로도 함께 반환하는 게 권장됩니다(SHOULD).4 구조화 결과를 모르는 구형 클라이언트도 텍스트로는 읽을 수 있게 하려는 배려입니다.

tool_choice — 4가지 옵션과 강제 호출이 사고를 막는 부작용

섹션 제목: “tool_choice — 4가지 옵션과 강제 호출이 사고를 막는 부작용”

tool_choice는 도구를 언제 쓸지 통제합니다. 네 옵션이 있습니다.3

  • auto — 기본값. 모델이 도구 호출 여부를 스스로 결정합니다.
  • any — 반드시 어떤 도구 하나를 쓰되, 특정 도구를 강제하진 않습니다.
  • tool — 특정 도구를 강제합니다({type: "tool", name: "..."}).
  • none — 도구를 금지합니다. tools를 주지 않으면 이게 기본입니다.

여기에 결정적인 부작용이 있습니다. any 또는 tool일 때 API는 assistant 메시지를 prefill하여 도구 사용을 강제합니다. 이 prefill 때문에 모델은 tool_use 앞에 자연어 응답·설명을 내놓지 못합니다 — 명시적으로 요청해도 그렇습니다.3 즉 강제 호출은 chain-of-thought나 선행 설명을 차단합니다.

extended thinking과의 호환성도 함께 봐야 합니다. extended thinking은 tool_choice any/tool과 비호환이라 에러가 납니다. autonone만 extended thinking과 호환됩니다.3 사고 과정을 켠 채 도구를 반드시 쓰게 만들 수는 없다는 뜻입니다.

prompt caching을 쓴다면 한 가지 더 주의할 점이 있습니다. tool_choice 값을 바꾸면 캐시된 메시지 블록이 무효화됩니다 — 도구 정의와 시스템 프롬프트의 캐시는 유지되지만, 메시지 단의 캐시는 깨집니다.3

병렬 도구 호출과 disable_parallel_tool_use

섹션 제목: “병렬 도구 호출과 disable_parallel_tool_use”

Claude는 한 응답에 여러 tool_use 블록을 내놓아 여러 도구를 동시에 부를 수 있습니다.1 멀티 도구 동시 호출은 실무의 핵심입니다 — 서로 의존하지 않는 조회 셋을 한 턴에 묶으면 왕복이 줄어듭니다. 앞서 “모든 tool_use를 순회하라”고 강조한 이유가 여기 있습니다.

병렬을 끄고 싶을 때의 손잡이는 제공자마다 다릅니다. OpenAI는 parallel_tool_calls: false로 병렬 호출을 비활성화합니다.5

Anthropic은 disable_parallel_tool_use 필드를 tool_choice 안에 둡니다. auto에서는 한 번에 최대 1개로 제한하고, any/tool에서는 정확히 1개 도구만 호출하도록 만듭니다.1

도구 사용 시스템 프롬프트와 토큰 오버헤드

섹션 제목: “도구 사용 시스템 프롬프트와 토큰 오버헤드”

tools 파라미터를 주면 API가 특수한 tool-use 시스템 프롬프트를 자동으로 구성합니다. 형식은 “In this environment you have access to a set of tools…”로 시작해, 포맷팅 지시 + JSONSchema 도구 정의 + 사용자 시스템 프롬프트 + 도구 설정 순으로 이어집니다.1

이 시스템 프롬프트의 토큰은 입력 토큰에 그대로 더해집니다.

토큰량은 모델과 tool_choice에 따라 다릅니다. Claude Opus 4.8 기준으로 auto/none은 290 토큰, any/tool은 410 토큰입니다.1

(참고로 Opus 4.5·Sonnet 4.5·Haiku 4.5는 셋 다 동일하게 auto/none 496 토큰, any/tool 588 토큰입니다.1) tools를 주지 않고 tool_choicenone이면 추가 시스템 프롬프트 토큰은 0입니다.1

도구 사용으로 늘어나는 추가 토큰의 출처는 셋입니다 — tools 파라미터(이름·설명·스키마), 요청·응답의 tool_use 블록, 요청의 tool_result 블록입니다.1 가격 면에서는 클라이언트 도구가 일반 요청과 동일하게 과금되고, 서버 도구는 사용량 기반으로 추가 과금됩니다(예: 웹 검색은 검색당 과금).1

도구는 공짜가 아닙니다. 정의 자체가 컨텍스트를 차지하고, 후보가 많아질수록 모델의 선택이 흐트러집니다.

tool search 문서는 두 문제를 명시합니다. 첫째, 컨텍스트 부풀림 — GitHub·Slack·Sentry·Grafana·Splunk 같은 다중 서버 구성은 작업을 시작하기도 전에 정의만으로 ~55k 토큰을 소비합니다.2

둘째, 선택 정확도 저하 — 가용 도구가 30~50개를 초과하면 올바른 도구를 고르는 능력이 크게 저하됩니다.2

해법은 “필요할 때만 꺼내기”입니다. tool search는 정의 토큰을 85%+ 줄이면서 요청당 실제 필요한 3~5개만 로드합니다.2 이는 스킬 기본형의 점진적 공개와 같은 원리입니다.

tool search에는 두 검색 방식이 있습니다. tool_search_tool_regex_20251119는 Claude가 Python re.search() 정규식을 구성하는 방식으로, 자연어가 아니며 최대 200자입니다(예: "(?i)slack", "get_.*_data"). tool_search_tool_bm25_20251119는 자연어 쿼리를 받습니다.2

두 변형 모두 도구 이름·설명·인자명·인자설명을 검색 대상으로 삼습니다.2

흐름은 이렇습니다. tool search 도구를 tools에 포함하고, 즉시 로드하지 않을 도구에 defer_loading: true를 붙입니다.

그러면 Claude는 처음엔 search 도구와 비-deferred 도구만 봅니다. Claude가 검색하면 API가 3~5개의 tool_reference 블록을 반환하고, 이 참조가 자동으로 full 정의로 확장됩니다.2

응답 블록의 구조도 정해져 있습니다. 검색 호출은 server_tool_use로, 그 결과는 tool_search_tool_result로 돌아오는데 그 안의 중첩된 tool_search_tool_search_resulttool_references 배열이 담깁니다.

이후 실제 tool_use가 이어집니다.2 확장은 API가 자동으로 처리하며, 대화 전체에 걸쳐 자동 확장되므로 같은 도구를 다시 검색할 필요가 없습니다.2

tool search가 영리한 점은 캐시를 깨지 않는다는 데 있습니다. deferred 도구는 시스템 프롬프트 prefix에 포함되지 않고, tool_reference는 대화 inline에 append됩니다.

prefix가 불변이므로 prompt caching이 유지됩니다.2 strict 모드 문법은 full toolset에서 빌드되어, defer_loading과 결합해도 문법 재컴파일 없이 동작합니다.2

권장 기준도 명확합니다. 가장 자주 쓰는 3~5개는 비-deferred로 유지하고, 서비스별 네임스페이스 접두(github_/slack_)를 붙이며, 도구가 10개 이상이거나 정의가 10k 토큰을 넘을 때 tool search를 씁니다.

반대로 도구가 10개 미만이거나, 매 요청 항상 쓰이거나, 정의가 100토큰 미만이면 전통적인 호출이 낫습니다.2

hosted/built-in 도구 — OpenAI 카탈로그와 API 경계

섹션 제목: “hosted/built-in 도구 — OpenAI 카탈로그와 API 경계”

제공자가 미리 만들어 호스팅하는 도구도 한 부류입니다. OpenAI 호스티드 도구 카탈로그에는 웹 검색, 파일 검색(벡터 스토어 기반), 이미지 생성(GPT Image), 코드 인터프리터(호스티드 컨테이너), 컴퓨터 사용, Shell, Skills(버전 번들), 그리고 Tool search(gpt-5.4+)가 있습니다.5

이 도구들은 현행 표준인 Responses API 기준이며, 일부는 레거시 Assistants API에서도 지원됐지만 deprecated입니다.5

OpenAI Agents SDK에서 호스티드 도구를 쓸 때(OpenAIResponsesModel 사용 시)는 전용 클래스들이 있습니다 — WebSearchTool, FileSearchTool, CodeInterpreterTool, HostedMCPTool, ImageGenerationTool, ToolSearchTool입니다.6

앞서 본 인자 예시가 여기서도 같은 역할을 합니다. "City and country e.g. Bogotá, Colombia"5 같은 설명이 모델이 값을 올바르게 채우게 만드는 단서이며, Anthropic의 대응 예시는 "The city and state, e.g. San Francisco, CA"입니다.1

MCP 도구 — 프로토콜 메시지·결과 타입·어노테이션

섹션 제목: “MCP 도구 — 프로토콜 메시지·결과 타입·어노테이션”

MCP는 모델·클라이언트와 분리된 별도 서버가 도구를 노출하는 프로토콜입니다. 프로토콜 메서드는 둘이 중심입니다.

tools/list는 사용 가능한 도구 목록을 페이지네이션과 함께 반환하고(커서는 cursor/nextCursor), tools/call{name, arguments}로 도구를 부릅니다.4 서버는 자신이 도구를 제공한다는 사실을 capability로 반드시(MUST) 선언해야 합니다({tools: {listChanged: true}}).4 도구 목록이 바뀌면 listChanged를 선언한 서버는 notifications/tools/list_changed를 보내는 게 좋습니다(SHOULD).4

tools/call의 응답은 CallToolResult입니다. content 배열, isError(불리언), 그리고 선택적 structuredContent로 이루어집니다.4

content의 타입은 다섯입니다 — text, image(data+mimeType), audio(data+mimeType), resource_link(uri+name+mimeType), resource(임베디드). 모든 content는 선택적 annotations(audience/priority/lastModified)를 지원합니다.4

에러를 다루는 길이 둘이라는 점이 중요합니다. 프로토콜 에러는 JSON-RPC 차원의 에러로, 예를 들어 -32602는 알 수 없는 도구나 잘못된 인자를 뜻합니다.

도구 실행 에러는 결과 안에 isError: true를 넣고 content에 에러 메시지를 담는 방식입니다.4 앞 절의 Anthropic is_error와 같은 발상으로, “프로토콜이 깨진 것”과 “도구는 정상 호출됐지만 실행이 실패한 것”을 구분합니다.

어노테이션은 힌트일 뿐 — 그리고 보안

섹션 제목: “어노테이션은 힌트일 뿐 — 그리고 보안”

도구 어노테이션은 동작에 관한 힌트를 줍니다 — title, readOnlyHint, destructiveHint, idempotentHint, openWorldHint입니다.4 다만 이것은 힌트지 보장이 아닙니다.

클라이언트는 신뢰된 서버에서 온 것이 아니면 어노테이션을 신뢰하지 말아야 합니다(MUST).4 읽기 전용이라고 표시됐다는 이유로 정말 읽기 전용이라 믿어서는 안 된다는 뜻입니다.

MCP 스펙은 보안을 의무·권장으로 못 박습니다. 도구는 model-controlled이므로, 항상 사람이 루프 안에서 도구 호출을 거부할 수 있어야 합니다(SHOULD).4 클라이언트는 민감한 작업에 사용자 확인을 받고(SHOULD), 서버 호출 전에 도구 입력을 사용자에게 보여 데이터 유출을 막으며, 결과를 검증하고, 타임아웃을 두고, 감사 로깅을 해야 합니다(SHOULD). 서버는 입력 검증·접근제어·rate limit·출력 sanitize를 반드시(MUST) 해야 합니다.4

도구는 모델에게 실제로 세상을 바꿀 힘을 주기 때문에, 권한과 확인은 기능이 아니라 안전장치입니다. 이 확인·권한 메커니즘을 체계로 묶는 방법은 10. 안전장치에서 이어집니다.

필수 파라미터가 프롬프트에 없을 때 모델이 어떻게 행동하는지는 모델마다 다릅니다. Claude Opus는 누락을 인지하고 되묻는 경향이 강합니다.

반면 Claude Sonnet은 — 특히 출력 전 사고를 지시하면 — 묻기도 하지만, 합리적인 값을 추론·추측하기도 합니다.1 예를 들어 location 없이 “What’s the weather?”라고만 물으면 Sonnet은 location을 추측하기도 합니다.

이 추측 거동은 보장되지 않습니다. 프롬프트가 모호할수록, 저지능 모델일수록 추측이 늘어납니다. Opus는 충분한 컨텍스트가 없으면 추측 대신 명확화 질문을 할 가능성이 훨씬 높습니다.1

날씨 도구 하나를 정의하고 한 바퀴를 도는 최소 흐름입니다. 모델이 호출을 내놓으면, 하네스가 실행해 결과를 되돌립니다. 첫 블록만 잡지 말고 모든 tool_use를 순회하는 점에 주목하세요.

# 1) 도구 정의 — name + description(언제 쓰는지까지) + input_schema
tools = [{
"name": "get_weather",
"description": (
"특정 위치의 현재 날씨를 가져온다. 사용자가 날씨·기온을 물을 때 사용. "
"location이 주어지지 않으면 추측하지 말고 되물을 것."
),
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "도시명 예: 서울"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["location"],
"additionalProperties": False,
},
"strict": True, # 호출이 스키마와 정확히 일치하도록 강제
}]
resp = client.messages.create(model="claude-opus-4-8", max_tokens=1024,
tools=tools, messages=msgs)
# 2) 모델이 실행이 아니라 "호출 의도"를 돌려준다. 선행 text + 여러 tool_use가 섞일 수 있다.
if resp.stop_reason == "tool_use":
tool_results = []
for block in resp.content: # 첫 블록만 잡지 말고 끝까지 순회
if block.type == "tool_use":
try:
result = run_get_weather(**block.input) # 3) 하네스가 실행
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id, # id로 호출과 결과를 연결
"content": result,
})
except Exception as e:
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": str(e),
"is_error": True, # 에러도 누락 없이 알린다
})
msgs += [
{"role": "assistant", "content": resp.content},
{"role": "user", "content": tool_results}, # 4) 병렬 결과는 한 user 메시지에
]
# 다음 turn에서 모델이 결과를 읽고 사용자에게 답한다

description과 인자 설명이 모델의 선택을 좌우하고, 실행은 전적으로 하네스 쪽 run_get_weather에서 일어납니다. tool_use_id로 호출과 결과를 묶고, 실패는 is_error로 알리며, 여러 결과를 하나의 user 메시지에 모은다는 세 규칙이 사이클의 골격입니다.

  • 도구 호출의 최소 단위(요청→실행→결과 반환)와 tool_use/tool_result 블록 구조·tool_use_id 연결·is_error를 설명할 수 있습니다.
  • Anthropic의 1차 분류가 ‘클라이언트 vs 서버(실행 위치)‘이고, 5갈래는 실무 형태임을 구분할 수 있습니다.
  • tool_choice 4옵션과, any/tool 강제 호출이 prefill로 선행 설명·CoT를 막는 부작용을 압니다.
  • 병렬 호출과 disable_parallel_tool_use, 병렬 결과를 한 user 메시지에 모으는 규칙을 압니다.
  • 도구가 30~50개를 넘으면 정확도가 떨어지고, defer_loading+tool search로 55k→85%+ 절감하며 35개만 로드하는 메커니즘을 압니다.
  1. Anthropic — Tool use with Claude (overview) 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

  2. Anthropic — Tool search tool 2 3 4 5 6 7 8 9 10 11 12 13

  3. Anthropic — Define tools (tool_choice·schema·best practices) 2 3 4 5 6 7 8 9 10 11 12 13

  4. Model Context Protocol — Tools spec 2 3 4 5 6 7 8 9 10 11 12 13

  5. OpenAI — Tools guide (Platform) 2 3 4 5 6 7

  6. OpenAI Agents SDK — Tools 2 3 4 5 6 7