メインコンテンツまでスキップ

プログラマティック・ツール呼び出し

上級
What you'll learn
  • Claude がサンドボックス内からツールを呼ぶとき実際に何が起きているのか、そしてなぜツール自体はあなたのマシン上で実行されるのかを理解する
  • allowed_callers で正しく有効化し、なぜそれがセキュリティ境界ではないのかを知る
  • 現実の数字を押さえる:何をどれだけ節約でき、どのワークロードに効き、どこでコストがかかるのか
  • 本番環境で 400 や TimeoutError を生む 5 つの失敗パターンを避ける

この機能が解決する問題

従来のツール使用は「会話」です。Claude が 1 回のツール呼び出しを求め、あなたが答え、その結果まるごとがコンテキストウィンドウに入り、Claude がそれを読んで次を求める。20 回のルックアップは、20 回の推論パスと、コンテキストに永久に居座る 20 個の生ペイロードを意味します。

そのペイロードのほとんどは無駄です。20 人の従業員のうち誰が経費予算を超過したかを知りたいだけなら、Claude に必要なのは全明細ではなく、ほんの数人の名前です。ところが従来のツール使用では、明細はモデルにフィルタしてもらうために、モデルを通過しなければなりません。

プログラマティック・ツール呼び出しはこれを反転させます。Claude が Python スクリプトを書き、そのスクリプトがループであなたのツールを呼び、結果をフィルタし、スクリプトがprint したものだけがモデルに戻ります。生データはコンテキストウィンドウに一切入りません。

実際に起きていること

この機能の要約のほとんどが取り違えている点がここです:あなたのツールはサンドボックス内では実行されません。 Anthropic のコンテナはあなたのデータベースにアクセスできません。

実際に起きているのは、Claude の Python コードが実行の途中で一時停止し、API がその呼び出しをあなたに手渡し、あなたが答えるとインタプリタが再開する、という流れです:

Guided walkthrough1 of 5
  1. スクリプトはコード実行コンテナ内で走ります。あなたのツールは、そのコードからは非同期 Python 関数として見えます — ツールごとに 1 つ、引数の dict を 1 つ受け取り、文字列を返します。

関数は async なので、Claude は asyncio.gather でファンアウトして 10 個のツールを同時に叩けます — 従来のツール使用が並列 tool ブロックで近似することしかできなかったことです。

Claude が生成するコードの実際の姿

import json

rows = json.loads(await query_database({"sql": "<sql>"}))
top = sorted(rows, key=lambda r: r["revenue"], reverse=True)[:5]
print(f"Top 5 customers: {top}")

json.loads に注目してください。ツール関数が返すのは文字列です — あなたが返送する tool_result のリテラルなテキストそのものです。ツールの説明文に「行のリストを JSON オブジェクトとして返す」と書かれていなければ、Claude にはそれをデシリアライズできると知る手立てがなく、データを不透明な塊として扱ってしまいます。ツール説明文の出力フォーマットの一文は、もはやドキュメントではなく、実質的なコードになります。 この機能を採用するとき、あなたが書く中でもっともレバレッジの高い一行です。

有効化する

コードから呼ばせたいツールに 1 つフィールドを足し、リクエストにコード実行ツールを含めるだけです:

ツールでプログラマティック呼び出しを有効化する

{
"name": "query_database",
"description": "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
"input_schema": { "type": "object", "properties": { "sql": { "type": "string" } }, "required": ["sql"] },
"allowed_callers": ["code_execution_20260120"]
}

allowed_callers は 3 つの形を取ります:

意味
["direct"]従来のツール使用。フィールドを省略した場合のデフォルト。
["code_execution_20260120"]Claude はコード内からのみ呼ぶよう誘導される。
["direct", "code_execution_20260120"]どちらでも可。ドキュメントはこれを推奨していません — どちらか一方を選び、Claude に曖昧さのないシグナルを与えてください。

レスポンス中のすべての tool_use ブロックには caller が付きます:{"type": "direct"} か、スクリプトを走らせた server_tool_use ブロックと tool_id が一致するコード実行 caller のどちらかです。呼び出しをどのスクリプトに帰属させるかは、これで判断します。

これはセキュリティ境界ではない

ドキュメントはこの点について異例なほど率直で、逆に思い込みやすいので繰り返す価値があります:allowed_callersツールが Claude にどう提示されるかを制御するだけです。API レベルの強制ブロックではありません。Claude は強く従うよう誘導されますが、あなたのクライアントは、定義したどのツールについても直接の tool_use を受け取る可能性に備えなければならず、このフィールドを認可メカニズムとして使ってはいけません。認可は、昔からそうだったように、ツールハンドラの中にあります。

数字

Anthropic 自身が公表している数値です。複雑さに見合うかどうかの判断材料にしてください:

  • 複雑なリサーチタスクでは、平均使用量が 43,588 トークンから 27,297 トークンへ — 37% 削減
  • GIA ベンチマークでは精度が 46.5% から 51.2% へ上昇。社内ナレッジ検索では 25.6% から 28.5% へ。トークンが減りかつ回答が良くなる — モデルが生ペイロードに溺れる代わりに、結論の上で推論するからです。
  • エージェント検索ベンチマーク(BrowseComp、DeepSearchQA)では、基本的な検索ツールの上にプログラマティック呼び出しを重ねることで、入力トークンを 24% 削減しつつ平均 11% の性能向上
  • レイテンシ:20 回以上のツール呼び出しを 1 つのコードブロックでオーケストレーションすると、19 回以上の推論パスが消えます。

