AI News HubLIVE
站内改写6 分で読了

Strands Evalsを使用したAIエージェントの障害検出と根本原因分析

本記事では、Strands Evals SDKの検出器がAIエージェントの実行トレースから障害を自動的に識別し、根本原因分析を行うことで、診断時間を数時間から数分に短縮する方法を紹介します。検出関数の呼び出し方、構造化出力(分類された障害、信頼度、因果連鎖、修正推奨事項)の解釈方法、および評価パイプラインへの統合方法について学びます。

ソースAWS Machine Learning Blog著者: Po-Shin Chen

AIエージェントが本番環境で障害を起こしたとき、障害が発生したことを知るのは始まりに過ぎません。より難しいのは、なぜ障害が発生したのか、何を修正すべきかを理解することです。従来の評価では「このエージェントは目標達成度で60%だった」と教えてくれますが、何が悪かったのかを理解するには手動で実行トレースをレビューする必要があります。エージェントを大規模に運用するチームにとって、この手動診断は問題を検出して修正をリリースするまでのボトルネックとなります。Strands Evals SDKの検出器は、エージェントの実行トレースから障害を自動的に識別し、根本原因分析を実行することで、このボトルネックを取り除き、診断時間を数時間から数分に短縮します。

この記事では、実際のエージェント障害を診断するために検出関数を呼び出す方法を説明します。構造化出力(カテゴリ化された障害、信頼度スコア、根本原因と下流症状を結び付ける因果連鎖、修正がシステムプロンプトとツール定義のどちらに属するかを指定する修正推奨事項)の解釈方法を学びます。また、検出を評価パイプラインに統合し、すべてのテスト実行で自動診断を実施する方法についても学びます。

検出器は、以前の記事で紹介した評価フレームワークを補完し、「エージェントはどの程度うまくやったか?」だけでなく、「なぜ失敗したのか、どう修正するか?」にも答えます。

前提条件

この記事を進めるには、以下の前提条件が必要です。Python 3.10以降、pip install strands-agents-evalsによるStrands Evals SDKのインストール、Amazon Bedrockモデルアクセスの有効化(検出器はLLMベースの分析を使用)、Amazon CloudWatchの例ではlogs:StartQueryとlogs:GetQueryResultsの権限を持つAWS認証情報の設定。

スコアだけでは不十分な理由

Strands Evalsフレームワークは、Cases、Experiments、Evaluatorsを通じて信頼性の高い品質シグナル(目標成功率、ツール選択精度、有用性スコア)を提供します。これらは回帰を捕捉し、統計レベルでパフォーマンスを理解するために重要です。しかし、回帰を検出した後に何が起こるかを考えてみてください。デプロイ後、またはビルド時テストでのプロンプトやツールの変更後に、エージェントの目標成功率が85%から70%に低下したとします。Evaluatorsが低下を確認しました。さて、どうしますか?

どの特定の動作が障害を引き起こしたかを特定し、根本原因と下流症状を区別し、修正がシステムプロンプトとツール定義のどちらに属するかを判断し、影響度で優先順位を付ける必要があります。この診断ワークフローは従来、上級エンジニアが手動でトレースをスパンごとに検査し、数百のステップにわたって障害を関連付ける必要があり、スケーラブルではありません。

検出器はこのワークフローを自動化します。Evaluatorsはケースレベルのスコアを生成して「エージェントはどの程度うまくやったか?」に答えます。検出器はスパンレベルの診断(カテゴリ化された障害、因果連鎖、修正推奨事項)を生成して「なぜ失敗したか?」に答えます。

検出器の仕組み

検出器パイプラインは2つのフェーズで動作し、各フェーズは実行トレースのLLMベースの分析によって駆動されます。Amazon Bedrock AgentCoreのエージェントリソースの可観測性を理解するを参照して、エージェントのセッション、トレース、スパンについて学んでください。

フェーズ1:障害検出は、セッション内の各スパンを包括的な障害分類法(9つの親カテゴリ:幻覚、誤ったアクション、オーケストレーションエラー、タスク指示違反、実行エラー、コンテキスト処理エラー、反復動作、LLM出力問題、設定ミスマッチ)に対してスキャンします。特定された障害ごとに、スパンの位置、1つ以上のカテゴリ、信頼度スコア、トレースから抽出された証拠を返します。

