💡

AI Agentフレームワークを使うべきなのか?

に公開

こちらはLayerX AI エージェントブログリレー41日目の記事です。

こんにちは、CEO室でAI Agent開発のPdMをしているKenta Watanabeです。

AI Agent開発に取り組んでいる方や自分用の効率化ツールを開発したりしてLLMで遊んでいる方は何かしらのAgentフレームワークを利用されている方が多いのではないかと思います。LayerXでもAI SDKなどのフレームワークが社内で利用されています。本日はAgent開発の試行錯誤を通して得られたAgentフレームワーク選びの参考になるような考え方を紹介できればと思います。

Agentフレームワーク戦国時代

ここ数年はAgentフレームワーク戦国時代と言えるほどたくさんのフレームワークやSDKが開発され利用されているのではないかと思います。各LLM ProviderはLLMを利用するためのHTTP EndpointとSDKを提供しているためこれらを直接利用することもできますが、複数のProviderのモデルを比較しながら利用したいときには、何かしらのフレームワークを試してみることが多いのではないでしょうか。

Langfuseの対応Frameworkの一部

Agentフレームワークの役割と利用メリット

Agentフレームワークにはまず最初に下記のような利用メリットがあると思います。

1. 複数LLM Providers対応

OpenAIやAnthropicといった各LLM Providerは類似はしているもののそれぞれ異なるInterfaceでAPI Endpoint/SDKを提供しています。そのため、複数のモデルを切り替えながら開発を行いたい場合、それぞれのSDKを利用しながらの開発だと効率悪くなりますが、Agentフレームワークではこれらの差異を吸収してくれる場合がほとんどです。TypeScriptではAI SDK、PythonではLangChainなどを、まず最初にこの目的で触り始める方が多いのではないかと思います。

2. 基本的な抽象化

Agentフレームワークでは「事前定義したPromptとTool定義を元にLLMを呼ぶ」と「LLMによって決定されたToolを実行する」をToolが呼ばれなくなるまで繰り返すという基本的な動作を実行することになります。これを今後Agent Loopと呼びます。

OpenAI Function calling
Agent Loopを実際にゼロから実装していると概念的には下記のようなとてもシンプルなコードで成り立っていることがわかります。

while 1
    response = llm.call(prompt, messages)
    if !response.toolCalls:
        return
    for toolCall in toolCalls:
        messages.append(toolCall.execute)

一方で実際にこれらを実装する場合は、たくさんの概念が存在し、コードが複雑になってしまうことに気づきます。LLMコールにはPromptや会話の履歴に加えて各種パラメータを渡すことになりますし、Toolの定義や実態、それらの実行やクライアント側との実行結果のやり取りなどがあります。多くのAgentフレームワークではこういった概念が利用しやすい形で抽象化されているため、フレームワークを使うことで開発しようとしているプロダクトの重要なロジックの開発に集中することができます。Pydantic AIなどシンプルな抽象化を行なっているものから、より複雑なマルチエージェントの連動を抽象化しているものなど、フレームワークにより形や狙いは異なります。

3. WorkflowやRAG

Agent Loopの実行より高度な概念の抽象化を行っているフレームワークも多く存在します。LLMを利用したサービス開発を行っていると、複数のLLM Callsを段階的に組み合わせて呼んだり外部からドキュメントを読み込んできてLLMに与えるといった作業が発生します。これらの開発を効率よく行うために例えばmastraではWorkflowの仕組みが備えられていたり、LlamaIndexではRAGに関連する機能が充実していたりします。

4. UIとの連携

Agentを用いた開発を行う場合、何らかの形でユーザからの指示を入力してもらい動作するアプリケーションを作ることが多くなります。その場合、LLMの出力をUIとして表示し、ユーザの入力をLLMへ与えるといったLLMとUIとの連携を行う必要があります。例えばChatGPTの画面のようなチャットインターフェースです。これらをゼロから実装しようとするとかなりの量のクライアント側での開発・LLMとの連携が必要になりますが、先述のAI SDKではAI SDK UIとしてUIとの連携を前提としてAgent側の抽象化が行われており、かなりシンプルなコードでUIとの連携を実現することができます。またAG-UIのようにLLM-UI間のコミュニケーションのプロトコルを整備するような取り組みも存在し、Agentフレームワークと組み合わせて利用することもできます。

AG-UI

5. Durable Engineとの連携

