Building effective agents (Engineering at Anthoropic)

### 原文
**Building effective agents**
https://www.anthropic.com/engineering/building-effective-agents

### はじめに
私たちは、業界を問わず、数十のチームとLLMエージェントの構築に取り組んできました。一貫して、最も成功した実装は、複雑なフレームワークではなく、シンプルで構成可能なパターンを使用しています。

過去1年間、私たちは業界を問わず、数十のチームと大規模言語モデル（LLM）エージェントの構築に取り組んできました。一貫して、最も成功した実装は、複雑なフレームワークや特殊なライブラリを使用していませんでした。代わりに、シンプルで構成可能なパターンで構築していました。 この記事では、お客様との協力や私たち自身のエージェント構築から学んだことを共有し、効果的なエージェントを構築するための実践的なアドバイスを開発者に向けて提供します。

### エージェントとは？
「エージェント」は、いくつかの方法で定義できます。一部のお客様は、エージェントを、さまざまなツールを使用して複雑なタスクを遂行するために、長期間にわたって独立して動作する完全に自律的なシステムとして定義しています。また、事前定義されたワークフローに従う、より規定的な実装を指すためにこの用語を使用するお客様もいます。Anthropicでは、これらすべてのバリエーションを**エージェントシステム**として分類していますが、**ワークフロー**と**エージェント**の間には、重要なアーキテクチャ上の区別があります。

- **ワークフロー**は、LLMとツールが事前定義されたコードパスを通じて連携されるシステムです
- **エージェント**は、LLMが自身のプロセスとツールの使用を動的に指示し、タスクをどのように達成するかを制御し続けるシステムです

以下では、両方のタイプのエージェントシステムについて詳しく説明します。付録1（「実践におけるエージェント」）では、お客様がこれらのシステムを使用することに特に価値を見出している2つのドメインについて説明します。

### エージェントを使用するべき時（とそうでない時）

LLMでアプリケーションを構築する際は、可能な限りシンプルなソリューションを見つけ、必要に応じて複雑さを増していくことをお勧めします。これは、エージェント的システムを全く構築しないことを意味するかもしれません。エージェント的システムは、多くの場合、レイテンシとコストをかけてタスクパフォーマンスを向上させます。そのため、このトレードオフが理にかなっているかどうかを検討する必要があります。

より複雑さが必要な場合、ワークフローは明確に定義されたタスクに対して予測可能性と一貫性を提供します。一方、エージェントは、柔軟性とモデル主導の意思決定が大規模に必要な場合に適しています。ただし、多くのアプリケーションでは、検索とコンテキスト内例を使用して単一のLLM呼び出しを最適化するだけで十分な場合がほとんどです。

### フレームワークをいつ、どのように使用するか

エージェントシステムをより簡単に実装するための多くのフレームワークがあります。例:

