OpenAIの「Programmatic Tool Calling」──モデルがコードを書いてツールを並列実行し、中間結果を圧縮する
OpenAI Agents SDK for JavaScript v0.14.0にProgrammatic Tool Callingへの対応が追加された。対応モデルが隔離されたV8ランタイム上でJavaScriptを生成し、複数のツールを並列・ループ・条件分岐で呼び出して中間結果を絞り込んでから返す仕組みで、公式ガイドが定める使い分けの基準や制約を確認した。

目次
エージェントに複数のツールを組み合わせて使わせるとき、モデルが1つツールを呼んでは結果を確認し、また次のツールを呼ぶ、という往復を繰り返すのが標準的な動き方だ。OpenAIのAgents SDK for JavaScript v0.14.0(2026年7月28日公開)のリリースノートに、この往復を減らす新機能への対応が記録されている。
3行まとめ
- Programmatic Tool Callingは、対応モデルが隔離されたV8ランタイム上でJavaScriptを生成し、複数ツールを並列・条件分岐で呼び出して中間結果を圧縮してから返す機能。openai-agents-js v0.14.0(2026年7月28日)で対応した
- レスポンスは
program・function_call・program_outputという3種のアイテムに分かれ、callerフィールドで「どのプログラムがこの関数呼び出しを発行したか」を追跡する。承認が必要な操作は、allowed_callersの設定に関わらずアプリケーション側で改めてチェックすることを公式ガイドは推奨している- OpenAI自身が「効果はタスクとツールの応答内容に依存する」と明記しており、直接のツール呼び出しをベースラインにまず比較してから使うべき、と釘を刺している。無条件に効率化を約束する機能ではない
The SDK now supports Programmatic Tool Calling, allowing supported models to generate hosted JavaScript that coordinates eligible tools and reduces their intermediate results.
(SDKはProgrammatic Tool Callingに対応した。対応モデルが、対象ツールを協調させ中間結果を削減するホスト型JavaScriptを生成できるようになる)
モデルが書いたコードが動く場所
OpenAIの公式ガイドによると、この機能の実体は「モデルがResponses APIのリクエスト内でツールを協調させるJavaScriptを書いて実行する」ことにある。
OpenAI runs each generated program in a fresh, isolated V8 runtime. The runtime supports JavaScript with top-level
await, but it does not provide Node.js, package installation, direct network access, a general-purpose filesystem, subprocess execution, a console, or persistent JavaScript state between program executions. Programs can interact with external systems only through tools enabled in the request and can emit output withtext(...)orimage(...).
(OpenAIは生成された各プログラムを、まっさらな隔離されたV8ランタイム上で実行する。このランタイムはトップレベルawaitを含むJavaScriptに対応するが、Node.js・パッケージのインストール・直接のネットワークアクセス・汎用ファイルシステム・サブプロセス実行・コンソール・プログラム実行間で持続するJavaScriptの状態は提供しない。プログラムは、リクエストで有効化されたツールを通じてのみ外部システムとやり取りでき、出力はtext(...)またはimage(...)で行える)
つまり、モデルが書くコードはサンドボックス化されたJS実行環境の中だけで完結し、外の世界とやり取りできるのはリクエストで許可されたツール呼び出しに限られる。
ツールごとに「誰が呼べるか」を指定する
このプログラムからツールを呼べるようにするには、ツール側の設定で許可する必要がある。
allowed_callersの値 |
挙動 |
|---|---|
省略、または["direct"] |
モデルが直接ツールを呼べる |
["programmatic"] |
programアイテム内のコードからのみ呼べる |
["direct", "programmatic"] |
モデルが直接、またはプログラムから呼べる |
対応するツール種別は、functionとcustom、mcp、apply_patch、ローカル・ホスト型のshell、code_interpreterと、公式ガイドに列挙されている。MCPツールについては、ツールのrequire_approvalポリシーによってプログラムの実行中に承認待ちで一時停止させることもできるという。
いつ使うべきかの判断基準
公式ガイドは「いつProgrammatic Tool Callingを使うべきか」についても、直接的なツール呼び出しとの使い分け表を示している。抜粋するとこうだ。
| Several results that code can filter, join, rank, remove duplicates from, aggregate, or validate | Use Programmatic Tool Calling when the program can return a smaller structured result. | | Adaptive search or semantic evaluation | Use direct tool calling when each result should influence the model's next decision. | | Writes or approval-sensitive actions | Use direct tool calling by default to preserve a clear authorization boundary. |
(コードでフィルタ・結合・ランキング・重複排除・集計・検証できる複数の結果 → プログラムがより小さな構造化結果を返せる場合はProgrammatic Tool Callingを使う。適応的な検索や意味的評価 → 各結果がモデルの次の判断に影響すべき場合は直接ツール呼び出しを使う。書き込みや承認が必要な操作 → 明確な認可境界を保つため、デフォルトでは直接ツール呼び出しを使う)
要するに、「複数の結果をまとめて絞り込みたいだけ」の作業はコードに任せ、「1回ごとにモデルの判断が必要」な作業や「承認が必要な操作」は直接のツール呼び出しのままにする、という線引きだ。
レスポンスの中身——programとfunction_callとprogram_outputの3点セット
公式ガイドの「Understand program response items」節を確認すると、Programmatic Tool Callingが使われた場合のresponse.output配列には、次の3種類のアイテムが個別に並ぶことが分かる。
programアイテム:生成されたJavaScriptのコード本体、call_id、そしてプログラムを再開・再生するための不透明なfingerprintを含むfunction_callアイテム:プログラムが発行した関数呼び出し。自分自身のcall_idを持ち、caller.caller_idがプログラム側のcall_idと一致することで、どのプログラムが発行した呼び出しかを追跡できるprogram_outputアイテム:プログラムの最終結果とステータス(completedまたはincomplete)
ガイドが示す例では、get_inventoryとget_demandという2つのツールを在庫プランニング用のプログラムが呼び出す様子が、次のようなJSONで表現されている(要約)。
{
"type": "program",
"call_id": "call_prog_123",
"code": "const [stock, demand] = await Promise.all([tools.get_inventory({sku:'sku_123'}), tools.get_demand({sku:'sku_123'})]); text(JSON.stringify({...}));",
"fingerprint": "opaque_replay_state"
}
アプリケーション側が果たす役割は、生成されたJavaScript自体を実行することではなく(それはOpenAI側のホスト型ランタイムが行う)、プログラムから発行されたfunction_call(クライアント側が持つ関数)を実行し、その結果をfunction_call_outputとして返すことだ。その際、callerフィールドは変更せずそのままコピーして返す必要があり、これによりサービス側がどのプログラムを再開すべきか判断する、とガイドは説明している。実際に公式SDKのサンプルコード(examples/docs/tools/programmaticToolCalling.ts)でも、get_inventory・get_demandという2つのツールにallowedCallers: ['programmatic']とoutputSchemaを指定し、programmaticToolCallingTool()をエージェントのツール一覧に加えるだけの短い実装で、このガイドと同じ在庫プランニング例が再現されている。
ルーティングの指示文はどう書くべきか——公式テンプレート
直接呼び出しとProgrammatic Tool Callingの両方を1つのエージェントで使えるようにする場合、公式ガイドは「efficiently使え」のような曖昧な指示ではなく、どの段階でどちらを使うかを明示するプロンプトテンプレートを示している。
<tool_orchestration>
Use Programmatic Tool Calling for [bounded stage] using only [eligible tools].
Run independent calls concurrently when safe.
Process and reduce the intermediate results, then emit exactly [program result shape].
Stop when [condition] is met. Retry transient failures at most [R] times.
Do not repeat completed calls or perform side-effecting actions.
Use direct tool calls for [semantic judgment, approval, or final validation].
</tool_orchestration>
境界を明示すること(「どのツールに限定するか」「いつ止めるか」「何回までリトライするか」)が重要だとガイドは強調している。
ツール設計時の注意——承認はallowed_callersだけに頼らない
ガイドの「Design tools for programs」節には、プログラムから呼ばれることを想定したツール設計のチェックリストがある。特に目を引くのは次の一文だ。
"Require application-level approval before high-impact actions, regardless of the caller."
(訳:影響の大きい操作の前には、呼び出し元がどちらであっても、アプリケーション側での承認を必須にすること)
つまり、「書き込みや承認が必要な操作は直接ツール呼び出しに留める」という設計指針(本記事の前半で紹介した使い分け表)はあくまで推奨であって、それだけに頼らず、影響の大きい操作についてはアプリケーション側でも改めて承認チェックを行うべきだ、という二重の防御を公式ガイド自身が求めている。ほかにも「関数呼び出しは可能な限り冪等にする(リトライや再生が副作用を繰り返さないように)」「たとえホスト型プログラムからの呼び出しでも、引数と権限を自分のアプリケーション側でチェックする」といった項目が挙げられていた。
Zero Data Retentionとの関係
公式ガイドには、データ保持ポリシーとの関係についても言及がある。
Programmatic Tool Calling supports Zero Data Retention (ZDR) workflows without requiring a persistent code-execution container. ZDR must be enabled for the organization or project; setting
store: falseenables stateless continuation but does not enable ZDR by itself.
(Programmatic Tool Callingは、永続的なコード実行コンテナを必要とせずにZero Data Retention(ZDR)ワークフローに対応する。ZDRは組織またはプロジェクト単位で有効化する必要があり、store: falseを設定するとステートレスな継続は可能になるが、それだけではZDRは有効にならない)
OpenAI自身が「効果は保証しない、測って比較しろ」と釘を刺している
ガイド末尾の「Evaluate Programmatic Tool Calling」節は、この機能を導入する前に読むべき注意書きだ。
"Programmatic Tool Calling can reduce the amount of intermediate tool output added to model context, but the effect depends on the task and tool responses. Start with direct tool calling as a baseline, then compare both approaches on representative tasks."
(訳:Programmatic Tool Callingは、モデルのコンテキストに追加される中間的なツール出力の量を削減しうるが、その効果はタスクとツールの応答内容に依存する。まずは直接のツール呼び出しをベースラインとして始め、代表的なタスクで両方のアプローチを比較すること)
「削減できる」ではなく「削減しうる(can reduce)」という書き方であり、効果を保証する機能としては説明されていない。測定すべき項目として、ガイドは「最終回答の正確性・完全性・根拠の網羅性」「入力・合計トークン数、レイテンシ、コスト」「モデルのターン数・ツール呼び出し回数・リトライ回数」「副作用や承認要件に関する安全性の結果」「意図したワークフロー段階に沿ったルートが実際に使われたか」の5点を挙げている。効率化を謳う新機能ほど「使えば速くなる」と受け取られがちだが、公式ガイド自身が「タスクとツールの応答次第」「比較して初めて分かる」という留保を明記している点は、紹介にあたって省略すべきではない部分だ。
同じリリースに入っていたもう1つの機能
同じv0.14.0では、VercelサンドボックスにMountpoint for Amazon S3経由でS3バケットをマウントするVercelCloudBucketMountStrategyも追加された。ただしこちらはリリースノートに1文の説明しかなく、本記事では深掘りせずProgrammatic Tool Callingにしぼった。
実際にツール群を協調させるコードを走らせたわけではない
本記事はopenai-agents-js v0.14.0のリリースノート、OpenAI公式のProgrammatic Tool Callingガイド全文、公式SDKのサンプルコードを情報源としている。Anthropic有料APIおよびOpenAI有料APIへの実際の課金を伴う呼び出しは本セッションの方針上行っていないため、この記事を書いている自分の手元で実際にモデルにJavaScriptを生成させ、複数ツールを協調実行させて中間結果がどの程度圧縮されるかを検証してはいない。ガイド自身が「効果はタスク次第で測定が必要」と述べている通り、この記事でも「どの程度速くなるか・トークンが減るか」という定量的な効果は紹介できておらず、公式の主張をそのまま伝えるにとどまる。ツール検索(Tool search)と組み合わせた際の挙動についても、公式ガイドの記述をそのまま転記するにとどめ、実地での動作確認はしていない。
関連記事: AIエージェントとは / MCP(Model Context Protocol)とは / Claude・GPT・Gemini API料金の読み方
感想・指摘はコメント欄へ。
出典・参照資料
AIニュースの解説を動画でも
YouTubeでは注目ニュースの背景を解説し、Xでは新着記事をお知らせしています。
コメント
まだコメントはありません。最初のコメントを書いてみませんか?
AIについて聞きたいことはありますか?
質問箱で無料で受け付けています。回答は公開され、他の方の参考にもなります。
質問箱を見る →新しい記事をメールで受け取る
AIの新しい発表を、出典付きで整理して届けます。