서버에서 실행되는 도구는 다음과 같은 공통 메커니즘을 공유합니다: server_tool_use 블록, pause_turn 계속, 서버 도구와 클라이언트 도구가 혼합된 턴, "Zero Data Retention"(제로 데이터 보존), 즉 ZDR 적격성, 그리고 도메인 필터링. 개별 도구에 대해서는 도구 참조를 참조하세요.
server_tool_use 블록은 서버에서 실행되는 도구가 실행될 때 Claude의 응답에 나타납니다. 이 블록의 id 필드는 클라이언트 도구 호출과 구분하기 위해 srvtoolu_ 접두사를 사용합니다:
{
"type": "server_tool_use",
"id": "srvtoolu_01A2B3C4D5E6F7G8H9",
"name": "web_search",
"input": { "query": "latest quantum computing breakthroughs" }
}API는 도구를 내부적으로 실행합니다. 응답에서 호출과 그 결과를 볼 수 있지만, 실행을 직접 처리하지는 않습니다. 클라이언트 tool_use 블록과 달리 tool_result로 응답할 필요가 없습니다. 도구의 결과 블록(예: 웹 검색의 경우 web_search_tool_result)은 동일한 어시스턴트 턴에서 server_tool_use 블록 뒤에 나타나며, tool_use_id로 쌍을 이룹니다. Claude가 동시에 클라이언트 도구 중 하나를 호출하는 경우, server_tool_use 블록은 결과 없이 나타나고 응답은 stop_reason: "tool_use"로 끝납니다. 다음 요청에서 클라이언트 tool_result 블록을 반환하면 API가 해당 도구를 실행합니다.
웹 검색과 같은 서버 도구를 사용할 때, API는 서버 측 에이전트 루프에서 도구 호출을 실행합니다. 장시간 실행되는 턴에서 API는 해당 루프를 일시 중지하고 pause_turn 중지 이유를 반환할 수 있습니다.
pause_turn 중지 이유를 처리하는 방법은 다음과 같습니다:
client = anthropic.Anthropic()
# 웹 검색을 포함한 초기 요청
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
messages=[
{
"role": "user",
"content": "Search for comprehensive information about quantum computing breakthroughs in 2025",
}
],
tools=[{"type": "web_search_20250305", "name": "web_search", "max_uses": 10}],
)
# 응답의 stop_reason이 pause_turn인지 확인
if response.stop_reason == "pause_turn":
# 일시 중지된 콘텐츠로 대화 계속하기
messages = [
{
"role": "user",
"content": "Search for comprehensive information about quantum computing breakthroughs in 2025",
},
{"role": "assistant", "content": response.content},
]
# 계속 요청 전송
continuation = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
messages=messages,
tools=[{"type": "web_search_20250305", "name": "web_search", "max_uses": 10}],
)
print(continuation)
else:
print(response)pause_turn을 처리할 때:
server_tool_use 블록으로 끝날 수 있으며, 해당 도구가 계속 요청에서 누락되면 API가 유효성 검사 오류를 반환합니다.stop_reason을 확인하고 다른 중지 이유를 받을 때까지 계속하되, 다른 재시도 루프와 마찬가지로 계속 횟수에 상한을 두세요.다른 stop_reason 값과 일반적인 처리 패턴에 대해서는 중지 이유 및 대체 처리를 참조하세요.
Claude는 동일한 병렬 도구 호출 그룹에서 서버 도구와 클라이언트 도구를 함께 호출할 수 있습니다. 예를 들어 web_fetch와 사용자 정의 도구를 함께 호출할 수 있습니다. 클라이언트 도구란 사용자 정의 도구이든 Bash 도구와 같은 Anthropic 스키마 클라이언트 도구이든, 코드에서 실행되고 tool_use 블록을 생성하는 모든 도구를 의미합니다. 이런 경우 API는 서버 도구를 실행하지 않습니다. 클라이언트 도구를 먼저 실행할 수 있도록 즉시 반환합니다:
stop_reason은 "pause_turn"이 아니라 "tool_use"입니다.content에는 server_tool_use 블록과 클라이언트 tool_use 블록이 포함되지만, 서버 도구에 대한 결과 블록은 없습니다. 해당 호출은 아직 완료되지 않았습니다.id에 대응하는 결과 블록이 없는 server_tool_use 블록을 찾아 이 상태를 감지하세요. MCP 커넥터의 mcp_tool_use 블록도 동일하게 동작합니다. 동일한 응답에 이미 결과 블록이 있는 서버 도구 호출은 완료된 것이며 추가 작업이 필요하지 않습니다.프로그래밍 방식 도구 호출을 사용하는 경우, 동일한 응답 형태가 다른 의미를 가집니다. 클라이언트 tool_use 블록은 Claude가 직접 생성한 것이 아니라 code_execution 도구에서 실행 중인 코드에서 나온 것이며, 해당 블록의 caller 필드는 이를 호출한 code_execution 블록의 이름을 나타냅니다. 해당 코드는 이미 시작되었습니다. tool_result 블록을 기다리며 일시 중지된 상태이며, 이를 전송하면 지연된 도구를 시작하는 것이 아니라 실행을 재개합니다. code_execution 블록 자체의 결과 블록은 코드가 완료되면 도착하며, 이는 한 번 이상의 도구 결과 라운드가 필요할 수 있습니다. 후속 사용자 메시지 자체는 두 경우 모두 동일합니다. 프로그래밍 방식 도구 호출의 경우, 해당 페이지에서 설명하는 대로 응답의 container 필드에서 id도 함께 전달하세요.
{
"stop_reason": "tool_use",
"content": [
{
"type": "text",
"text": "I'll fetch the article and check your system at the same time."
},
{
"type": "server_tool_use",
"id": "srvtoolu_01HxbWnMRmbWyMfUtJKC45rA",
"name": "web_fetch",
"input": { "url": "https://example.com/article" }
},
{
"type": "tool_use",
"id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",
"name": "run_command",
"input": { "command": "uname -a" }
}
]
}턴을 계속하려면 클라이언트 도구를 실행하고, 해당 응답의 각 tool_use 블록에 대해 하나씩 tool_result 블록만으로 구성된 사용자 메시지를 전송하세요. 동일한 tools 배열을 유지하세요. 대기 중인 서버 도구를 더 이상 정의하지 않는 재개 요청은 but no `web_fetch` tool was provided로 끝나는 메시지와 함께 400 오류로 실패합니다.
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",
"content": "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"
}
]
}API는 결과를 아직 열려 있는 어시스턴트 턴에 연결하고, 지연된 서버 도구를 실행한 다음(일시 중지된 코드 실행의 경우 재개), Claude가 계속할 수 있도록 합니다. Claude가 직접 호출한 서버 도구의 경우, 다음 응답은 이전 응답의 server_tool_use id에 대응하는 결과 블록으로 시작하고, 그 뒤에 새로 생성된 콘텐츠와 새로운 stop_reason이 이어집니다:
{
"stop_reason": "end_turn",
"content": [
{
"type": "web_fetch_tool_result",
"tool_use_id": "srvtoolu_01HxbWnMRmbWyMfUtJKC45rA",
"content": {
"type": "web_fetch_result",
"url": "https://example.com/article",
"content": {
"type": "document",
"source": {
"type": "text",
"media_type": "text/plain",
"data": "Full text content of the article..."
}
}
}
},
{
"type": "text",
"text": "The article argues that... and your machine is running Linux..."
}
]
}server_tool_use 블록과 그 결과 블록은 위치가 아니라 tool_use_id로 쌍을 이룹니다. 이 흐름에서는 두 개의 서로 다른 응답으로 도착하며, server_tool_use 블록은 두 번째 응답에서 반복되지 않습니다. 이후 요청에서는 다른 도구 사용 교환을 누적하는 것과 동일한 방식으로 전체 교환을 messages 배열에 순서대로 유지하세요: 첫 번째 응답을 assistant 메시지로, tool_result 사용자 메시지, 그리고 다음 응답을 또 다른 assistant 메시지로 유지합니다.
후속 사용자 메시지에는 tool_result 블록 외에 아무것도 포함되어서는 안 됩니다. 결과 뒤에 텍스트와 같은 블록을 추가하면 API에 어시스턴트 턴이 끝났다고 알리는 것입니다. Claude가 직접 호출한 서버 도구의 경우, 이는 해결되지 않은 서버 도구 호출이 있는 상태로 턴을 남기게 되며, 요청은 400 invalid_request_error로 실패합니다:
`web_fetch` tool use with id `srvtoolu_01HxbWnMRmbWyMfUtJKC45rA` was found without a corresponding `web_fetch_tool_result` block결과 앞에 콘텐츠를 배치하거나, 일부 클라이언트 tool_use ID에만 응답하거나, tool_result 블록이 전혀 없는 후속 요청은 도구 호출 처리에 설명된 클라이언트 도구 오류와 함께 더 일찍 실패합니다:
`tool_use` ids were found without `tool_result` blocks immediately after: toolu_01PjgRJLbXrXEMZwDNYLnBqk. Each `tool_use` block must have a corresponding `tool_result` block in the next message.Claude에 추가 입력을 제공하려면 턴이 완료된 후 별도의 사용자 메시지로 전송하세요.
pause_turn과의 차이점: pause_turn 응답도 아직 실행되지 않은 server_tool_use 블록으로 끝날 수 있지만, 클라이언트 tool_use 블록이 대기 상태로 남는 경우는 없으므로 어시스턴트 콘텐츠를 그대로 다시 전송하여 계속합니다. 클라이언트 tool_use 블록이 대기 상태로 남는 응답은 stop_reason이 pause_turn인 경우가 없습니다. Claude가 도구를 호출하기 위해 중지할 때 stop_reason은 tool_use이며, 응답을 다시 전송하는 대신 클라이언트 tool_result 블록을 전송하여 계속합니다. 두 경우 모두 API는 다음 요청 시작 시 대기 중인 서버 도구를 실행합니다.
다음 예제는 사용자 정의 run_command 도구와 함께 웹 페치를 활성화하고 혼합 응답을 처리합니다:
client = anthropic.Anthropic()
tools = [
{"type": "web_fetch_20250910", "name": "web_fetch", "max_uses": 5},
{
"name": "run_command",
"description": "Run a shell command on this computer and return its output.",
"input_schema": {
"type": "object",
"properties": {
"command": {"type": "string", "description": "The command to run"}
},
"required": ["command"],
},
},
]
messages = [
{
"role": "user",
"content": "Summarize https://example.com/article and run uname -a to tell me what system this is on.",
}
]
response = client.messages.create(
model="claude-opus-4-8", max_tokens=1024, tools=tools, messages=messages
)
tool_results = [
{
"type": "tool_result",
"tool_use_id": block.id,
# 여기서 도구를 실행하세요. 이 예제는 고정된 문자열을 반환합니다.
"content": "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux",
}
for block in response.content
if block.type == "tool_use"
]
if response.stop_reason == "tool_use" and tool_results:
# 이 응답에 결과 블록이 없는 server_tool_use 블록은 아직 완료되지 않은 것이며, 결과는 이후 응답에서 도착합니다.
# 동일한 tools와 함께 클라이언트 tool_result 블록만 다시 보내세요.
continuation = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
tools=tools,
messages=[
*messages,
{"role": "assistant", "content": response.content},
{"role": "user", "content": tool_results},
],
)
# web_fetch가 지연된 경우 이 요청에서 실행되며, 해당
# web_fetch_tool_result가 continuation.content의 첫 번째 블록이 됩니다.
print(continuation)
else:
print(response)이 코드는 Claude가 두 종류의 호출을 혼합하지 않는 경우에도 올바르게 작동합니다. 클라이언트 tool_use 블록만 있는 턴은 동일한 계속 경로를 따르며, 서버 도구 호출만 있는 턴은 클라이언트 tool_result 블록이 필요하지 않습니다. 해당 결과 블록은 일반적으로 이미 존재하며, pause_turn 응답과 같이 일시 중지된 상태로 반환되는 경우에는 그대로 다시 전송합니다.
웹 검색(web_search_20250305) 및 웹 페치(web_fetch_20250910)의 기본 버전은 Zero Data Retention (ZDR) 적격 대상입니다.
동적 필터링이 포함된 _20260209 이후 버전은 동적 필터링이 내부적으로 코드 실행에 의존하기 때문에 기본적으로 ZDR 적격 대상이 아닙니다.
_20260209 이후 서버 도구를 ZDR과 함께 사용하려면 도구에 "allowed_callers": ["direct"]를 설정하여 동적 필터링을 비활성화하세요:
{
"type": "web_search_20260209",
"name": "web_search",
"allowed_callers": ["direct"]
}이렇게 하면 도구가 직접 호출로만 제한되어 내부 코드 실행 단계를 우회합니다.
allowed_callers는 도구가 호출될 수 있는 방식을 제어합니다: Claude가 직접 호출("direct"), 코드 실행 컨테이너 내부에서 호출(예: "code_execution_20260120"), 또는 둘 다. 웹 도구의 _20260209 버전은 기본적으로 코드 실행 호출자만 허용하며, 이전 버전은 기본적으로 ["direct"]입니다. 프로그래밍 방식 도구 호출을 지원하지 않는 모델에서는 이러한 버전에 allowed_callers: ["direct"]가 필요합니다. 이를 설정하지 않으면 API가 이를 설정하라는 유효성 검사 오류를 반환합니다.
웹 페치가 ZDR 적격 구성으로 사용되는 경우에도, Claude가 웹사이트에서 콘텐츠를 가져올 때 웹사이트 게시자가 URL에 전달된 매개변수를 보존할 수 있습니다.
웹에 접근하는 서버 도구는 Claude가 접근할 수 있는 도메인을 제어하기 위해 allowed_domains 및 blocked_domains 매개변수를 허용합니다. 둘 다 도구 객체의 필드입니다:
{
"type": "web_search_20250305",
"name": "web_search",
"allowed_domains": ["example.com", "docs.python.org"]
}도메인 필터를 사용할 때:
https://example.com 대신 example.com 사용).example.com은 docs.example.com을 포함).docs.example.com은 example.com이나 api.example.com이 아닌 해당 하위 도메인의 결과만 반환).example.com/blog는 example.com/blog/post-1과 일치).allowed_domains 또는 blocked_domains 중 하나를 사용할 수 있지만, 동일한 요청에서 둘 다 사용할 수는 없습니다.와일드카드 지원:
*)는 도메인 자체에는 허용되지 않으며, 도메인 뒤의 경로에만 허용됩니다.example.com/*, example.com/*/articles*.example.com, ex*.com유효하지 않은 도메인 형식은 요청 시점에 400 invalid_request_error로 거부됩니다.
요청 수준 도메인 제한은 Claude Console에서 구성된 조직 수준 도메인 제한과 함께 작동합니다. 요청 수준 allowed_domains는 조직 수준 허용 목록의 하위 집합이어야 하며, 그 외의 항목이 있으면 API가 유효성 검사 오류를 반환합니다. 조직에서 차단한 도메인은 오류를 반환하는 대신 요청 수준 허용 목록에서 제거됩니다.
도메인 이름의 유니코드 문자는 동형 문자 공격(homograph attack)을 통해 도메인 필터를 우회할 수 있습니다. аmazon.com(키릴 문자 а 사용)은 amazon.com과 동일하게 보이지만 다른 도메인입니다. 허용 및 차단 목록에는 ASCII 전용 도메인 이름을 사용하고, 기존 항목에 비 ASCII 문자가 있는지 검토하세요.
웹 검색 및 웹 페치의 _20260209 이후 버전은 검색 결과에 동적 필터를 적용하기 위해 내부적으로 코드 실행을 사용합니다.
이러한 버전에는 code_execution 도구를 추가할 필요가 없습니다. 동적 필터링이 실행될 때 API가 요청에 대해 코드 실행을 자동으로 프로비저닝하며, 두 도구는 단일 실행 컨테이너를 공유합니다. 코드 실행 도구를 포함하는 경우 code_execution_20260120 이상을 사용하세요. API는 이러한 웹 도구 버전과 함께 이전 코드 실행 버전을 거부합니다.
서버 도구 이벤트는 일반적인 "server-sent events"(서버 전송 이벤트), 즉 SSE 흐름의 일부로 스트리밍됩니다. Claude가 직접 호출하는 server_tool_use 블록은 클라이언트 tool_use 블록처럼 스트리밍됩니다: content_block_start 이벤트 다음에 input_json_delta 이벤트가 이어집니다. 결과 블록은 델타 없이 단일 content_block_start 이벤트로 완전한 형태로 도착합니다.
전체 이벤트 참조는 스트리밍을 참조하세요. 개별 도구 페이지는 차이가 있는 경우 도구별 이벤트 이름을 문서화합니다.
모든 서버 도구는 배치 처리를 지원합니다. 배치에서 에이전트 루프는 동기 요청과 동일하게 실행되며, 턴당 반복 제한이 더 높습니다. 루프가 해당 제한에 도달하면 응답은 stop_reason: "pause_turn"으로 끝납니다. 반환된 콘텐츠로 후속 요청을 제출하여 계속할 수 있습니다. 자세한 내용은 서버 도구와 에이전트 루프를 참조하세요.
일반적인 배치 워크로드에는 웹의 정보로 데이터셋을 보강하기, 대량의 문서를 최신 소스와 대조하기, 여러 파일에 대해 분석 코드 실행하기 등이 포함됩니다.
증상별 해결 진단 표로 가장 일반적인 도구 사용 오류를 해결하세요.
웹을 검색하고 결과를 인용하세요.
특정 URL에서 콘텐츠를 가져와 읽어 Claude의 컨텍스트를 실시간 웹 콘텐츠로 보강하세요.
샌드박스 컨테이너에서 Python 및 bash 코드를 실행하여 데이터를 분석하고, 파일을 생성하고, 솔루션을 반복 개선하세요.
필요에 따라 도구를 검색하고 로드하세요.
Was this page helpful?