エージェント設計は依然として難しい (Agent Design Is Still Hard)

以下はhttps://lucumr.pocoo.org/2025/11/21/agents-are-hard/の翻訳です。

学んだ新しいことについて書くのに良い時期だと感じました。ほとんどがエージェント構築についてですが、エージェント的なコーディングツールの使用についても少し触れます。

TL;DR: エージェントの構築はまだ煩雑です。実際のツール使用に直面すると、SDKの抽象化は破綻します。キャッシングは自分で管理した方がうまくいきますが、モデルによって異なります。強化学習は予想以上に大きな役割を果たし、失敗がループを脱線させないためには厳密な隔離が必要です。ファイルシステムライクな層を介した共有状態は、重要な構成要素です。出力ツールは驚くほど扱いにくく、モデルの選択は依然としてタスクに依存します。

どのエージェントSDKをターゲットにするか?

独自のエージェントを構築する際、OpenAI SDKやAnthropic SDKといった基盤となるSDKをターゲットにするか、Vercel AI SDKやPydanticなどのより高レベルの抽象化を使用するかを選択できます。以前、私たちはVercel AI SDKを採用するが、プロバイダーの抽象化のみを使用し、エージェントループの駆動は基本的に自分たちで行うという選択をしました。現時点では、この選択を再度行うことはないでしょう。Vercel AI SDKに全く問題があるわけではありませんが、エージェントを構築しようとすると、私たちが当初予期していなかった2つのことが起こります。

1つ目は、モデル間の違いが非常に大きいため、独自のエージェント抽象化を構築する必要があるということです。私たちは、これらのSDKのソリューションで、エージェントにとって適切な抽象化を構築するものを見つけていません。これは、基本的なエージェント設計が単なるループであるにもかかわらず、提供するツールに基づいて微妙な違いがあるためだと考えています。これらの違いが、適切な抽象化(キャッシュ制御、強化学習に対する異なる要件、ツールプロンプト、プロバイダー側のツールなど)を見つける難易度に影響します。適切な抽象化がまだ明確でないため、専用プラットフォームの元のSDKを使用することで、完全に制御下に置くことができます。これらの高レベルSDKの一部では、既存の抽象化の上に構築する必要があり、それが最終的に本当に欲しいものではない可能性があります。

また、プロバイダー側のツールを扱う際、Vercel SDKでの作業が非常に難しいこともわかりました。メッセージ形式を統合しようとする試みは、完全には機能しません。例えば、Anthropicのウェブ検索ツールは、Vercel SDKを使用するとメッセージ履歴をルーチン的に破壊しますが、私たちはまだその原因を完全に解明していません。また、Anthropicの場合、Vercelではなく彼らのSDKを直接ターゲットにする方が、キャッシュ管理がはるかに簡単です。間違いを犯したときのエラーメッセージもずっと明確です。

これは変わるかもしれませんが、現時点では、エージェントを構築する際に抽象化を使用しないでしょう。少なくとも、状況がもう少し落ち着くまでは。私たちにとって、そのメリットはまだコストを上回っていません。

他の誰かが解決策を見つけているかもしれません。もしこれを読んでいて、私が間違っていると思う方がいれば、ぜひメールをください。学びたいと思っています。

キャッシングの教訓

プラットフォームによって、キャッシングへのアプローチは大きく異なります。これについてはすでに多く語られていますが、Anthropicはキャッシングに対して料金を支払わせます。明示的にキャッシュポイントを管理する必要があり、これがエージェントエンジニアリングのレベルで、私たちがそれとやり取りする方法を大きく変えます。当初、私はこの手動管理をかなり愚かだと感じていました。なぜプラットフォームがこれをやってくれないのか?と。しかし、今では完全に考えを変え、明示的なキャッシュ管理を断然好むようになりました。これにより、コストとキャッシュの利用率がはるかに予測しやすくなります。

明示的なキャッシングにより、他の方法でははるかに難しい特定のことができるようになります。たとえば、会話を分割し、同時に2つの異なる方向に実行させることができます。また、コンテキスト編集を行う機会もあります。最適な戦略は不明ですが、明らかにずっと多くの制御が可能になり、私はその制御を持っていることが非常に気に入っています。また、基盤となるエージェントのコストを理解することもはるかに容易になります。他のプラットフォームでは当たり外れがあることがわかりましたが、これだとキャッシュがどれだけうまく利用されるかについて、より多くのことを想定できます。

Anthropicを使用したエージェントでのキャッシング方法は非常に簡単です。1つのキャッシュポイントはシステムプロンプトの後に置かれます。2つのキャッシュポイントは会話の開始時に配置され、最後のものは会話の末尾とともに上に移動します。そして、途中で行うことができるいくつかの最適化があります。

