Azure AI Foundry Agent Service の接続済みエージェントを使用すると、カスタム オーケストレーターや手動でコーディングされたルーティング ロジックを必要とせずに、複雑なタスクを調整された特殊なロールに分割できます。 この機能を使用すると、プライマリ エージェントが専用のサブエージェントにインテリジェントに委任し、顧客サポート、市場調査、法的要約、財務分析などのワークフローを合理化するシステムを設計できます。
1 つのエージェントに多くのスキルをオーバーロードするのではなく、シームレスに共同作業を行う、集中型の再利用可能なエージェントを構築し、パフォーマンスと保守性の両方をスケーリングできます。
特徴
- 簡素化されたワークフロー設計: 複雑さを軽減し、明確にするために、特殊なエージェント間で複雑なタスクを分割します。
- カスタム オーケストレーションは必要ありません:メイン エージェントは自然言語を使用してタスクをルーティングするため、ハードコーディングされたロジックは不要です。
- 簡単な拡張性: メイン エージェントを変更せずに、新しい接続されたエージェント (翻訳やリスク スコアリングなど) を追加します。
- 信頼性と追跡可能性の向上: デバッグを容易にし、監査性を向上させるために、各エージェントに重点を置いた責任を割り当てます。
- 柔軟なセットアップ オプション: Foundry ポータルでコードなしのインターフェイスを使用するか、Python SDK を使用してプログラムでエージェントを構成します。
例: 接続されたエージェントを使用してモジュラー コントラクト レビュー エージェントを構築する
ユース ケースが複雑になるにつれて、接続されている複数のエージェントに特定の責任を割り当てることで、AI ソリューションをスケーリングできます。 これにより、各エージェントは狭いタスクを専門にし、メイン エージェントはワークフロー全体を調整できます。 このモジュール設計により、精度、保守容易性、および追跡可能性が向上します。特に、法的、コンプライアンス、調達などのドキュメントの負荷の高い分野に対して行われます。 接続されたエージェントを使用して コントラクト レビュー アシスタント を構築する方法の実際の例を見てみましょう。
アーキテクチャの概要
メイン エージェント – コントラクト オーケストレーター
中央インターフェイスとして機能します。 ユーザー プロンプト (「句を要約」、「ドラフトを比較」、「コンプライアンスを確認」など) を解釈し、タスクの種類を決定し、適切な対応するエージェントに委任します。
使用されているツール: 直接なし
責任: 意図の分類と委任
エージェントの説明の例:
"あなたは契約レビューアシスタントです。 ユーザー クエリに応じて、タスクに句の要約、ドキュメントの比較、またはコンプライアンス チェックが含まれているかどうかを判断し、それに応じてルーティングします。"
接続済みエージェント 1: 句要約ツール
コントラクトから重要なセクション (終了、補償、機密性など) を抽出し、プレーンな言語で要約します。
使用されるツール:
- アップロードされたコントラクトを取得するファイル検索
- ドキュメントをスキャンして句の見出しを検索し、内容を要約するコード インタープリター
責任: 情報の抽出と要約
エージェントの説明の例:
"提供された契約から'終了'、'支払条件'、および '補償'句を抽出して要約します。
接続されたエージェント 2: コンプライアンス検証コントロール
内部標準またはアップロードされたガイドラインに対してコントラクトをチェックして、危険な言語または非準拠言語を特定します。
使用されるツール:
- 内部ポリシー ドキュメントまたはコントラクト テンプレートにアクセスするためのファイル検索
- 内部コンプライアンス規則 API を呼び出す OpenAPI ツール
- 単純なロジック検査を実行する Azure 関数または Azure Logic Apps (必須の句の存在やしきい値の検証など)
責任: ポリシーの照合とリスクフラグ
プロンプト命令の例:
"このドキュメントを会社のコンプライアンス ガイドラインに照らして確認し、承認済みのテンプレートからの逸脱にフラグを付けます。"
制限事項
- 接続されたエージェントは、関数呼び出しツールを使用してローカル関数を呼び出すことはできません。 代わりに 、OpenAPI ツール または Azure Functions を使用することをお勧めします。
- 現時点では、接続されているエージェントから引用文献が渡されることを保証することはできません。 プロンプト エンジニアリングをさまざまなモデルと組み合わせて使用して、メイン エージェントによって引用文献が出力される可能性を高めることができますが、結果は変動の影響を受けます。
マルチエージェント セットアップの作成
- ポータルの [エージェント] ページに移動します
- 一覧から既存のエージェントを選択するか、新しいエージェントを作成します。
- エージェントのセットアップ パネルで [ 接続済みエージェント ] セクションまで下にスクロールし、[ +] を選択します。
表示されるダイアログで、タスクを委任するメイン エージェントのエージェントを選択し、次の内容を説明します。
- ドロップダウンから 既存のエージェント を選択します。 これは、メイン エージェントがタスクを委任する接続されたエージェントです。
- 接続されているエージェントの 一意の名前 を入力します (文字とアンダースコアのみ)。 この名前は、API レベルの関数呼び出しに使用されます。 正確な再現率を最大限に高めるために、記述的で機械が読み取れる形式にしてください(例:
summarize_text
、lookup_product_info
)。 - 接続されたエージェントを呼び出すタイミングと理由の明確な 説明 を追加します。 これは、実行時に接続されたエージェントにタスクを渡すタイミングに関するメイン エージェントの意思決定をガイドするのに役立ちます。
+ 追加を選択する
手順 3 ~ 5 を繰り返して、メイン エージェントに特殊なエージェントを追加します。
接続されているエージェントがセットアップ パネルに表示されたら、上にスクロールして [プレイグラウンドで試す] を選択します
エージェントプレイグラウンドのテストプロンプトを使用して、メインエージェントが該当する場合に接続されたエージェントにタスクを正しくルーティングすることを検証します。 たとえば、ツールが構成されていない
research_agent
というメイン エージェントを作成し、stock_price_bot
という名前のエージェントを接続した場合は、次のようなプロンプトを試してください。"Microsoft の現在の株価は何ですか?
research_agent
は、定義したルーティングの説明に基づいて、この要求をstock_price_bot
に委任する必要があります。
.NET SDK を使用する
注
これは同期的な使用法を示しています。 GitHub で非同期の例を見つけることができます
エージェントが接続されたエージェントを使用できるようにするには、エージェント ID、名前、および説明と共に ConnectedAgentToolDefinition
を使用します。
まず、エージェント クライアントを作成し、環境変数を読み取る必要があります。環境変数は、次の手順で使用します。
var projectEndpoint = configuration["ProjectEndpoint"]; var modelDeploymentName = configuration["ModelDeploymentName"]; PersistentAgentsClient client = new(projectEndpoint, new DefaultAzureCredential());
次に、メイン エージェント
mainAgent
と、エージェント クライアントを使用して接続stockAgent
エージェントを作成します。 この接続されたエージェントは、ConnectedAgentToolDefinition
の初期化に使用されます。PersistentAgent stockAgent = client.Administration.CreateAgent( model: modelDeploymentName, name: "stock_price_bot", instructions: "Your job is to get the stock price of a company. If you don't know the realtime stock price, return the last known stock price." // tools: [...] tools that would be used to get stock prices ); ConnectedAgentToolDefinition connectedAgentDefinition = new(new ConnectedAgentDetails(stockAgent.Id, stockAgent.Name, "Gets the stock price of a company")); PersistentAgent mainAgent = client.Administration.CreateAgent( model: modelDeploymentName, name: "stock_price_bot", instructions: "Your job is to get the stock price of a company, using the available tools.", tools: [connectedAgentDefinition] );
次に、スレッドを作成し、エージェントの質問を含むメッセージを追加し、実行を開始します。
PersistentAgentThread thread = client.Threads.CreateThread(); // Create message to thread PersistentThreadMessage message = client.Messages.CreateMessage( thread.Id, MessageRole.User, "What is the stock price of Microsoft?"); // Run the agent ThreadRun run = client.Runs.CreateRun(thread, agent); do { Thread.Sleep(TimeSpan.FromMilliseconds(500)); run = client.Runs.GetRun(thread.Id, run.Id); } while (run.Status == RunStatus.Queued || run.Status == RunStatus.InProgress); // Confirm that the run completed successfully if (run.Status != RunStatus.Completed) { throw new Exception("Run did not complete successfully, error: " + run.LastError?.Message); }
エージェント メッセージを時系列でコンソールに出力します。
Pageable<PersistentThreadMessage> messages = client.Messages.GetMessages( threadId: thread.Id, order: ListSortOrder.Ascending ); foreach (PersistentThreadMessage threadMessage in messages) { Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: "); foreach (MessageContent contentItem in threadMessage.ContentItems) { if (contentItem is MessageTextContent textItem) { string response = textItem.Text; if (textItem.Annotations != null) { foreach (MessageTextAnnotation annotation in textItem.Annotations) { if (annotation is MessageTextUriCitationAnnotation urlAnnotation) { response = response.Replace(urlAnnotation.Text, $" [{urlAnnotation.UriCitation.Title}]({urlAnnotation.UriCitation.Uri})"); } } } Console.Write($"Agent response: {response}"); } else if (contentItem is MessageImageFileContent imageFileItem) { Console.Write($"<image from ID: {imageFileItem.FileId}"); } Console.WriteLine(); } }
スレッドとエージェントを削除してリソースをクリーンアップします。
agentClient.DeleteThread(threadId: thread.Id); agentClient.DeleteAgent(agentId: agent.Id); agentClient.DeleteAgent(agentId: connectedAgent.Id);
マルチエージェント セットアップの作成
マルチエージェント セットアップを作成するには、次の手順に従います。
クライアント オブジェクトを初期化します。
import os from azure.ai.projects import AIProjectClient from azure.ai.agents.models import ConnectedAgentTool, MessageRole from azure.identity import DefaultAzureCredential project_client = AIProjectClient( endpoint=os.environ["PROJECT_ENDPOINT"], credential=DefaultAzureCredential(), )
"main" エージェントに接続されるエージェントを作成します。
stock_price_agent = project_client.agents.create_agent( model=os.environ["MODEL_DEPLOYMENT_NAME"], name="stock_price_bot", instructions="Your job is to get the stock price of a company. If you don't know the realtime stock price, return the last known stock price.", #tools=... # tools to help the agent get stock prices )
エージェント ID、名前、および説明を使用して、接続されたエージェント ツールを初期化します
connected_agent = ConnectedAgentTool( id=stock_price_agent.id, name=stock_price_agent.name, description="Gets the stock price of a company" )
接続されたエージェントを使用する "main" エージェントを作成します。
agent = project_client.agents.create_agent( model=os.environ["MODEL_DEPLOYMENT_NAME"], name="my-agent", instructions="You are a helpful agent, and use the available tools to get stock prices.", tools=connected_agent.definitions, ) print(f"Created agent, ID: {agent.id}")
スレッドを作成し、それにメッセージを追加します。
thread = project_client.agents.threads.create() print(f"Created thread, ID: {thread.id}") # Create message to thread message = project_client.agents.messages.create( thread_id=thread.id, role=MessageRole.USER, content="What is the stock price of Microsoft?", ) print(f"Created message, ID: {message.id}")
実行を作成し、完了するまで待ちます。
# Create and process Agent run in thread with tools run = project_client.agents.runs.create_and_process(thread_id=thread.id, agent_id=agent.id) print(f"Run finished with status: {run.status}") if run.status == "failed": print(f"Run failed: {run.last_error}") # Delete the Agent when done project_client.agents.delete_agent(agent.id) print("Deleted agent") # Delete the connected Agent when done project_client.agents.delete_agent(stock_price_agent.id) print("Deleted connected agent")
エージェントの応答を印刷します。 メイン エージェントは、接続されたエージェントからの応答をコンパイルし、応答を提供します。 接続されたエージェントの応答は、メイン エージェントにのみ表示され、エンド ユーザーには表示されません。
# Print the Agent's response message with optional citation response_message = project_client.agents.messages.list(thread_id=thread.id).get_last_message_by_role( MessageRole.AGENT ) if response_message: for text_message in response_message.text_messages: print(f"Agent response: {text_message.text.value}") for annotation in response_message.url_citation_annotations: print(f"URL Citation: [{annotation.url_citation.title}]({annotation.url_citation.url})")