サーバー実行ツールは、次の仕組みを共有しています: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というstop reasonを返すことがあります。
pause_turnのstop reasonを処理する方法は次のとおりです:
client = anthropic.Anthropic()
# Web検索を使用した最初のリクエスト
response = client.messages.create(
model="claude-opus-5",
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-5",
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が得られるまで継続してください。その際、他のリトライループと同様に継続回数に上限を設けてください。その他のstop_reasonの値と一般的な処理パターンについては、stop reasonとフォールバックを参照してください。
Claudeは、同じ並列ツール呼び出しのグループ内でサーバーツールとクライアントツールを呼び出すことができます。たとえば、web_fetchとユーザー定義ツールを一緒に呼び出す場合です。クライアントツールとは、あなたのコードが実行し、tool_useブロックを生成するあらゆるツールのことで、ユーザー定義のものでも、BashツールのようなAnthropicスキーマのクライアントツールでも構いません。この状況が発生すると、APIはサーバーツールを実行しません。クライアントツールを先に実行できるよう、即座にレスポンスを返します:
stop_reasonは"pause_turn"ではなく"tool_use"になります。contentにはserver_tool_useブロックとクライアントのtool_useブロックが含まれますが、サーバーツールの結果ブロックは含まれません。その呼び出しはまだ完了していないためです。idを持つserver_tool_useブロックを探すことで、この状態を検出してください。MCPコネクターからのmcp_tool_useブロックも同じように動作します。同じレスポンス内にすでに結果ブロックがあるサーバーツール呼び出しは完了しており、あなたが何かをする必要はありません。{
"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ブロックに対して1つずつ、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によって対応付けられます。このフローでは、それらは2つの異なるレスポンスで届き、server_tool_useブロックは2つ目のレスポンスでは繰り返されません。以降のリクエストでは、やり取り全体を順番どおりにmessages配列に保持してください。最初のレスポンスをassistantメッセージとして、次にtool_resultのユーザーメッセージ、そして次のレスポンスを別のassistantメッセージとして保持します。これは他のツール使用のやり取りを蓄積する場合と同じ方法です。
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 ブロックは未完了であり、その結果は後続のレスポンスで届きます。
# 同じツールを指定して、クライアントの 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が2種類の呼び出しを混在させない場合にも正しく動作します。クライアントの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はそれを設定するよう指示するバリデーションエラーを返します。
ウェブにアクセスするサーバーツールは、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で拒否されます。
ウェブ検索とウェブフェッチの_20260209以降のバージョンは、検索結果に対して動的フィルターを適用するために内部的にコード実行を使用します。
サーバーツールイベントは、通常の「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?