- LangChain の [LangGraph](https://python.langchain.com/docs/langgraph);
- Amazon Bedrock の [AI エージェントフレームワーク](https://aws.amazon.com/bedrock/agents/);
- Rivet, ドラッグアンドドロップ GUI LLM ワークフロービルダー; そして
- Vellum, 複雑なワークフローを構築およびテストするための別の GUI ツール。

これらのフレームワークを使用すると、LLM の呼び出し、ツールの定義と解析、呼び出しの連鎖などの標準的な低レベルタスクが簡素化されるため、簡単に始めることができます。ただし、多くの場合、追加の抽象化レイヤーが作成され、基になるプロンプトと応答が不明瞭になり、デバッグが困難になります。また、単純なセットアップで十分な場合に、複雑さを増すように誘われる可能性もあります。

開発者は、LLM API を直接使用して始めることをお勧めします。多くのパターンは数行のコードで実装できます。フレームワークを使用する場合は、基になるコードを理解していることを確認してください。背後にあるものについて誤った仮定をすることは、顧客エラーの一般的な原因です。

いくつかのサンプル実装については、[クックブック](https://github.com/anthropics/anthropic-cookbook) を参照してください。

### 構成要素、ワークフロー、およびエージェント

このセクションでは、実際に運用されているエージェントシステムでよく見られるパターンについて説明します。まず、基本的な構成要素である **拡張された LLM** から始め、単純な構成ワークフローから自律エージェントまで、徐々に複雑さを増していきます。

### 構成要素：拡張LLM

エージェントシステムの基本的な構成要素は、検索、ツール、メモリなどの拡張機能で強化されたLLMです。現在のモデルは、これらの機能を積極的に使用できます。独自の検索クエリを生成したり、適切なツールを選択したり、保持する情報を決定したりできます。

![The augmented LLM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107056/a40176f3-9941-4b44-8e8f-17383061a496.png)

実装の2つの重要な側面に焦点を当てることをお勧めします。これらの機能を特定のユースケースに合わせて調整し、LLMに簡単で十分に文書化されたインターフェースを提供することです。これらの拡張機能を実装する方法はたくさんありますが、1つのアプローチは、最近リリースされた[モデルコンテキストプロトコル](リンク先)を使用することです。これにより、開発者は単純な[クライアント実装](リンク先)を使用して、拡大するサードパーティツールのエコシステムと統合できます。

この記事の残りの部分では、各LLM呼び出しがこれらの拡張機能にアクセスできることを前提としています。

### ワークフロー：プロンプトチェーニング

プロンプトチェーニングは、タスクを一連のステップに分解し、各LLM呼び出しが前のLLM呼び出しの出力を処理します。プロセスがまだ順調に進んでいることを確認するために、中間ステップにプログラムによるチェック（下の図の「ゲート」を参照）を追加できます。

![The prompt chaining workflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107056/5fd6d7a2-b943-4e18-a9b8-24e9257c1936.png)

**このワークフローを使用する場合：** このワークフローは、タスクを固定されたサブタスクに簡単かつ明確に分解できる状況に最適です。主な目標は、各LLM呼び出しをより簡単なタスクにすることで、レイテンシと引き換えに精度を高めることです。

**プロンプトチェーニングが役立つ例：**

*   マーケティングコピーを生成し、それを別の言語に翻訳する
*   ドキュメントの概要を作成し、その概要が特定の基準を満たしていることを確認してから、概要に基づいてドキュメントを作成する


### ワークフロー：ルーティング

ルーティングは、入力を分類し、専門化されたフォローアップタスクに誘導します。このワークフローにより、関心の分離が可能になり、より特殊なプロンプトを構築できます。このワークフローがない場合、1種類の入力に対して最適化すると、他の入力のパフォーマンスが低下する可能性があります。

![The routing workflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107056/a4d5b18c-ec4f-4f25-9176-4426cb5cb13e.png)

**このワークフローを使用するタイミング：**ルーティングは、別々に処理する方が適切である個別のカテゴリがあり、分類がLLMまたはより従来の分類モデル/アルゴリズムによって正確に処理できる複雑なタスクに適しています。

ルーティングが役立つ例：

*   さまざまな種類のカスタマーサービスクエリ（一般的な質問、払い戻しのリクエスト、テクニカルサポート）を、さまざまなダウンストリームプロセス、プロンプト、およびツールに誘導する
*   簡単/一般的な質問をClaude 3.5 Haikuのような小さいモデルにルーティングし、難しく/珍しい質問をClaude 3.5 Sonnetのようなより高性能なモデルにルーティングして、コストと速度を最適化する


### ワークフロー：並列化

LLMは、タスクを同時に実行し、その出力をプログラムで集計する場合があります。このワークフローである並列化は、2つの主要なバリエーションで現れます。

*   **セクション分割**：タスクを独立したサブタスクに分割して並行して実行します。
*   **投票**：多様な出力を得るために、同じタスクを複数回実行します。

![The parallelization workflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107056/081b212b-4ab4-4840-ab8e-5b8c9d9ed2e9.png)

**このワークフローを使用するタイミング**：並列化は、分割されたサブタスクを高速化のために並列化できる場合、またはより信頼性の高い結果を得るために複数の視点または試みが必要な場合に効果的です。複数の考慮事項がある複雑なタスクの場合、LLMは通常、各考慮事項を個別のLLM呼び出しで処理する方がパフォーマンスが向上し、各特定の側面に焦点を当てることができます。

**並列化が役立つ例**：

*   **セクション分割**：
    *   1つのモデルインスタンスがユーザーのクエリを処理し、別のモデルインスタンスが不適切なコンテンツまたはリクエストをスクリーニングするガードレールの実装。これは、同じLLM呼び出しでガードレールとコアレスポンスの両方を処理するよりもパフォーマンスが向上する傾向
    *   LLMのパフォーマンスを評価するための自動評価。各LLMの呼び出しは、特定のプロンプトに対するモデルのパフォーマンスのさまざまな側面を評価します
*   **投票**：
    *   脆弱性がないかコードをレビューし、複数の異なるプロンプトがコードをレビューし、問題が見つかった場合はフラグを立てます
    *   特定のコンテンツが不適切かどうかを評価し、複数のプロンプトがさまざまな側面を評価したり、誤検知と誤検出のバランスを取るために異なる投票しきい値を必要としたりします

### ワークフロー：オーケストレーターワーカー

オーケストレーターワーカーワークフローでは、中央のLLMがタスクを動的に分解し、ワーカーLLMに委任し、それらの結果を統合します。

![The orchestrator-wokers workflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107056/b85af2a9-471a-4e1f-aa95-88f0cf0da001.png)

**このワークフローを使用するタイミング**：このワークフローは、必要なサブタスクを予測できない複雑なタスクに適しています（たとえば、コーディングでは、変更する必要があるファイルの数と各ファイルの変更の性質は、タスクによって異なる可能性があります）。地形的には似ていますが、並列化との主な違いは、柔軟性です。サブタスクは事前定義されていませんが、オーケストレーターによって特定の入力に基づいて決定されます。

**オーケストレーターワーカーが役立つ例**：

*   毎回複数のファイルに複雑な変更を加えるコーディング製品
*   関連する可能性のある情報について、複数のソースから情報を収集して分析する検索タスク


### ワークフロー：評価者オプティマイザー

評価者オプティマイザー ワークフローでは、1つのLLMの呼び出しが応答を生成し、別のLLMの呼び出しがループで評価とフィードバックを提供します。

![The evaluator-optimizer workflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107056/12c36c06-f9b9-4557-9865-becc78d2cee6.png)

**このワークフローを使用する時：**このワークフローは、明確な評価基準があり、反復的な改善が測定可能な価値を提供する場合に特に効果的です。適合性の兆候は2つあります。1つ目は、人間がフィードバックを明確にすると、LLMの応答が明らかに改善されること。2つ目は、LLMがそのようなフィードバックを提供できることです。これは、人間の作家が洗練されたドキュメントを作成するときに経る反復的な執筆プロセスと似ています。

**評価者オプティマイザーが役立つ例：**

*   翻訳者のLLMが最初には捉えられないニュアンスがある文学翻訳。ただし、評価者オプティマイザーLLMが役立つ批評を提供できます
*   包括的な情報を収集するために、複数回の検索と分析が必要な複雑な検索タスク。評価者オプティマイザーは、さらに検索が必要かどうかを判断します


### エージェント

エージェントは、主要な機能（複雑な入力の理解、推論と計画への関与、ツールを確実に使用すること、エラーからの回復）でLLMが成熟するにつれて、本番環境に登場しています。エージェントは、人間ユーザーからのコマンドまたはインタラクティブなディスカッションから作業を開始します。タスクが明確になると、エージェントは独立して計画および操作し、さらなる情報または判断のために人間に戻る可能性があります。実行中は、エージェントが各ステップで環境から「グラウンドトゥルース」（ツールの呼び出し結果やコードの実行など）を取得して、進捗状況を評価することが重要です。エージェントは、チェックポイントまたはブロッカーに遭遇したときに、人間のフィードバックのために一時停止できます。タスクは完了時に終了することが多いですが、制御を維持するために停止条件（反復の最大数など）を含めることも一般的です。

エージェントは洗練されたタスクを処理できますが、その実装は多くの場合簡単です。通常、それらは環境からのフィードバックに基づいてツールを使用するLLMにすぎません。したがって、ツールセットとそのドキュメントを明確かつ慎重に設計することが重要です。ツールの開発に関するベストプラクティスについては、付録2（「ツールのプロンプトエンジニアリング」）で詳しく説明します。

![Autonomous agent.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107056/c02db457-d5cb-437a-b2bb-b60106569244.png)

**エージェントを使用する状況**：エージェントは、必要なステップ数を予測することが困難または不可能な、オープンエンドの問題に使用できます。また、固定パスをハードコーディングすることもできません。LLMは潜在的に多くのターンで動作するため、その意思決定にある程度の信頼を置く必要があります。エージェントの自律性により、信頼できる環境でのタスクのスケーリングに最適です。

エージェントの自律性により、コストが高くなり、エラーが増加する可能性があります。サンドボックス環境での広範なテストと、適切なガードレールをお勧めします。

エージェントが役立つ例：

次の例は、当社独自のインプリメンテーションからのものです。

*   タスクの説明に基づいて多くのファイルを編集する、[SWE-benchタスク](https://github.com/princeton-nlp/SWE-agent)を解決するコーディングエージェント
*   当社の[「コンピュータの使用」](https://www.anthropic.com/research/claude-3-opus)リファレンス実装。Claudeがコンピュータを使用してタスクを完了します

![High-level flow of a coding agent.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107056/6c8eca10-8649-487b-bd9d-f71b640f6f7d.png)

### まとめ

LLM分野での成功は、最も洗練されたシステムを構築することではありません。ニーズに合った適切なシステムを構築することです。単純なプロンプトから始め、包括的な評価で最適化し、よりシンプルなソリューションが不十分な場合にのみ、多段階エージェントシステムを追加します。

エージェントを実装する場合、次の3つのコア原則に従うように努めます。
1. エージェントの設計で**シンプルさ**を維持します
2. エージェントの計画手順を明示的に示すことで、**透明性**を優先します
3. 徹底的なツールの**ドキュメント化**とテストを通じて、エージェント-コンピューターインターフェイス（ACI）を慎重に作成します

フレームワークは迅速に開始するのに役立ちますが、抽象化レイヤーを削減し、本番環境に移行する際に基本的なコンポーネントで構築することを躊躇しないでください。これらの原則に従うことで、強力であるだけでなく、信頼性が高く、保守可能で、ユーザーから信頼されるエージェントを作成できます。

### 謝辞

執筆者：Erik SchluntzとBarry Zhang。この作品は、Anthropicでのエージェントの構築経験と、お客様から共有された貴重な洞察に基づいており、深く感謝申し上げます。

### 付録1：実践におけるエージェント

顧客との取り組みを通して、AIエージェントの特に有望な2つの応用例が明らかになりました。これらの例は、上記のパターンが持つ実践的な価値を示しています。どちらの応用例も、エージェントが会話と行動の両方を必要とし、明確な成功基準を持ち、フィードバックループを有効にし、意味のある人間の監督を統合するタスクに対して最も価値を付加することを示しています。

**A. カスタマーサポート**

カスタマーサポートは、使い慣れたチャットボットのインターフェースと、ツール連携による強化された機能を組み合わせています。これは、よりオープンなエージェントにとって自然な適合です。なぜなら：

*   サポートのやり取りは、外部情報やアクションへのアクセスを必要としながら、自然に会話の流れに従うからです。
*   顧客データ、注文履歴、ナレッジベースの記事を取得するために、ツールを連携させることができます。
*   払い戻しの発行やチケットの更新などのアクションをプログラムで処理できます。
*   成功は、ユーザー定義の解決を通じて明確に測定できます。

いくつかの企業は、成功した解決に対してのみ課金する使用量ベースの価格設定モデルを通じて、このアプローチの実現可能性を実証しており、エージェントの有効性に自信を示しています。

**B. コーディングエージェント**

ソフトウェア開発の分野は、LLM機能の目覚ましい可能性を示しており、その能力はコード補完から自律的な問題解決へと進化しています。エージェントは特に効果的です。なぜなら：

*   コードソリューションは、自動テストによって検証可能だからです。
*   エージェントは、テスト結果をフィードバックとして使用してソリューションを反復処理できるからです。
*   問題空間は明確に定義され構造化されているからです。
*   出力品質を客観的に測定できるからです。

当社の独自の実装では、エージェントはプルリクエストの説明のみに基づいて、[SWE-bench Verified](https://github.com/princeton-nlp/SWE-bench)ベンチマークで実際の問題を解決できるようになりました。ただし、自動テストは機能の検証には役立ちますが、ソリューションがより広範なシステム要件に適合することを保証するには、人間のレビューが依然として重要です。

### 付録2：ツールをプロンプトエンジニアリングする

構築しているエージェントシステムに関係なく、ツールはおそらくエージェントの重要な一部となるでしょう。**ツール**を使用すると、Claude はAPI内で正確な構造と定義を指定することにより、外部サービスおよびAPIと対話できます。 Claude が応答するとき、ツールを呼び出す予定がある場合は、API応答に**ツール使用ブロック**が含まれます。ツールの定義と仕様は、全体のプロンプトと同じくらい注意を払ってプロンプトエンジニアリングする必要があります。この簡単な付録では、ツールのプロンプトエンジニアリング方法について説明します。

同じアクションを指定する方法はいくつかあることがよくあります。たとえば、差分を記述するか、ファイル全体を書き換えることで、ファイルの編集を指定できます。構造化された出力の場合、コードをマークダウン内またはJSON内に返すことができます。ソフトウェアエンジニアリングでは、これらの違いは表面的なものであり、損失なく相互に変換できます。ただし、一部の形式は、LLMが記述するのが他の形式よりもはるかに困難です。差分を記述するには、新しいコードが記述される前に、チャンクヘッダーで変更されている行数を把握する必要があります。（マークダウンと比較して）JSON内にコードを記述するには、改行と引用符を特別にエスケープする必要があります。

ツール形式を決定するための推奨事項は次のとおりです。

*   モデルに、窮地に陥る前に「考える」のに十分なトークンを与えます。
*   モデルがインターネット上のテキストで自然に発生するのを見てきたものに近い形式を維持します。
*   数千行のコードを正確にカウントしたり、記述するコードを文字列エスケープしたりするなど、フォーマットの「オーバーヘッド」がないようにします。

経験則の1つは、ヒューマンコンピュータインタフェース（HCI）にどれだけの労力が費やされているかを考え、優れた**エージェントコンピュータインタフェース（ACI）**の作成に同じくらいの労力を費やすことを計画することです。以下に、その方法に関するいくつかの考えを示します。

*   モデルの立場になって考えてみてください。説明とパラメータに基づいて、このツールの使用方法が明らかですか、それとも慎重に検討する必要がありますか？もしそうなら、おそらくモデルにも当てはまります。優れたツールの定義には、多くの場合、使用例、エッジケース、入力形式の要件、および他のツールからの明確な境界が含まれます。
*   パラメータ名または説明を変更して、よりわかりやすくするにはどうすればよいですか？これをチームのジュニア開発者向けに優れたドキュメンテーションを書くことと考えてください。これは、多くの類似したツールを使用する場合に特に重要です。
*   モデルがツールをどのように使用するかをテストします。多くの入力例を[ワークベンチ](https://console.anthropic.com/workbench)で実行して、モデルが犯す間違いを確認し、繰り返します。
*   ツールを[ポカヨケ](https://ja.wikipedia.org/wiki/%E3%83%9D%E3%82%AB%E3%83%A8%E3%82%B1)します。引数を変更して、間違いを犯しにくくします。

[SWE-bench](https://github.com/princeton-nlp/SWE-bench)のエージェントを構築する際、実際には、全体のプロンプトよりもツールの最適化に多くの時間を費やしました。たとえば、エージェントがルートディレクトリから移動した後、モデルが相対ファイルパスを使用するツールで間違いを犯すことがわかりました。これを修正するために、ツールが常に絶対ファイルパスを要求するように変更しました。そして、モデルがこのメソッドを完璧に使用していることがわかりました。