フェーズ2:根本原因分析は、検出された障害を取得し、それらの間の因果連鎖を追跡します。単一の上流ミスが複数の下流障害に連鎖することがよくあります。根本原因分析は原因と症状を分離します。各障害の因果関係(PRIMARY、SECONDARY、またはTERTIARY)を分類し、伝播の影響を判断し、修正が属する場所(システムプロンプト、ツール説明、その他)に基づいて修正推奨事項を生成します。

両フェーズは、階層的な戦略を通じてさまざまなサイズのセッションを処理します。選択された検出器モデルのコンテキストウィンドウに収まるセッションは直接分析、中程度の大きさのセッションでは障害パスプルーニング(祖先と子孫スパンのみ保持)、非常に大きなセッションではチャンク分析とマージ(トレースを重複ウィンドウに分割し結果を調整)を使用します。

次の図は、2つのエントリポイントが同じ検出および分析フローに合流するエンドツーエンドパイプラインを示しています。

[図:統合およびスタンドアロンのエントリポイントが障害検出と根本原因分析に流れ込む検出器パイプライン]

障害検出の開始

以下の例では、Evaluating AI agents for production: A practical guide to Strands Evalsで取り上げられた創薬研究アシスタントのセッショントレースを使用します。エージェントはStrands AgentsとAmazon Bedrock上に構築されています。手順を追うには、OpenTelemetryトレーシングを有効にしてエージェントを実行し、セッションをJSONとしてエクスポートするか、後で説明するCloudWatchProviderを使用して既存のトレースを取得します。トレースの設定とセッションのエクスポート方法については、Strands Agents SDKドキュメントのUser Simulationを参照してください。

detect_failures関数はSessionオブジェクト(Strands Evalsの標準トレース形式)を受け取り、構造化された障害を返します。各障害には、障害が発生したスパン、定義済み障害分類法からの1つ以上のカテゴリ、信頼度スコア、トレースから抽出された証拠が含まれます。

import json
from strands_evals.detectors import detect_failures
from strands_evals.types.trace import Session
from strands_evals.detectors import ConfidenceLevel

with open("agent_trace.json") as f:
    session = Session.model_validate_json(f.read())

result = detect_failures(session, confidence_threshold=ConfidenceLevel.MEDIUM)

for failure in result.failures:
    for cat, conf, ev in zip(failure.category, failure.confidence, failure.evidence):
        print(f"[{conf}] {cat} at span {failure.span_id}")
        print(f" Evidence: {ev}")

以下は、「現実世界でAIを動かすためのエネルギー要件の影響を調査して」と依頼された研究エージェントからの出力です。エージェントはツール設定の問題に直面し、徐々に劣化しました:

[0.9] execution-error-category-tool-schema at span f503a7d546fa4157
Evidence: Tool execution failed due to missing required parameter 'knowledgeBaseId'. Error: 'Parameter validation failed: Invalid type for parameter knowledgeBaseId, value: None'

[0.75] hallucination-category-hall-usage at span 0466979670d14099
Evidence: Agent claims 'I don't have access to the specific knowledge base needed' and then proceeds to provide detailed information about AI energy requirements 'based on general knowledge' without using any tools.

[0.9] orchestration-related-errors-category-goal-deviation at span d98d578e61233d33
Evidence: Agent completely abandons the original task about AI energy requirements and instead provides a lengthy response about marine biology, stating 'I'm going to pivot to discuss marine biology instead.'

1回のパスで、検出器は複数レベルの障害を識別します。実行エラー(ツールパラメータ検証)、セマンティックな問題(「一般的な知識」からの幻覚)、およびオーケストレーションの問題(完全な目標逸脱)です。1つのスパンが複数の障害カテゴリを示す可能性があり、各カテゴリには独立した信頼度と証拠があります。

根本原因分析の追加

障害を特定することは有用ですが、なぜ発生したかを理解することが修正につながります。analyze_root_cause関数は検出された障害を取得し、それらの間の因果連鎖を追跡し、根本原因と下流症状を分離し、各修正が属する場所を推奨します。analyze_root_causeに障害が提供されない場合、自動的に障害検出を実行します。