Agent開発を行っていると、長いLLM Callの待ちやHuman in the Loopにおけるユーザの入力待ち、またイベントをトリガーとしてAgentの実行など「時間」の概念に向き合う必要が出てきます。何かの待ちが発生していても継続的にAgent Loopがクラッシュせずに動き続けることができる仕組みが必要になります。通常のWebサーバで全てのAgentを実行しているとこれらの対応が難しくなるため、Temporalなどworkflowエンジンを利用する選択肢も生まれてきます。Pydantic AIではこのようなエンジンと連携してAgentを動かす仕組みを用意しており、workflowエンジンの存在を深く気にすることなくアプリケーションの開発を行うことも可能です。

6. 実際のAgent開発では確率的動作の安定化との戦いになる

さてここまで様々なAgentフレームワークやその役割を見てきました。フレームワークを使うことで、Agent開発を行う上で避けて通れない車輪部分の再発明を避けて、作りたいアプリケーションのコアのロジックの開発に集中することができます。一方で、実際にAgent開発を進めていくと「デモやちょっとした作業効率化には使えるんだけど、継続的に安定して使えるツールやお客様へ提供できるプロダクト」を作ることが非常に難しいことに気づきます。これはLLMが非常に強力な一方で、LLMに行わせるタスクを適切な粒度に絞ったり、LLMにやらせたい挙動やユーザの期待を深く理解してPromptを改善しなければ、意図した挙動を安定的に実行するのが難しいためです。

Context Engineeringには様々なテクニックが存在しますが、過去のContext Engineeringに関するブログでも紹介しているためご興味ある方はこちらも読んでいただければと思います。

フレームワークを使っていて困ること

Agentの動作を安定化させるために様々なアプローチのContext Engineeringを行うことになりますが、ここでAgentフレームワークを利用している場合問題になることがあります。Agentフレームワークは前述の通り基本的な抽象化やAgent Loopの枠組みを提供してくれていますが、事前に定義された枠組みの中での利用になってしまいます。そこで具体的に困るケースを見ていきたいと思います。

1. 溜まっていくメッセージの履歴を適切なタイミングで操作したい

LLMはStatelessなため、Agentとユーザの会話やToolの実行履歴はアプリケーション側で履歴を持っておき、次のLLM Callを履歴付きで実行することで過去の会話を考慮した出力を得ることができます。一方で、現在のLLMはContext制限の最大値に達しなくてもContextが膨らんでいくと性能低下が発生します(Context Rot等)。特に会話の中で何かを編集したりするなどで類似のデータが積み重なっていく場合などでは、1万token程度積み重なっただけでも明確な性能低下が見られると思います。

これに対応するために過去の不必要な会話履歴を削除・要約したりするアプローチがあります。会話履歴を編集する場合、Agent Loopので編集する場合特にどのフレームワークを利用していても対応可能だと思いますが、Agent Loopので行いたい場合(例:ユーザの入力に基づいて特定のTool Callが呼ばれたときにお掃除する)はフレームワークによっては対応が難しかったり複雑な追加実装が必要になることがあります。

Context Rot

2. 実行するAgentをTool Callを起点に入れ替えたい

前述のContext Rotの問題以前に、そもそもLLMにはなるべく必要最低限の情報のみを与えることが安定化に鍵になります(参照:Context Engineering)。これを実現するために、会話の状況に応じてPromptやToolを入れ替えるという手法があります。例えば、「ウェブやナレッジから情報を検索したあとに集めた情報をスライドにする」みたいなことをAgentでやる場合に、スライドへのCRUD操作のToolは情報検索の段階ではContextに与えずにスライドを編集するフェーズに入ってから付与するみたいな感じです。これをより単純化した手法としてhandoffというやり方が存在しており、OpenAI Agents SDK等handoffをネイティブでサポートしている場合もありつつ、フレームワークによっては「Tool起点でAgent Loopで利用するPromptやToolを入れ替える」という操作が難しい場合があります。

3. Toolの出力結果をユーザに見せつつ、LLMには別の内容を渡したい

Contextを有効活用する手法として、複雑だが一定の決まった操作をToolの中でdeterministicに実行するLLM Callとして切り出すやり方があります。簡単な例としては、先ほどの「特定の情報からスライドを作成する」みたいな操作をMainのAgentで実行するのではなく、Tool側の中で実行するAgentで行い、結果のみをMainのAgentに返すみたいなものになります。しかしこの実装を単純に実装すると、Toolの中でLLMで組み立てた結果をToolの出力として返し、それを受け取ったMainのAgentで改めてユーザに対して出力する結果を組み立てるといった手順になり、Contextの中で不必要な重複が生じてしまい性能劣化につながります。またToolの中ですでに完成している結果をユーザにすぐに出力できないためレイテンシーも上がります。
これを防ぐために、Toolの中で作成した結果をそのままユーザに出力するやり方が考えられます。ただその場合、ユーザ向けにはややフォーマットをかけた状態やUI向けに構造化した状態で出力し、LLM向けにはContextに載せるのに適切な形で返したくなります。また、LLM向けには情報を加工して(例:大きな成果物の場合、一部のみを返す)渡したいケースも発生します。こういった操作も大抵の場合自前での実装が必要になります。