勝ち筋の形が手がかりです。3 回以上の依存する呼び出し、ループ、フィルタ、ファンアウトがあるときに効きます。Claude がツール呼び出しをちょうど 1 回だけ行い、その答え全体を読みたいだけのときには、何の得もなく、コンテナ代だけがかかります。

Watch out
  • Claude Haiku 4.5 は新しいツールタイプを受け付けますが、プログラマティック・ツール呼び出しも、それに依存する REPL 状態の永続化もサポートしていません。新しいバージョンは、そこでは黙って code_execution_20250825 のように振る舞います。コスト目的で Haiku にルーティングしているなら、この機能は得られていません — しかもそれを知らせるエラーは出ません。

コスト

プログラマティック・ツール呼び出しはコード実行として課金され、コード実行は呼び出し回数ではなくコンテナ時間で課金されます:

  • 組織あたり月 1,550 時間まで無料。
  • それを超えると、コンテナごとに 1 時間 $0.05
  • 実行時間には 5 分の最小単位があります — 2 秒のスクリプトでもコンテナ 5 分ぶん課金されます。
  • リクエストにファイルを添付した場合、ツールが一度も呼ばれなくても実行時間が課金されます。ファイルはいずれにせよコンテナにプリロードされるからです。
  • 同じリクエストが web search または web fetch(web_search_20260209 / web_fetch_20260209 以降)も使っている場合は無料です。

内面化しておくべき帰結が 2 つあります。第一に、5 分の下限は短命なコンテナを多数作るのが高くつくパターンであることを意味します。セッションを通じて 1 つのコンテナを使い回すのが安いパターンです。第二に、この機能は Zero Data Retention の対象外です — ZDR が契約上の要件なら、これはチューニングの余地ではなく、ハードストップです。

壊れ方は 5 通り

Guided walkthrough1 of 5
  1. 保留中のプログラマティック・ツール呼び出しがあるとき、あなたのレスポンスメッセージは tool_result ブロックのみを含まなければなりません。テキスト+ツール結果はダメ。ツール結果のあとに丁寧な一文を添えるのもダメ。tool_result ブロックだけです。

バージョン文字列の読み解き

3 つのコード実行バージョンはすべて一般提供されており、ベータヘッダーは不要です:

バージョン追加されるもの
code_execution_20250825ベースライン。Bash + Python + ファイル操作。現行の全モデルでサポート。
code_execution_20260120REPL 状態の永続化とプログラマティック・ツール呼び出しを追加。必要なのはこれです。
code_execution_20260521ランタイムは 20260120同一。唯一の違いは、ツール説明文が Python セルあたり 90 秒の実時間上限を Claude に伝えるため、長時間実行セルの時間配分ができる点です。上限を超えたセルは、detection_timeout ステータスとともに 0 以外の return_code を返します。

最後の行は、API 設計として注目に値します:バージョンアップの中身がまるごとモデルへのより良いプロンプトなのです。両方の文字列は allowed_callers の中で互換であり、どちらを宣言してもレスポンスは常に caller を code_execution_20260120 としてタグ付けします。

コンテナ自体にはインターネットアクセスがありません — Claude は実行時に pip install できないので、プリインストールされたライブラリ群(pandas、numpy、scipy、scikit-learn、statsmodels ほか)だけが使えます。コンテナは約 5 分の非アクティブ後にチェックポイントされ、ID で復元でき、作成から 30 日で期限切れになります。

いつ使うべきか

モデルが「推論器」としてではなく、ループとフィルタとして使われているときに、プログラマティック・ツール呼び出しを選んでください:N 個のエンティティにまたがる一括ルックアップ、条件が満たされた時点での早期終了、中間結果に基づく条件付きツール選択、200 KB のログダンプを重要な 10 行まで圧縮すること。

問題が、1 回も呼び出す前に定義がコンテキストを食い潰していることなら、代わりに Tool Search Tool を選んでください — ツールを defer_loading: true にすれば、Claude は必要なときにロードします。両者は代替ではなく補完関係です:tool search が正しいツールを見つけ、プログラマティック呼び出しがそれを安価に実行します。ツール定義がおよそ 10K トークンを超えるなら、たぶん両方が必要です。

そして逆側から来ている場合 — MCP のツール結果でコンテキストが溺れているエージェント — なら、MCP のトークンコストコンテキストエンジニアリング から始めてください。もっとも安いトークンは、いまだに「送らなかったトークン」です。

Check yourself

0/5
  1. プログラマティック・ツール呼び出しの最中、あなたのツールは実際にはどこで実行されますか?
  2. ツールが direct に呼ばれるのを防ぐために allowed_callers を頼れますか?
  3. コスト削減のためエージェントを Claude Haiku 4.5 にルーティングし、code_execution_20260120 を渡しました。何が起きますか?
  4. 保留中のプログラマティック・ツール呼び出しがあるとき、返信メッセージに含めてよいのは何ですか?
  5. 新しいコンテナで 2 秒のスクリプトを実行しました。コード実行時間はどれだけ課金されますか?
Enter キーまたはスペースキーでカードを裏返します。左右の矢印キーでカードを移動できます。用語を表示しました。
1 / 7

出典と参考文献