システムプロンプトとツール選択はほとんど静的である必要があるため、現在の時刻などの情報を提供するために、動的なメッセージを後でフィードします。そうしないと、キャッシュが無効になってしまいます。また、ループ中に強化学習をより活用しています。

エージェントループにおける強化学習

エージェントがツールを実行するたびに、ツールが生成するデータだけでなく、より多くの情報をループにフィードバックする機会があります。たとえば、全体的な目的や個々のタスクのステータスをエージェントに思い出させることができます。また、ツールが失敗した場合に、そのツール呼び出しがどのように成功するかについてのヒントを提供することもできます。強化学習のもう一つの用途は、バックグラウンドで発生した状態変化についてシステムに通知することです。並列処理を使用するエージェントの場合、その状態が変化し、タスクの完了に関連する場合、ツール呼び出しごとに情報を注入できます。

エージェントが自己強化するだけで十分な場合もあります。たとえば、Claude Codeでは、「todo write」ツールは自己強化ツールです。エージェントが実行すべきだと考えるタスクのリストを受け取り、入ってきたものをそのまま出力するだけです。これは基本的に単なるエコーツールであり、それ以外のことは何もしていません。しかし、これだけで、コンテキストの最初にタスクとサブタスクが与えられただけで、その間にあまりにも多くのことが起こってしまった場合よりも、エージェントをより良く前進させることができます。

また、実行中にエージェントにとって問題となる方法で環境が変化した場合に、システムに通知するために強化学習を使用します。たとえば、エージェントが失敗し、特定のステップから再試行するものの、復旧が壊れたデータに基づいて行われる場合、数ステップ戻って以前のステップをやり直すことを勧めるメッセージを注入します。

失敗の隔離

コード実行中に多くの失敗が予想される場合、それらの失敗をコンテキストから隠す機会があります。これには2つの方法があります。1つは、イテレーションが必要な可能性のあるタスクを個別に実行することです。それらをサブエージェントで成功するまで実行し、成功と、おそらくうまくいかなかったアプローチの簡単な要約のみを報告します。うまくいかなかったことをエージェントがサブタスクで学ぶことは、次のタスクにその情報をフィードして、それらの失敗から遠ざかるように導くのに役立ちます。

2つ目のオプションは、すべてのエージェントや基盤モデルには存在するわけではありませんが、Anthropicではコンテキスト編集を行うことができます。これまでのところ、コンテキスト編集で多くの成功を収めていませんが、さらに探求したい興味深いものだと信じています。また、それを使って成功している人がいれば、ぜひ知りたいと思っています。コンテキスト編集が興味深いのは、イテレーションループのさらに下流のためにトークンを保持できるはずだという点です。ループの成功完了にはつながらなかったが、実行中の特定の試みにのみ悪影響を与えた特定の失敗をコンテキストから取り出すことができます。しかし、先に述べた点と同様に、エージェントにとって何がうまくいかなかったかを理解することも有用ですが、おそらくすべての失敗の完全な状態と完全な出力を必要とするわけではありません。

残念ながら、コンテキスト編集は自動的にキャッシュを無効にします。これを回避する方法は本当にありません。したがって、それを行うことのトレードオフが、キャッシュを破棄する追加のコストをいつ相殺するのかが不明確になる可能性があります。

サブエージェント / サブ推論

このブログですでに何度か述べたように、私たちのエージェントのほとんどはコード実行とコード生成に基づいています。これには、エージェントがデータを保存するための共通の場所が本当に必要です。私たちの選択はファイルシステム、この場合は仮想ファイルシステムですが、これにアクセスするには異なるツールが必要です。これは、サブエージェントやサブ推論のようなものがある場合に特に重要です。

行き止まりのないエージェントを構築するように努めるべきです。行き止まりとは、構築したサブツール内でしかタスクの実行を継続できない場所です。たとえば、画像を生成するツールを構築したが、その画像を別のツールに一度だけフィードバックできるだけだとします。これは問題です。なぜなら、その画像をコード実行ツールを使用してzipアーカイブに入れたいと思うかもしれないからです。したがって、画像生成ツールが、コード実行ツールが読み取ることができるのと同じ場所に画像を書き込むことができるシステムが必要です。本質的に、それはファイルシステムです。

もちろん、逆のことも可能である必要があります。コード実行ツールを使用してzipアーカイブを解凍し、その後推論に戻ってすべての画像を記述し、次のステップでコード実行に戻る、といった具合です。ファイルシステムは、私たちがそのために使用するメカニズムです。ただし、仮想ファイルシステム上のファイルパスを受け取って機能するようにツールを構築する必要があります。

つまり、基本的にExecuteCodeツールは、RunInferenceツールと同じファイルシステムにアクセスでき、RunInferenceツールは同じ仮想ファイルシステム上のファイルへのパスを受け取ることができる、ということです。

