도구 호출 처리하기
도구 호출 처리하기 (Handle tool calls)
이 페이지에서는 도구 호출 수명 주기를 다뤄요. Claude의 응답에서 tool_use 블록을 읽고, 응답에 tool_result 블록을 형식화하고, 오류를 알리는 방법까지 살펴봐요. 이 과정을 자동으로 처리해주는 SDK 추상화는 Tool Runner를 참고해요.
출처: 문서
본문
이 페이지에서는 도구 호출 수명 주기를 다뤄요. Claude의 응답에서 tool_use 블록을 읽고, 응답에 tool_result 블록을 형식화하고, 오류를 알리는 방법을 살펴볼게요. 이 과정을 자동으로 처리하는 SDK 추상화는 Tool Runner를 참고해요.
참고 (Note) Tool Runner로 더 간단하게: 이 페이지에서 설명하는 수동 도구 처리는 Tool Runner가 자동으로 관리해줘요. 도구 실행을 직접 제어해야 할 때 이 페이지를 사용하세요.
Claude의 응답은 클라이언트 또는 서버 도구를 쓰는지에 따라 달라져요.
클라이언트 도구의 결과 처리하기 (Handling results from client tools)
응답은 stop_reason이 tool_use이고 하나 이상의 tool_use 콘텐츠 블록을 가져요. 여기에는 다음이 포함돼요:
id: 특정 도구 사용 블록의 고유 식별자예요. 나중에 도구 결과를 매칭하는 데 사용돼요.name: 사용 중인 도구의 이름이에요.input: 도구의input_schema에 맞는, 도구에 전달되는 입력을 담은 객체예요.
computer use 또는 browser use 도구셋 멤버의 tool_use 블록은 toolset_name 필드("computer" 또는 "browser")도 함께 가져요. 그 name은 Claude가 호출하는 멤버 도구(예: screenshot이나 navigate)이므로, 두 필드 모두로 디스패치하세요.
tool_use 콘텐츠 블록이 있는 예시 API 응답
{
"id": "msg_01Aq9w938a90dw8q",
"model": "claude-opus-5-5",
"stop_reason": "tool_use",
"role": "assistant",
"content": [
{
"type": "text",
"text": "I'll check the current weather in San Francisco for you."
},
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "get_weather",
"input": { "location": "San Francisco, CA", "unit": "celsius" }
}
]
}
클라이언트 도구에 대한 도구 사용 응답을 받으면 다음을 해야 해요:
-
tool_use블록에서name,id,input을 추출해요. -
코드베이스에서 해당 도구 이름과 일치하는 실제 도구를 실행하고, 도구
input을 전달해요. -
role이user이고tool_result타입과 다음 정보를 담은content블록을 가진 새 메시지를 보내서 대화를 계속해요.tool_use_id: 이 결과가 응답하는 도구 사용 요청의id예요.content(선택): 도구의 결과예요. 문자열(예:"content": "15 degrees"), 중첩 콘텐츠 블록 리스트(예:"content": [{"type": "text", "text": "15 degrees"}]), 또는 문서 블록 리스트(예:"content": [{"type": "document", "source": {"type": "text", "media_type": "text/plain", "data": "15 degrees"}}])일 수 있어요. 이 콘텐츠 블록은text,image,document, 또는search_result타입을 사용할 수 있어요.is_error(선택): 도구 실행에 오류가 발생한 경우true로 설정해요.
computer use 또는 browser use 멤버 블록에 응답하는 tool_result는 tool_use 블록과 같은 toolset_name 값을 반드시 그대로 담아야 해요. 이 값을 빼면 거부돼요. 그 content도 더 좁아요. 멤버 결과는 text와 image 블록만 담을 수 있고, browser use 결과는 browser_state 블록 하나를 추가할 수 있어요 (탭 관리 멤버는 그 블록만 반환해요).
참고 (Note) 중요한 형식 요구 사항:
- 도구 결과 블록은 메시지 히스토리에서 해당 도구 사용 블록 바로 뒤에 위치해야 해요. 어시스턴트의 도구 사용 메시지와 사용자의 도구 결과 메시지 사이에 어떤 메시지도 넣을 수 없어요.
- 도구 결과를 담은 user 메시지에서는
tool_result블록이 content 배열에서 맨 앞에 와야 해요. 어떤 텍스트도 모든 도구 결과 뒤에 와야 해요.- 어시스턴트 턴이 아직 결과 블록이 없는 서버 도구도 호출했다면, user 메시지는
tool_result블록만 담아야 해요. 결과 뒤의 텍스트는 턴을 일찍 끝내는데, Claude가 직접 호출한 서버 도구의 경우 요청이 그 해결되지 않은 서버 도구를 명명하는 400 오류로 실패해요. 자세한 내용은 중지 이유와 폴백을 참고해요.
예를 들어, 이렇게 하면 400 오류가 발생해요:
{
"role": "user",
"content": [
{ "type": "text", "text": "Here are the results:" }, // ❌ Text before tool_result
{ "type": "tool_result", "tool_use_id": "toolu_01" /* ... */ }
]
}
어시스턴트 턴이 클라이언트 도구만 호출할 때는 이렇게가 맞아요:
{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "toolu_01" /* ... */ },
{ "type": "text", "text": "What should I do next?" } // ✅ Text after tool_result
]
}
"tool_use ids were found without tool_result blocks immediately after" 같은 오류를 받으면 도구 결과 형식이 올바른지 확인해보세요.
경고 (Warning) 도구 결과는 여러분이 통제하지 못하는 출처(웹 페이지, 수신 이메일, 사용자 업로드, 타사 API)의 콘텐츠를 자주 담아요. 그 콘텐츠를 신뢰할 수 없는 것으로 취급하세요. 이를 조작할 수 있는 공격자가 Claude를 리디렉션하려는 지침을 심어둘 수 있어요(간접 프롬프트 주입). 신뢰할 수 없는 콘텐츠는
system프롬프트나 일반 usertext블록 대신tool_result블록 안에 두고, 더 강화하려면 탈옥·프롬프트 주입 완화를 참고해요.
성공적인 도구 결과 예시
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "15 degrees"
}
]
}
이미지가 있는 도구 결과 예시
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": [
{ "type": "text", "text": "15 degrees" },
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/jpeg",
"data": "/9j/4AAQSkZJRg..."
}
}
]
}
]
}
빈 도구 결과 예시
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9"
}
]
}
문서가 있는 도구 결과 예시
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": [
{ "type": "text", "text": "The weather is" },
{
"type": "document",
"source": {
"type": "text",
"media_type": "text/plain",
"data": "15 degrees"
}
}
]
}
]
}
도구 결과를 받으면 Claude는 그 정보를 사용해 원래 사용자 프롬프트에 대한 응답을 계속 생성해요.
서버 도구의 결과 처리하기 (Handling results from server tools)
Claude는 도구를 내부적으로 실행하고 추가적인 사용자 상호작용 없이 결과를 응답에 직접 통합해요.
참고 (Note) 응답에는 클라이언트
tool_use블록과 아직 결과 블록이 없는server_tool_use블록이 함께 포함될 수 있어요. 그 서버 도구 호출은 아직 끝나지 않았고, 결과 블록은 이후 응답에서 도착해요. 클라이언트 도구에 대한tool_result블록만 담은 user 메시지로 답하고 같은tools배열을 유지하세요. Claude가 직접 호출한 서버 도구의 경우 API가 그 요청에서 실행하고 다음 응답이 그 결과 블록으로 시작해요. 자세한 내용은 중지 이유와 폴백을 참고해요.
팁 (Tip) 다른 API와의 차이점
도구 사용을 분리하거나
tool·function같은 특수 역할을 쓰는 API와 달리, Claude API는 도구를user와assistant메시지 구조에 직접 통합해요.메시지에는
text,image,tool_use,tool_result블록 배열이 들어 있어요.user메시지는 클라이언트 콘텐츠와tool_result를 포함하고,assistant메시지는 AI 생성 콘텐츠와tool_use를 포함해요.
is_error로 오류 처리하기 (Handling errors with is_error)
Claude와 함께 도구를 쓸 때 발생할 수 있는 오류 유형은 몇 가지가 있어요:
도구 실행 오류 (Tool execution error)
도구 자체가 실행 중에 오류를 던지면(예: 날씨 데이터를 가져올 때 네트워크 오류), content에 오류 메시지를 "is_error": true와 함께 반환할 수 있어요:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "ConnectionError: the weather service API is not available (HTTP 500)",
"is_error": true
}
]
}
그러면 Claude는 이 오류를 사용자에게 하는 응답에 통합해요. 예를 들어: "죄송합니다. 날씨 서비스 API를 사용할 수 없어 현재 날씨를 가져오지 못했습니다. 나중에 다시 시도해주세요."
팁 (Tip) 교훈적인 오류 메시지를 작성하세요.
"failed"같은 일반 오류 대신 무엇이 잘못됐고 Claude가 다음에 무엇을 시도해야 하는지 담으세요(예:"Rate limit exceeded. Retry after 60 seconds."). 이렇게 하면 Claude가 추측하지 않고도 회복하거나 적응하는 데 필요한 컨텍스트를 얻어요.
잘못된 도구 이름 (Invalid tool name)
Claude의 도구 사용 시도가 유효하지 않으면(예: 필수 파라미터 누락), 보통 Claude가 도구를 올바르게 쓰기에 충분한 정보가 없었다는 뜻이에요. 개발 중 최선의 방법은 도구 정의에서 더 상세한 description 값으로 요청을 다시 시도하는 거예요.
하지만 오류를 나타내는 tool_result로 대화를 앞으로 계속하고 Claude가 누락된 정보를 채워 도구를 다시 사용하게 할 수도 있어요:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "Error: Missing required 'location' parameter",
"is_error": true
}
]
}
도구 요청이 유효하지 않거나 파라미터가 누락되면 Claude는 사용자에게 사과하기 전에 수정하며 2-3번 재시도해요.
팁 (Tip) 잘못된 도구 호출을 완전히 없애려면 도구 정의에
strict: true를 써서 strict tool use를 사용하세요. 이렇게 하면 도구 입력이 항상 스키마와 정확히 일치하는 것이 보장되어 파라미터 누락과 타입 불일치를 막아줘요.
서버 도구 오류 (Server tool errors)
서버 도구가 오류를 만나면(예: 웹 검색의 네트워크 문제), Claude는 그 오류를 투명하게 처리하고 사용자에게 대체 응답이나 설명을 제공하려 해요. 클라이언트 도구와 달리 서버 도구에 대해서는 is_error 결과를 처리할 필요가 없어요.
특히 웹 검색의 경우 가능한 오류 코드는 다음과 같아요:
too_many_requests: 요금 한도 초과invalid_input: 잘못된 검색 쿼리 파라미터max_uses_exceeded: 최대 웹 검색 도구 사용 횟수 초과query_too_long: 쿼리가 최대 길이를 초과unavailable: 내부 오류 발생
더 알아보기 (Learn more)
- 병렬 도구 사용 (Parallel tool use) — Claude가 한 턴에 여러 도구를 호출하는 응답 처리하기
- Tool Runner (SDK) — SDK가
tool_use루프, 결과 형식화, 재시도를 관리하게 하기 - 도구 정의하기 (Define tools) — Claude를 올바른 도구로 이끄는 스키마와 설명 작성하기