他にもLLMを安定稼働させるためにテクニックを使おうとしたときに、フレームワークによっては対応ができなかったり、かなり無理矢理な追加実装を行う必要が出てきます。プロダクト上重要なLLMを安定化させる工夫を行なっていると、車輪の再発明を防ぐためにフレームワークを使っているはずが、いつの間にかフレームワークの内部構造の理解や強引な実装に逆に工数を取られてしまうような状態も発生します。

海外のAgent開発における実情

ここで一旦立ち返って、AI Agent開発の最前線である北米においてどのようなアプローチが取られているのかを見てみます。

まず最初にLLM Providerはシンプルなアプローチを取ることを推奨しています。AnthropicはBuilding effective agentsをはじめとして、むやみやたらにフレームワークを使うのではなく、シンプルな実装を行うことを推奨しています。OpenAIもSwarmでの検証を踏まえてOpenAI Agents SDKをリリースしていますが、過度な抽象化を抑えた実装になっています。

また、12 factor agentsでは多くのY-Combinatorスタートアップでフレームワークを使わない実装がなされているようです。gemini-cliなどのOpen SourceのAgent実装を見ても、かなりのContext Engineeringが行われており、Agent Loopも自前で実装されています。

今取れる現実的なオプション

こういった状況を踏まえると、「もはや自前で実装してAgentの動作を安定化させるために色々な実験を高速に回せるようにしたほうが良いのでは?」とも思えてきます。一方で、現状日本でAI Agentプロダクトの開発を行う場合、数名から10名程度のチームで行うケースがほとんどなのではないかと思います。その場合、AI Agentのロジック以外にも様々な開発が必要になります。自前実装の試行錯誤にどれだけのマインドシェアを使うべきかでいうと、ここに多くのリソースを使えるケースは多くないかと思います。また、AI Agentの開発を行う場合、Agentを稼働させるために実行基盤や監視、評価基盤などこれまでとは異なる多くの開発や試行錯誤も必要になります。
これらを踏まえると現実的には、

  1. 作りたいプロダクトとチームの構成から、開発のボトルネックを解消してくれるフレームワークを選択する
    数名でカッチリしたチャットUIを作るケースではAI SDKなどUIとの結合部分の開発のスピードアップできるものを選ぶ。ML系のチームでUIとの結合が簡素な場合、Pythonフレームワークから選ぶ。Durable実装をしたいがSREや基盤人材が不足している場合、Durableエンジンとの連携が組み込まれたフレームワークを選ぶなど。

  2. なるべく抽象度の低いフレームワークを選び、必要なContext Engineeringに応じた拡張を行う
    過度な抽象化がされたものではなく、抽象度が低いシンプルなものを選び、Agent Loop部分などAgentの挙動を安定化させるために必要な変更を加えやすい状況を維持する。

といった戦略が良いのではないかと個人的には感じています。一方で、ものすごく抽象化の得意なチーム構成だったり、CLIツールなどでAgent周辺の連携が薄く、コアのAgentロジックやAgent実行基盤にフォーカスできるようなチームではフレームワークを使わないオプションもあるかと思います。

まとめ

Agentフレームワークは現在進行形でAgentの実装手法の発達に合わせて急速に変化している領域です。Vercel CTOのMalte Ublさんが出演しているPodcast(Latent Space)でも、フレームワーク開発側も試行錯誤をしながら色々なアプローチにトライしている状況であることが伺えます。

LayerXではLLMが前提になった世界での経済活動のデジタル化や摩擦の解消へ真正面から向き合うべく、LLMを活用したAI Agentの開発に真正面から向き合って取り組んでいます。そして、これらの課題に向き合う仲間を全力で募集しています! 少しでもこれらのLLM活用に興味のある方がいればぜひ一度お話をさせてください!また、LLMやAIに興味はあってCoding Agentやモック制作にAIは使っているけど、作る側での知識や経験がないEngineerやPdMの方も多いのではないかと思いますが、そういった方でもぜひお声がけください。
カジュアル面談はこちら

また、この記事はLayerXエージェントブログリレー41日目の記事です。
明日以降も毎日AI Agentに関する記事が公開されますので、LayerX Tech公式Xアカウント私のXをフォローしてチェックいただければ幸いです!

LayerX

Discussion