世界を動かす技術を、日本語で。

LLMの関数呼び出しはスケールしない;コードオーケストレーションはよりシンプルで効果的です

概要

  • LLMにツールコールの全出力を渡すのはコスト高・低速という課題を指摘
  • 出力スキーマが普及すれば構造化データ処理が容易になると提案
  • コードによるツールコール処理は効率的かつスケーラブルであることを強調
  • MCPサーバの現実的な課題と、コード実行環境の設計上の困難に言及
  • 今後の展望として「AIランタイム」新カテゴリへの期待を述べる

LLMによるツールコール出力処理の限界とコード実行アプローチ

現在のツールコール出力処理の課題

  • LLMに ツールコールの全出力 (例:巨大JSON)をそのまま渡すと コスト高・処理遅延 が発生することを確認
  • MCPサーバ(例:Linear, Intercom)は API類似の大きなJSON を返すが、 事前定義スキーマがない ため、LLMによる解釈に頼らざるを得ない状況を確認
  • 例としてLinearのMCPで 50件のIssue出力 を取得した場合、 約70,000文字・25,000トークン と大規模データとなり非効率
  • JSONには 意味的価値の少ないidフィールド等 が多く含まれ、LLMへの入力・出力トークン数が膨大になることを確認
  • LLMが 全データを出力で再現 しようとすると コスト増・速度低下・データ欠落リスク が発生することを指摘
  • 出力データに ノイズ情報 (再現手順、エラー、ユーザプロンプト等)が多く、LLMが 正確に再現できない・指示から逸脱する 危険性も指摘

データ処理とオーケストレーションの分離

  • オーケストレーション (処理手順管理)と データ処理 を同一チャットスレッドで混在させることが 根本的な問題 と分析
  • マルチエージェント方式(別スレッドでデータ処理専任エージェントを立てる)は 調整次第で効果的 だが、 構造化データ前提なら冗長 と指摘
  • MCPサーバが 既にJSON構造で返している場合、LLMに再現させるより 直接データ操作(例:ソート処理) を行う方が 効率的・スケーラブル と提案

コード実行によるデータ処理の優位性

  • コード実行(例:Code Act, Smol Agents)を AIによるデータ処理の基本手法 とすることで スケーラブルなAI活用 が可能と主張
  • 変数をメモリとして活用 し、外部メモリ不要で 値の保存・参照・引数渡し が可能となることを強調
  • 型情報が明確な言語を使えば スキーマ活用 も容易であることを確認
  • ツールチェイニング (複数関数の連携呼び出し)により、 並列処理・出力の再利用 が実現できることを説明
  • LLMは データの再現出力を担当せず処理の完全性保証 が得られることを評価
  • コードでの大規模データ処理は ループ・NumPy/pandas等のライブラリ活用 で自然にスケール可能であることを強調
  • コード内から 他のLLM呼び出し (LLM-inception)も可能で、 非構造データ処理 にも対応できる点を指摘

MCP仕様の進化と今後の可能性

  • MCP仕様は既に 入力スキーマ を定義しており、 出力スキーマも導入 されたことを紹介
  • 出力スキーマの普及により、 大規模データセット活用 (例:カスタムダッシュボード、週次レポート、自律エージェントによる監視・介入)が期待できると提案

コード実行環境の課題とAIランタイムの展望

  • コード実行環境は セキュリティ重視のサンドボックス での運用が必須となることを説明
  • MCPやツール・ユーザデータへのアクセスには、 APIキー管理・ツール公開設計 が重要であると指摘
  • 設計例として、 限定APIアクセス環境APIドキュメント提供 でモデルに秘密情報を渡さずに操作可能としたことを紹介
  • 多くの実行環境は ステートフル (例:Jupyterカーネル常駐)だが、 管理困難・コスト高 となるため、 ステートレスかつ永続的な実行環境 が求められると提案
  • こうした要件から「 AIランタイム」という新しい実行環境カテゴリが生まれつつあると展望
  • コード実行アプローチの詳細はまだ初期段階であり、 同様の課題に取り組む方からのフィードバック を歓迎すると表明
  • 実際の取り組み例として Lutra の利用を案内