出力ツールの使用

私たちがエージェントをどのように構成したかについての興味深い点の1つは、それがチャットセッションを表していないことです。最終的にはユーザーまたは外部の世界に何かを伝えますが、その間に送信するメッセージは通常、すべては明らかにされません。問題は、そのメッセージをどのように作成するかです。私たちには1つのツールがあり、それが出力ツールです。エージェントは、人間と通信するためにそれを明示的に使用します。次に、いつそのツールを使用するかを指示するためにプロンプトを使用します。私たちの場合、出力ツールは電子メールを送信します。

しかし、それがいくつかの別の課題を引き起こすことが判明しました。1つは、メインのエージェントループのテキスト出力をユーザーと話すメカニズムとして使用するのと比較して、その出力ツールの文言とトーンを誘導するのが驚くほど難しいということです。なぜそうなのかは言えませんが、おそらくこれらのモデルがどのようにトレーニングされているかに関連しているのだと思います。

うまくいかなかった試みの1つは、出力ツールにGemini 2.5 Flashのような別のクイックLLMを実行させ、トーンを私たちの好みに調整させることでした。しかし、これはレイテンシーを増加させ、実際に出力の品質を低下させます。部分的には、モデルが物事を正しく表現できず、サブツールに十分なコンテキストがないためだと思います。メインのエージェント的なコンテキストのより多くのスライスをサブツールに提供すると、コストが高くなり、問題も完全に解決しませんでした。また、最終的な出力に、望んでいなかった情報、たとえば最終結果につながったステップなどが含まれてしまうこともあります。

出力ツールのもう1つの問題は、ツールを呼び出さないことがあるということです。私たちがこれを強制する方法の1つは、出力ツールが呼び出されたかどうかを記憶することです。出力ツールなしでループが終了した場合、出力ツールを使用するように促す強化学習メッセージを注入します。

モデルの選択

全体として、モデルの選択はこれまで劇的に変化していません。HaikuとSonnetは依然として利用可能な最高のツールコーラーであり、エージェントループで優れた選択肢となります。また、RLがどのようなものかについても多少透過的です。他の明白な選択肢はGeminiモデルです。これまでのところ、メインループでGPTファミリーのモデルで大きな成功を収めていません。

個々のサブツール(一部は推論も必要とするかもしれません)については、大規模なドキュメントを要約したり、PDFなどを操作したりする必要がある場合は、現在の選択肢はGemini 2.5です。これは、画像から情報を抽出するのにもかなり良いモデルです。特に、Sonnetファミリーのモデルはセーフティフィルターに引っかかりやすく、それが煩わしい場合があるためです。

また、トークンコストだけではエージェントのコストを定義できないという、非常に明白な認識もあるでしょう。より優れたツールコーラーは、より少ないトークンでジョブを完了します。今日、Sonnetよりも安価なモデルもありますが、ループ内では必ずしも安価ではありません。

しかし、全体的に見て、ここ数週間でそれほど多くの変化はありません。

テストと評価

ここでは、テストと評価が最も難しい問題だと感じています。これは全く驚くべきことではありませんが、エージェント的な性質がそれをさらに難しくしています。プロンプトとは異なり、フィードする必要があるものが多すぎるため、外部システムで評価を行うだけでは済みません。つまり、オブザーバビリティデータまたは実際のテスト実行のインストゥルメンテーションに基づいて評価を行う必要があります。これまでのところ、私たちが試したソリューションのどれも、ここで適切なアプローチを見つけたとは確信させてくれませんでした。残念ながら、現時点では本当に満足のいくものを見つけていないと報告しなければなりません。これはエージェント構築のますます苛立たしい側面になっているため、解決策を見つけられることを願っています。

コーディングエージェントの更新

コーディングエージェントでの経験については、実際にはそれほど多くの変化はありません。主な新しい進展は、Ampをより試用していることです。なぜ気になるのかというと、それが客観的に私が使用しているものよりも優れたエージェントだからではなく、彼らが投稿しているものから、彼らがエージェントについて考えている方法が本当に気に入っているからです。Oracleのような異なるサブエージェントとメインループとの相互作用は美しく行われており、今日、他の多くのハーネスはこれを行っていません。また、さまざまなエージェント設計がどのように機能するかを検証するための良い方法でもあります。Ampは、Claude Codeと同様に、自分たちのツールも使用する人々によって構築された製品のように本当に感じられます。業界の他のすべてのエージェントがそうだと感じているわけではありません。

読んだり見つけたりした簡単なこと