from strands_evals.detectors import detect_failures, analyze_root_cause

failures = detect_failures(session)
rca_result = analyze_root_cause(session, failures=failures.failures)

for rc in rca_result.root_causes:
    print(f"Causality: {rc.causality}")
    print(f" Span: {rc.failure_span_id} | Fix type: {rc.fix_type}")
    print(f" Root cause: {rc.root_cause_explanation}")
    print(f" Recommendation: {rc.fix_recommendation}")

同じ研究エージェントのセッションを続けると、根本原因分析が因果構造を明らかにします:

Causality: PRIMARY_FAILURE
Span: f503a7d546fa4157 | Fix type: TOOL_DESCRIPTION_FIX
Root cause: Agent called retrieve tool without required knowledgeBaseId parameter because tool description does not clearly document that knowledgeBaseId is mandatory. This caused parameter validation failure and forced agent into multiple retry attempts with different parameter combinations.
Recommendation: Update retrieve tool description to explicitly mark knowledgeBaseId as a required parameter with clear documentation including format constraints and example values.

Causality: SECONDARY_FAILURE
Span: 0466979670d14099 | Fix type: SYSTEM_PROMPT_FIX
Root cause: Agent fabricated detailed AI energy consumption information claiming it is 'based on general knowledge' after all retrieval attempts failed, because system prompt lacks instruction prohibiting generation of factual content without tool-retrieved evidence.
Recommendation: Add instruction to system prompt requiring agent to explicitly acknowledge inability to complete research tasks when retrieval tools fail, and prohibit generating detailed factual content without tool-verified sources.

修正タイプの区別により、根本原因分析が実用的になります。ツールスキーマエラーはTOOL_DESCRIPTION_FIXです。なぜなら、retrieveツールのknowledgeBaseIdが明確に文書化されていないからです。下流の幻覚はSYSTEM_PROMPT_FIXです。なぜなら、持続的なツール障害の処理方法に関する指示が欠けているからです。一方のカテゴリだけを修正しても、もう一方は未対応のままです。

統合診断:diagnose_session

便宜上、diagnose_sessionは両方のフェーズを単一のパイプラインとして実行し(障害を検出し、次に根本原因を分析)、重複排除された推奨事項を含む統一されたDiagnosisResultを返します:

from strands_evals.detectors import diagnose_session, ConfidenceLevel

result = diagnose_session(session, confidence_threshold=ConfidenceLevel.MEDIUM)
print(f"Found {len(result.failures)} failures, {len(result.root_causes)} root causes")

for rec in result.recommendations:
    print(f" - {rec}")

これにより、前の例と同じ障害と根本原因が生成され、すべての根本原因にわたって推奨事項が重複排除されて1つの結果にパッケージ化されます。1つの関数呼び出しから、修正が属する場所によって分類された具体的な変更の優先順位リストが得られます。

評価パイプラインとの統合

検出器は、既存の評価ワークフローに統合するとさらに価値が高まります。DiagnosisConfigは自動診断を任意の実験にアタッチし、失敗した各テストケースが自動的に診断を生成するようにします:

from strands_evals import Experiment
from strands_evals.evaluators import GoalSuccessRateEvaluator
from strands_evals.detectors import ConfidenceLevel, DiagnosisConfig, DiagnosisTrigger
from strands_evals.types.evaluation_report import EvaluationReport

experiment = Experiment(
    cases=test_cases,
    task_function=my_agent_task,
    evaluators=[GoalSuccessRateEvaluator()],
    diagnosis_config=DiagnosisConfig(
        trigger=DiagnosisTrigger.ON_FAILURE,
        confidence_threshold=ConfidenceLevel.MEDIUM
    ),
)

report = experiment.run()
report.display(include_recommendations=True)

2つのトリガーモードが利用可能です。ON_FAILURE(デフォルト)は、少なくとも1つのEvaluatorがtest_pass=Falseを返した場合にのみ診断を実行するため、CI/CD回帰検出においてコスト効率が高くなります。ALWAYSは結果に関係なくすべてのケースで診断を実行し、名目上合格しているケースの最適ではないパスを特定するのに役立ちます。