[翻訳]OpenSearch 3.0 の plan-execute-reflect agent によるインテリジェントなトラブルシュート
本投稿は OpenSearch Project Blog "Intelligent troubleshooting using OpenSearch 3.0’s plan-execute-reflect agent" の日本語訳です。
OpenSearch 3.0 では、plan-execute-reflect エージェントが導入されました。これは複雑な問題を分解し、ツールを自律的に選択・実行し、振り返りを通じて適応する強力な新機能です。この記事では、このエージェントが可観測性ワークフローにおける根本原因分析をどのように自動化するかをご紹介します。
はじめに
AI の時代において、エージェントは大規模言語モデル (LLM) をより実用的で有用なものにする強力な手段として登場しました。LLM を特定のツールや機能に接続することで、エージェントは自然言語リクエストを具体的なアクションに変換し、意味のある結果へと導くことができます。
OpenSearch ML Commons はこの変革の最前線に立ち、ツールを調整しワークフローを自動化できる堅牢なエージェントフレームワークを提供してきました。OpenSearch 3.0 では、複雑な多段階推論タスク向けに設計された plan-execute-reflect エージェントを導入し、大きな飛躍を遂げています。
OpenSearch 3.0 のエージェントフレームワークの新機能
OpenSearch 3.0 では、データとの対話や複雑な問題への対処方法を強化する改良されたエージェントフレームワークが導入されています。主な追加機能は、多段階タスクを体系的に処理するために設計された plan-execute-reflect エージェントです。
新しいエージェントフレームワークには、以下のような注目すべき改良点が含まれています
- 複雑な多段階タスクを体系的に分解して実行する plan-execute-reflect エージェント
- 外部 AI ツールとの統合のためのネイティブ Model Context Protocol (MCP) サポート
- 強化されたツール選択と実行機能
- 長時間実行タスクを効率的に管理するための非同期実行サポート
このブログ記事では、この新しいエージェントフレームワークの真の力を示す実用的な可観測性のユースケースを詳しく見ていきます。マイクロサービスアプリケーションにおけるサービス障害を自動的に調査する方法(通常は時間がかかり複雑なプロセス)を実際に見ていただきます。エージェントが以下のことを行う様子をご覧いただけます
- 複雑な調査を論理的なステップに分解する
- 適切なツールを自動的に選択して使用する
- 複数のデータソース(ログ、トレース、メトリクス)を分析する
- 明確で実行可能な洞察を提供する
クラウドインフラストラクチャの管理、アプリケーション開発、AI を活用したソリューションの構築など、この新機能はワークフローの合理化と問題解決能力の向上に役立ちます。
それでは、plan-execute-reflect エージェントの機能とワークフローを見ていきましょう。
plan-execute-reflect エージェントとは
plan-execute-reflect エージェントは、複雑な多段階タスク向けに設計された長時間実行エージェントです。このエージェントは、複雑なタスクを一連の単純なステップに分解し(plan)、各ステップを実行し(execute)、中間ステップの結果に基づいて計画を最適化する(reflect)能力を持っています。サブステップの実行には別のエグゼキューターエージェントを使用します。
このエージェントの主な特徴は以下の通りです
- 中間結果に基づいて進化する適応型計画
- 登録時に独自のエグゼキューターエージェントを指定することで、計画フェーズと実行フェーズで異なるモデルを使用する柔軟性(デフォルトでは会話型エージェントを使用)
- バックグラウンドで長時間実行ワークフローを処理するための非同期実行機能(async=true の場合)
- 複数の MCP サーバーへの接続を可能にする組み込み MCP クライアント機能
- 関数呼び出しを通じた標準化されたツールコミュニケーション
- カスタムプロンプトのサポートにより、可観測性エージェントや研究エージェント(WebSearchTool を使用)などの特定のユースケース向けの特殊化が可能
以下の図は、plan-execute-reflect エージェントの実行フローを示しています。
ワークフローは以下のステップで構成されています
- ユーザーが plan-execute-reflect エージェントにタスクを提供します。
- plan-execute-reflect エージェントはタスクをプランナー LLM に転送します。
- LLM は計画(実行するステップのシリーズ)を返します。
- plan-execute-reflect エージェントは計画の最初のステップをエグゼキューターエージェントに転送します。
- エグゼキューターエージェントはステップを実行し、応答を返します。
- plan-execute-reflect エージェントは実行されたステップの結果と元の計画をプランナー LLM に転送します。
- プランナー LLM は最終結果または改良された計画を返します。
- プランナー LLM が最終結果を返した場合、その結果はユーザーに返されます。そうでない場合、プランナー LLM は新しい計画を返し、タスクを完了して結果を返すのに十分な情報が得られるまでステップ 4~7 を実行します。
詳細な技術情報については、この issue を参照してください。
それでは、実際のシナリオをシミュレートして plan-execute-reflect エージェントの動作を見てみましょう。システムの問題を特定し、その根本原因を見つけるという実用的な問題にどのように対処するかを説明します。
OpenTelemetry デモアプリを使用した実際の障害のシミュレーション
現代の分散システムは複雑で、監視に大きな課題をもたらします。マイクロサービスは予測不可能な方法で相互に通信し、何が起きているかという情報はログ、トレース、メトリクスにわたって分散しています。OpenSearch は、メトリクス、ログ、トレース用のダッシュボードを含む強力な可観測性ツールスイートを提供し、分散システムの監視とトラブルシューティングを支援します。しかし、複雑な障害をデバッグする際、サービスとインフラストラクチャ層全体でシグナルを手動で関連付ける必要があることがよくあります。このプロセスは一般的に遅く退屈です。ここでエージェントの出番です。OpenSearch の可観測性データと推論・計画能力を組み合わせることで、これらのエージェントは根本原因分析を自動化し、実行可能な洞察を生成し、トラブルシューティング体験を大幅に向上させることができます。
plan-execute-reflect エージェントを使用して、マイクロサービスアプリケーションの問題の根本原因を特定できる可観測性エージェントを構築する方法を紹介します。最小限のセットアップで自然言語入力を使用して、エージェントを登録し、タスクを実行し、出力を解釈する方法をお見せします。
マイクロサービス環境での障害をシミュレートします。e コマースアプリケーションでのカート障害です。このために、実際のシステムを模した参照アプリケーションである OpenTelemetry デモアプリケーションを使用します。
このアプリケーションは、ログ、トレース、メトリクスを含むテレメトリデータを OpenSearch に送信し、豊富な可観測性シグナルを提供します。カート障害をトリガーし、その後、可観測性エージェントにこれらのシグナルを使用して根本原因を診断するよう依頼します。
デモアプリケーションの詳細については、OpenTelemetry-Demo を参照してください。
カート障害のトリガー
OpenTelemetry デモは flagd という簡単な機能フラグサービスを使用して、組み込みの障害シナリオを管理しています。Web UI を使用するか、デモの設定ファイルを直接編集することで、フラグ値を切り替えることができます。カート障害をシミュレートするには、次の手順を実行します:
- OpenTelemetry デモアプリケーションをデプロイし、http://localhost:8080/feature の機能フラグダッシュボードに移動します。
- cartFailure を見つけ、On の位置に切り替えて、Save を選択します。
- カートにアクセスするには、http://localhost:8080/cart に移動します。フラグが有効になると、フロントエンド UI の Empty Cart ボタンが機能しなくなります。
- エラー状態を生成するには、ショッピングカートに少なくとも 1 つのアイテムを追加し、Empty Cart ボタンを選択します。
この操作は失敗し、Cart Service の障害に対応するエラースパンとログが OpenSearch でトリガーされます。
カート障害がアクティブになると、デモアプリケーションは Cart Service のエラーレベルのスパンとログエントリを出力します。これらのシグナルが根本原因分析の基礎となります。
可観測性エージェントを使用した問題の調査
それでは、OpenSearch の新しい plan-execute-reflect エージェントを使用して、この問題の根本原因を特定してみましょう。ログを手動でクエリしたり、トレースを調べたりする代わりに、エージェントに問題を説明し、調査を実行させます。以下の手順でエージェントをセットアップしましょう。
エージェントの詳細については、Plan-execute-reflect agent を参照してください。
ステップ 1: LLM の登録
エージェントで使用する LLM を登録します。この例では、Amazon Bedrock にデプロイされた Claude 3.7 Sonnet モデルを使用します。
LLM をエージェントに接続する方法の詳細については、Connecting to LLMs を参照してください。
ステップ 1.1: コネクタの登録
POST /_plugins/_ml/connectors/_create
{
"name": "BedRock Claude 3.7-sonnet connector",
"description": "Connector to Bedrock service for claude model",
"version": 1,
"protocol": "aws_sigv4",
"parameters": {
"region": "your_aws_region",
"service_name": "bedrock",
"model": "us.anthropic.claude-3-7-sonnet-20250219-v1:0"
},
"credential": {
"access_key": "your_aws_access_key",
"secret_key": "your_aws_secret_key",
"session_token": "your_aws_session_token"
},
"actions": [
{
"action_type": "predict",
"method": "POST",
"url": "https://bedrock-runtime.${parameters.region}.amazonaws.com/model/${parameters.model}/converse",
"headers": {
"content-type": "application/json"
},
"request_body": "{ \"system\": [{\"text\": \"${parameters.system_prompt}\"}], \"messages\": [${parameters._chat_history:-}{\"role\":\"user\",\"content\":[{\"text\":\"${parameters.prompt}\"}]}${parameters._interactions:-}]${parameters.tool_configs:-} }"
}
]
}
コネクタ ID をメモしておきます。これを使用してモデルを登録します。
ステップ 1.2: モデルの登録
POST /_plugins/_ml/models/_register
{
"name": "Bedrock Claude Sonnet model",
"function_name": "remote",
"description": "Bedrock Claude 3.7 sonnet model for Plan, Execute and Reflect Agent",
"connector_id": "your_connector_id"
}
モデル ID をメモしておきます。これを使用してエージェントを登録します。
ステップ 2: エージェントの登録
POST _plugins/_ml/agents/_register
{
"name": "My Plan Execute and Reflect agent with Claude 3.7",
"type": "plan_execute_and_reflect",
"description": "this is a test agent",
"llm": {
"model_id": "your_llm_model_id",
"parameters": {
"prompt": "${parameters.question}"
}},
"memory": {
"type": "conversation_index"
},
"parameters": {
"_llm_interface": "bedrock/converse/claude"
},
"tools": [
{
"type": "ListIndexTool"
},
{
"type": "SearchIndexTool"
},
{
"type": "IndexMappingTool"
}
],
}
エージェント ID をメモしておきます。これを使用してエージェントを実行します。
ステップ 3: エージェントの実行
OpenSearch 3.0 では、エージェントを非同期で実行する機能が導入されています。このエージェントは長時間実行されるため、async=true クエリパラメータを指定して非同期で実行しましょう:
POST /_plugins/_ml/agents/your_agent_id/_execute?async=true
{
"parameters": {
"question": "My users are complaining about the cart service. It is showing some unexpected behavior. When I click on empty cart it doesn't do anything. Can you investigate the root cause of this? There are spans and logs you can use to conduct your investigation."
}
}
OpenSearch はタスク情報で応答します:
{
"task_id": "waIQmJYBJr85UikuxTKC",
"status": "RUNNING",
"response": {
"memory_id": "v6IQmJYBJr85UikuxTJN"
}
}
タスク ID とメモリ ID をメモしておきます。タスク ID を使用して結果をクエリし、メモリ ID を使用してエージェントと LLM 間のやり取りを追跡します。
ステップ 4: 結果の分析
タスクのステータスを確認するために、tasks エンドポイントにクエリを実行しましょう:
GET _plugins/_ml/tasks/your_task_id
エージェントが実行を完了すると、次のような応答が返されます:
{
"task_type": "AGENT_EXECUTION",
"function_name": "AGENT",
"state": "COMPLETED",
"worker_node": [
"q5yAqa75RM-rv0I67V1VVQ"
],
"create_time": 1746148548710,
"last_update_time": 1746148706345,
"is_async": false,
"response": {
"memory_id": "bzWQjpYBKhItn1nNYHtu",
"inference_results": [
{
"output": [
{
"result": "bzWQjpYBKhItn1nNYHtu",
"name": "memory_id"
},
{
"result": "cDWQjpYBKhItn1nNYHuS",
"name": "parent_interaction_id"
},
{
"result": "dTWQjpYBKhItn1nNbHsw",
"name": "executor_agent_memory_id"
},
{
"result": "YjWQjpYBKhItn1nN6oYk",
"name": "executor_agent_parent_interaction_id"
},
{
"name": "response",
"dataAsMap": {
"response": """After a comprehensive investigation of the cart service issues, I have identified the root cause of the 'empty cart' functionality failure.
# Root Cause Analysis
## Problem Identification
Users reported that clicking on 'empty cart' doesn't do anything. This was confirmed through analysis of OpenTelemetry traces showing failures in the `/oteldemo.CartService/EmptyCart` gRPC method.
## Key Findings
1. **Redis Connection Failures**:
- Error message: \"Wasn't able to connect to redis\"
- Component: `cart.cartstore.ValkeyCartStore`
- Multiple occurrences between 15:56 and 16:00 on April 18, 2025
2. **EmptyCart Operation Failures**:
- Method: `/oteldemo.CartService/EmptyCart`
- Status Code: ERROR (2)
- Error Message: \"Error emptying cart\"
- HTTP Status Code: 500 (Internal Server Error)
- These failures occurred in the same time window as the Redis connection errors
3. **Correlation Evidence**:
- The timing of EmptyCart failures perfectly aligns with Redis connection errors
- All failures affect the same cart service instance (container ID: `2e6e7f69cca2`)
- Read operations (`GetCart`) sometimes succeeded while write operations (`EmptyCart`) consistently failed
## Conclusion
The root cause of the 'empty cart' functionality failure is a Redis connection issue in the cart service. The cart service uses Redis as its backend storage for maintaining cart state. When Redis becomes unavailable, the cart service can't perform write operations like emptying a cart.
Interestingly, some read operations (GetCart) were still succeeding, likely due to caching or different error handling for read vs. write operations, but all EmptyCart operations failed with a 500 error due to the inability to connect to Redis.
## Recommended Action
To resolve this issue:
1. Restore the Redis connection for the cart service
2. Investigate why the Redis connection was lost
3. Consider implementing better error handling in the cart service for Redis connection failures
4. Add better user feedback when backend operations fail"""
}
}
]
}
]
}
}
エージェントは、問題の根本原因が Redis 接続の問題であることを特定しています。サービスログとトレースに表示される Redis バックエンドへの接続失敗が繰り返し発生していることを強調し、ECONNREFUSED エラーを示す特定のログエントリへのリンクを提供しています。応答には、エージェントがトレースとログを分析して障害を特定した方法についてのステップバイステップの説明も含まれています。根本原因分析を自動化することで、エージェントは手動でのトラブルシューティングにかかる時間を効果的に削減し、複雑な問題を解決してチームが迅速に解決策を見つけられるようにする方法を示しています。
結果を検証するために、ログにクエリを実行してみましょう
GET ss4o_logs-*/_search
{
"size": 10,
"sort": [
{ "time": { "order": "desc" } }
],
"query": {
"bool": {
"must": [
{ "match": { "serviceName": "cart" } }
],
"should": [
{ "term": { "severityText.keyword": "Error" } },
{ "wildcard": { "body.keyword": "*Error*" } }
],
"minimum_should_match": 1
}
}
}
応答は明らかに Redis 接続の問題が根本原因であることを示しています
{
"_index": "ss4o_logs-2025.05.03",
"_id": "jKd4mJYBJr85Uiku-gbe",
"_score": null,
"_source": {
"traceId": "2d45e1cde4f8645b36ab31c07e2e67d6",
"spanId": "e29428cdfabb1c30",
"severityText": "Error",
"flags": 1,
"time": "2025-05-03T23:26:20.084598400Z",
"severityNumber": 17,
"droppedAttributesCount": 0,
"serviceName": "cart",
"body": "Wasn't able to connect to redis",
"observedTime": "2025-05-03T23:26:20.084598400Z",
"schemaUrl": "",
"instrumentationScope.name": "cart.cartstore.ValkeyCartStore",
"resource.attributes.service@version": "2.0.2",
"resource.attributes.telemetry@sdk@name": "opentelemetry",
"resource.attributes.telemetry@sdk@language": "dotnet",
"resource.attributes.host@name": "7cbfd02de5b9",
"resource.attributes.service@namespace": "opentelemetry-demo",
"resource.attributes.container@id": "7cbfd02de5b9886dcda65e9876ee4d9601c98b29efada503117f3ac187a3b81a",
"resource.attributes.telemetry@sdk@version": "1.11.2",
"resource.attributes.service@name": "cart"
}
},
{
"_index": "ss4o_logs-2025.05.03",
"_id": "nqd4mJYBJr85Uiku-gbe",
"_score": null,
"_source": {
"traceId": "2d45e1cde4f8645b36ab31c07e2e67d6",
"spanId": "e29428cdfabb1c30",
"severityText": "Information",
"flags": 1,
"time": "2025-05-03T23:26:20.084929Z",
"severityNumber": 9,
"droppedAttributesCount": 0,
"serviceName": "cart",
"body": "Error status code '{StatusCode}' with detail '{Detail}' raised.",
"observedTime": "2025-05-03T23:26:20.084929Z",
"schemaUrl": "",
"instrumentationScope.name": "Grpc.AspNetCore.Server.ServerCallHandler",
"log.attributes.Detail": """Can't access cart storage. System.ApplicationException: Wasn't able to connect to redis
at cart.cartstore.ValkeyCartStore.EnsureRedisConnected() in /usr/src/app/src/cartstore/ValkeyCartStore.cs:line 95
at cart.cartstore.ValkeyCartStore.EmptyCartAsync(String userId) in /usr/src/app/src/cartstore/ValkeyCartStore.cs:line 178""",
"resource.attributes.service@version": "2.0.2",
"resource.attributes.telemetry@sdk@name": "opentelemetry",
"resource.attributes.telemetry@sdk@language": "dotnet",
"resource.attributes.host@name": "7cbfd02de5b9",
"resource.attributes.service@namespace": "opentelemetry-demo",
"resource.attributes.container@id": "7cbfd02de5b9886dcda65e9876ee4d9601c98b29efada503117f3ac187a3b81a",
"resource.attributes.telemetry@sdk@version": "1.11.2",
"resource.attributes.service@name": "cart",
"log.attributes.StatusCode": "FailedPrecondition"
}
}
エージェントの登録と実行の詳細については、このチュートリアルを参照してください。
中間結果を確認したい場合は、メモリインデックスとメモリトレースをクエリして、エージェントと LLM 間のやり取りを理解できます
GET /_plugins/_ml/memory/message/your_message_id/traces
メモリとトレースの詳細については、Memory APIs を参照してください。
より多くのツールと MCP サポートによるエージェントの拡張
plan-execute-reflect エージェントの力はその柔軟性にあります。今回の例ではカート障害を調査するための基本的なツールセットを使用していますが、エージェントは幅広いツールをサポートできます。利用可能なツールのリストについては、Tools を参照してください。
そのような例の一つとして、WebSearchTool を使用して深い調査タスクを実行することが挙げられます。
さらに、このエージェントは MCP クライアントとして機能し、MCP サーバーに接続することができます。この機能により、エージェントはツールと設定を動的に取得し、より複雑なワークフローに参加することができます。
エージェントを MCP サーバーに接続する方法については、Connecting to an external MCP server を参照してください。
推奨事項とトラブルシューティング
- モデルがエージェントをスロットリングしていることに気づいた場合は、コネクタ設定を使用して再試行を有効にしてください。
- エージェントが max_steps ステップを実行した後に停止する場合は、max_steps 値を増やすか、実行時に parameters.max_steps フィールドで指定してください。
将来の拡張
plan-execute-reflect エージェントは現在、実験的な機能です。私たちは以下の潜在的な将来の拡張でそれを進化させ続ける計画です
- 並列ツール実行
- 複数のリフレクション戦略
- ヒューマンインザループ
- 実行中のタスクをキャンセルする機能
- エージェント実行チェックポイント
機能の進捗状況に関する更新や、フィードバックを残したい場合は、関連する GitHub issue を参照してください。
結論
このチュートリアルでは、plan-execute-reflect エージェントを使用して OpenTelemetry デモアプリケーションのカート障害の根本原因をトラブルシューティングし特定する方法を示しました。高レベルのタスクを小さなステップに分解し、それらを反復的に実行することで、エージェントは複雑な推論ワークフローを自動化するための強力で柔軟な方法を提供します。このアプローチは、多段階診断が必要な可観測性と運用インテリジェンスのユースケースに特に有用です。
plan-execute-reflect エージェントは、インテリジェントな自動化が根本原因分析をどのように簡素化できるかを示しています。OpenTelemetry の可観測性データと LLM ベースの推論を組み合わせることで、OpenSearch は単一のプロンプトだけで複雑なマルチサービスシステムのデバッグを支援できるようになりました。
自身の環境でも試してみたい場合は、このチュートリアルをチェックして、自分のスタックにエージェントをデプロイしてください。
Discussion