これは、共有する価値があるかもしれないと感じるランダムな情報の詰め合わせです。

  • MCPが全く必要ないとしたら?: Marioは、多くのMCPサーバーがオーバーエンジニアリングされており、多くのコンテキストを消費する大きなツールセットを含んでいると主張しています。彼は、ブラウザエージェントのユースケースに対して、Bash経由で実行されるシンプルなCLIツール(例:起動、ナビゲート、JS評価、スクリーンショット)に依存することで、トークン使用量を少なくし、ワークフローを柔軟に保つミニマリストなアプローチを提案しています。私はそれからClaude/Ampスキルを構築しました。
  • 「小さな」オープンソースの運命: 著者は、プラットフォームの組み込みAPIやAIツールがオンデマンドでシンプルなユーティリティを生成できるようになったため、小さくて単一目的のオープンソースライブラリの時代は終焉を迎えつつあると主張しています。本当にありがたいことです。
  • Tmuxは愛だ。これに伴う記事はありませんが、TLDRはTmuxは素晴らしいということです。エージェントが操作すべき対話型システムに少しでも似たものがある場合は、Tmuxスキルを与えてみるべきです。
  • LLM APIは同期の問題である。これは、この投稿には長すぎる別の認識だったので、別の記事を書きました。

💡 エージェント開発の現状:まだ難しいけれど、光明も見えてきた

この記事は、AIエージェント(特定の目標を達成するためにツールを使って自律的に動作するプログラム)を開発するエンジニアが、最近の経験から学んだ教訓をまとめたものです。

1. 🛠️ 既存のツールキットはまだ不十分

  • 高機能なライブラリに頼るのは危険: OpenAIやAnthropicのような提供元が作った基本的なツールキット(SDK)を使う方が、Vercel AI SDKのような複数のプラットフォームを統合した高レベルのツールキットを使うよりも、今のところは良い結果が得られます。
  • なぜなら、高レベルのツールキットは、実際にエージェントが複雑な道具(ツール)を使い始めると、プラットフォームごとの細かい違いを吸収しきれず、かえって問題を起こすからです。

2. 💰 キャッシング(一時保存)は手動が良い

  • AIとのやり取りは毎回コストがかかるため、同じ内容を繰り返す部分を一時的に保存(キャッシュ)して再利用します。
  • Anthropic(Claudeの提供元)のように、どこをキャッシュするかをエンジニアが手動で決める方式の方が、AI側の自動機能に任せるよりも、コストの予測がしやすく、エージェントの動作をより柔軟に制御できるため、好ましいということが分かりました。

3. 🎯 強化学習(フィードバック)で導く

  • エージェントがツールを使うたびに、単にツールの結果を返すだけでなく、「目標を忘れないように」「タスクの進捗はこうだ」といった追加のヒントや状況変化をフィードバック(強化学習)として送ることが非常に重要です。
  • このフィードバックが、エージェントを正しい方向に進ませ、途中で迷子になるのを防ぎます。

4. 🧱 エージェント間の情報共有

  • エージェントがコード実行や画像生成といった複数のタスクを行うには、生成したファイルなどを共通の場所(仮想ファイルシステム)に保存し、すべてのツールがアクセスできるようにする必要があります。
  • これにより、例えば「画像を生成するツール」が作ったファイルを、「それを圧縮するコード実行ツール」が使えるようになり、タスクの幅が広がります。

5. 🗣️ ユーザーへの最終報告

  • エージェントがユーザーにメールなどで最終的な報告をする際、単にメインのAIに報告文を書かせるのではなく、「出力ツール」という専用のツールを使わせています。
  • しかし、このツールを使っても、報告のトーンや言葉遣いを意図通りに調整するのが難しいという意外な課題が見つかりました。別のAIを使ってトーン調整を試みても、品質が落ちてレイテンシーが増加するだけでうまくいきませんでした。

6. 🏆 モデル選びのポイント

  • メインのエージェントループでは、Claude 3 Haiku / Sonnetが最高のツールコーラー(道具を上手に使えるAI)であり、依然として最高の選択肢です。
  • コストが安くても、ツールを使う能力が低いモデルは、結果的に何度も試行錯誤してトークンを多く消費するため、トータルコストで高くなることがあります。

7. 🧪 テストと評価が最大の難関

  • エージェントのテスト(エバル)は、従来のプログラムよりもはるかに難しく、現在、誰もが納得できる良い解決策が見つかっていません。これは、エージェントの複雑で自律的な性質に起因しています。

免責事項

記事は、一般的な情報提供のみを目的としてのみ作成したものであり、投資家に対する有価証券の売買の推奨や勧誘を目的としたものではありません。また、記事は信頼できると判断した資料およびデータ等により作成しておりますが、その正確性および完全性について保証するものではありません。また、将来の投資成果や市場環境も保証されません。最終的な投資決定は、投資家ご自身の判断でなされますようお願いします。

Ads Blocker Image Powered by Code Help Pro

Ads Blocker Detected!!!

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

タイトルとURLをコピーしました