提案・確認

  • MCPツールコールの出力処理は 構造化データ+コード実行 へ移行することが 効率化・スケーラビリティ向上 の鍵
  • AIランタイム 設計では セキュリティ・永続性・API管理 を重視すること
  • 出力スキーマの普及 を待ちつつ、 コード中心のAIオーケストレーション を検討すること

Hackerたちの意見

最適な解決策は極端なものではなく、ハイブリッドだと思う。つまり、できるだけ決定論的なアプローチを使いつつ、残りの複雑な部分を扱うためにLLMを活用するってこと。

そうだね、特に面白い視点は、LLMを使って決定論的なアプローチ(コード)を生成することだと思う。それで、もしそのコードがうまくいけば、将来のために保存しておいて、今後は決定論的に使えるようになる。

同意するよ。ワークフローではできるだけLLMを使わない方がいいよね。

Shopifyの私のチームが最近Roastをオープンソースにしたよ。[1] これを使うと、非決定論的なLLMのジョブをオーケストレーションされたワークフローに組み込むことができる。何百万行ものコードを持つコードベースで作業を自動化する際には欠かせないね。[1] https://github.com/shopify/roast

Rubyが存在し続けて、ちゃんと機能しているのを見るのは嬉しいね…「AI」の時代でも。

わあ、Roastは素晴らしいね。ずっと悩んでたことに名前や制約をつけて設計したんだね。決定論と非決定論をうまく融合させてるのがすごく好きだよ。(READMEを何回か(さっと)読んでも、LLMが必要に応じて複数のツール呼び出しを調整したり、どのツールをどの順番で呼ぶか決めたりできるかどうかが明確じゃなかったんだ。リファクタリングを指示するときにはできるみたいだけど、「改善してからテストを実行。完了するまで繰り返す」ってタスクに適してるかは分からなかった。)

いいね!俺、Claude Code Research Previewを壊しちゃったし、ChatGPT 4.5 Pro Deep Researchもクラッシュさせたよ。証拠もあるからね :)、だから使えるツールを探してるんだ。

これ、めっちゃクールだね!Shopifyの内部でこういうワークフローがどう使われてるのか気になるな。何か例を共有してもらえる?

そもそも、構造化データをソートするのにLLMを使う理由がちょっとわからないな?

目標はもっと複雑なデータ処理をすることで、ダッシュボードを作ったり、どのチケットが停滞しているかをエージェント的に把握したり、やったことの四半期レビューをしたりすることなんだ。ソートは大きなタスクの中の小さな作業だけど、問題をよりわかりやすく示すことができるといいな。

問題は関数呼び出しではなく、ここでMCPがどのように設計されているか、そしてあなたが使っているかだね。ほとんどのMCPはAPIを複製していて、データの塊を返している。1. これはJSON形式でのフォーマットに多くの入力コンテキストを使っていて、すでにJSONの中にあるJSONをエスケープしている。2. これには関係のない情報がたくさん含まれていて、それに対して同じことが言える。だから、問題はMCPツールにある。データをできるだけフラットにすべきで、JSONエンコーディングを通って戻るときに必要なフィールドを削除するべきだ。だから、ここでのMCP SAASは主にAPIゲートウェイなんだ。それがこのノイズを生んでいる! そして、何よりもMCPを最適化していないんだ。

  1. これ、JSONの形式で大量の入力コンテキストを使っていて、すでにJSONの中にJSONをエスケープしてるよね。複雑なJSONスキーマを尊重しないのはモデルの問題じゃない?

これはGraphQLのために設計されたものだよ。本当に必要なフィールドだけを選べる。OSSゲートウェイを作って、GraphQLクエリのコレクションをMCPサーバーに変換して、これをシンプルにしてるんだ:https://wundergraph.com/mcp-gateway

これには別の解決策があるかもしれないと思うんだ。つまり、LLMがMCPを関数として呼び出す有効なコードを書くってこと。Pythonスクリプトみたいに、各MCPが関数にマッピングされる感じ。簡単な例を挙げると、def process(param1, param2): my_data = mcp_get_data(param1) sorted_data = mcp_sort(my_data, by=param2) return sorted_data

そうだね!これが実際にどう機能するか見たいなら、https://lutra.ai をチェックしてみて。そこで似たようなパターンを使ってるよ。課題は、コードの実行時間をうまく調整することだね。

ごめん、ここ1年くらい業界から離れてたんだけど、今って本当にこんなことやってるの?

いや、ほとんどの人はそうじゃないよ。でも、一部の人は実験してる。まだ革命的なものは見つかってないけど、確かに役立つアプリケーションはいくつかあるよ。

今の私の仕事は、AIを使ってAIエージェントデザイナーを開発することなんだけど、これがめちゃくちゃ多いんだ。正直、こんなの望んでなかったんだけど、気づいたらこうなってた。

出力を意識したLLM推論エンジンをぜひ見てみたいな。例えば、LLMが「今からツール呼び出しをするよ」って意味のトークンを出力したら、推論エンジン(例えば、llama.cpp)がその場で文法を変えて、次のトークンが利用可能なツールにだけ有効になるようにする、みたいな。あと、ユーザーのリストをLLMに渡して、何か基準でフィルタリングさせたら、文法が私のリストに存在するユーザーIDだけを出力するように変わるとか。実際にどれくらい役立つかは分からないけど、少なくともLLMがこれらのケースで幻覚を見ないようにはなるよね。

もちろん、幻覚を見ちゃうよ。適当な間違った値を選ぶだけだから。

2年間ずっと「十分に進化したエージェントはDSLと区別がつかない」って言ってるんだ。エージェントにアルゴリズムを内面化させるんじゃなくて、APIを教えて、それを使ってユーザースペースで実行できるアルゴリズムを設計させるべきだと思う。LLMがアルゴリズムを内面化する意味がある状況は、コストや精度の観点からもごくわずかだよ。エンジニアに頭の中で関数をステップ実行させる代わりに、ただ実行させるようなもんだね。

ASIへの道はLLMの能力を拡張することではなく、外部で自己改善アルゴリズムを抽出してコンパイルすることだという証拠だね。

2年前にこの文脈で「エージェント」という言葉が広く使われていた証拠を示してもらえる?

自分のeコマースビジネスのためにエージェントシステムを構築してるんだ。smolagentsを評価してみたけど、エレガントで魅力的な特性がたくさんある一方で、システムにかなりの複雑さを加えてしまう。いくつかのタスクには完璧だけど、スキーマなしでデータをソートや集計できる動的報告環境なんかは良いかもしれない。でも大抵のタスクにはオーバーキルだよ。GeminiとOpenAIはどちらもツールとしてPythonインタープリターを提供していて、コードエージェントの多くのユースケースをカバーできる。無限のメッセージをツール呼び出しやインタラクションのスタックに詰め込むのはスケーラブルじゃないし、これらのツールを使う良い方法じゃないのは確かだね。ほとんどのエージェントワークフローは短命だし、複雑さは構造と規律で管理される。これはソフトウェア開発でよく知られた問題で、古い教訓は新しいツールにも当てはまる。関数呼び出しはエージェントシステムでうまくスケールすることもあれば、どんなコードベースでもそうだけど、めちゃくちゃになることもある。個人的には、うまく機能するシステムを構築するのは、開発者の認知負荷を管理することと、制御フローやランタイムパフォーマンスを管理することの両方が重要だと思ってる。十分に機能するシンプルな解決策は、素晴らしいパフォーマンスの賢い解決策よりも通常は優れている。関数呼び出しを組み合わせるのがシンプルな解決策だよ。構造化データは昔ながらの方法でまだパースや変換ができる。構造が不明な場合でも、安価なモデルはパースが得意だしね。エージェントシステムでの複雑さの管理は、アプリケーション状態を慎重に管理する問題に分解できる。メッセージスタックは、モデルにアクティブなコンテキストを提供するために必要に応じて操作できる。制約のある環境でのメモリ管理だね。

MCPの戻り値の型がすごく基本的だからだよ。テキストか画像か、あとはプロトコルの中の他の型を忘れちゃったけど。それがあまり考えられてないんだ。新しい認証仕様で一つ作ってるけど、公式のコードやツールが本当に不足してる。今の時点でずっとシンプルでわかりやすくなってたはずなのに。代わりに3種類のサーバーがあって、そのうちの一つはもう廃止されてる(SSE)って、ほとんど笑えるよね。