エージェントの観測可能性がエージェント評価を強化
LangChain Blogは、従来のソフトウェア観測とは異なり、不確実性が高く複雑な推論プロセスを持つAIエージェントの動作を把握する「エージェント観測」の重要性と、トレースに基づく評価手法の必要性について解説している。
キーポイント
デバッグ対象のシフト
従来のコードエラーではなく、エージェントの「推論プロセス」自体がデバッグの対象となり、スタックトレースに代わってトレースデータが真のソースとなる。
決定論から確率的へ
LLMアプリやエージェントは入力に対して常に同じ出力を保証せず、ループ内の複数ステップやツール呼び出しを含む不確実な振る舞いをするため、従来の観測手法では対応できない。
トレースと評価の融合
エージェントがどのような判断で特定の行動(例:edit_fileの呼び出し)を取ったかという文脈を記録するトレースは、エージェントの評価(Evaluation)において不可欠な基盤となる。
エージェント評価は推論のテストである
従来のソフトウェアテストが決定論的なコードパスを検証するのに対し、エージェント評価は単一ステップ、完全ターン、マルチターンといった粒度で「推論」そのものをテストする必要がある。
プロダクションが主要な教師となる
自然言語入力が多様であるため、プロダクション環境での実データこそが予測不可能な失敗モードや「正しい動作」の定義を発見する場となり、オフラインテストケースの源泉となる。
エージェント可観測性の3つの基本概念
エージェントの非決定論的な推論を捉えるために、「Runs(単一実行ステップ)」「Traces(一連の実行履歴)」「Threads(マルチターン会話)」という3つの基本概念を用いる。
エージェントトレースの規模と内容
エージェントトレースは単一の実行を記録し、モデルへの入力、ツール呼び出しの結果、およびステップ間の階層構造を含みます。複雑なエージェントの場合、数百メガバイトに及ぶ巨大なデータとなり、デバッグと評価に必要なコンテキストを提供します。
影響分析・編集コメントを表示
影響分析
この記事は、AIエージェントの実装と運用におけるパラダイムシフトを明確に示しており、開発者に対して「コードのデバッグ」から「推論プロセスの可視化と評価」への思考転換を求めている。LangChainという主要フレームワークの公式ブログであるため、業界標準としての「エージェント観測」の重要性を定着させる重要な示唆となり、実務における評価指標やツールの選定基準に直接影響を与える可能性が高い。
編集コメント
エージェントのブラックボックス化が進む中で、その内部動作を可視化する「観測」が評価の前提となるという指摘は極めて妥当です。開発現場では、単なるログ出力ではなく、推論の文脈を捉えるための専用ツール導入が急務となります。
エージェントの評価を支えるエージェントの可観測性
エージェントが実際に動作するまで、それが何をするかはわかりません。これは、エージェントの可観測性がソフトウェアの可観測性とは異なり、より重要であることを意味します。
エージェントはしばしば複雑で、答えが一つに定まらないタスクを実行します。これは、エージェントの評価がソフトウェアの評価とは異なることを意味します。
トレースはエージェントの振る舞いがどのように生じたかを記録するため、評価をさまざまな形で支える力となります。
従来のソフトウェアで何か問題が発生したとき、あなたは何をすべきかわかっています。エラーログを確認し、スタックトレースを見て、失敗したコードの行を見つけるのです。しかし、AIエージェントは私たちがデバッグする対象を変えました。エージェントがタスクを完了するために2分間に200ステップを実行し、その過程のどこかでミスを犯した場合、それは別種のエラーです。スタックトレースはありません。なぜなら、失敗したコードがないからです。失敗したのは、エージェントの推論なのです。
コードのデバッグから推論のデバッグへ
エージェントを定義するコード(例えば、どのツールが存在するか、どのデータが利用可能か)は依然として書きます。エージェントの振る舞いを導くためにプロンプトやツールの説明を書きますが、LLMがこれらの指示をどのように解釈するかは、実際に実行するまでわかりません。したがって、真実の源はコードから、エージェントが実際に何をしたかを示すトレースへと移行します。
エージェントエンジニアリングは反復的なプロセスであり、トレーシングと評価はそのループを閉じる方法です。この記事では、なぜエージェントの可観測性と評価が従来のソフトウェアと根本的に異なるのか、どのような新しいプリミティブと実践が必要なのか、そして可観測性がいかにして評価を支え、それらを不可分なものにするのかを探ります。
エージェントの可観測性 ≠ ソフトウェアの可観測性
LLM以前のソフトウェアは、大部分が決定的でした。同じ入力に対して、同じ出力が得られます。ロジックはコード化されていました。コードを読めば、システムがどのように振る舞うか正確に知ることができました。何か問題が起きたとき、ログはどのサービスや関数が失敗したかを示し、その後、コードに戻ってなぜそれが起きたかを理解し、修正することができました。
AIエージェントは、決定性とコードを真実の源とする前提を打ち破ります。従来のソフトウェアからLLMアプリケーション、そしてエージェントへと移行するにつれ、各ステップでより多くの不確実性が導入されます。LLMアプリケーションは、コンテキストと共にLLMに対して単一の呼び出しを行い、自然言語に内在する「曖昧さ」を導入しますが、一つのLLM呼び出しに制限されたままです。
しかし、エージェントは、タスクが完了したと判断するまで、ループ内でLLMとツールを呼び出し続けます。数十または数百のステップにわたって推論を行い、ツールを呼び出し、状態を維持し、コンテキストに基づいて振る舞いを適応させることができます。エージェントを構築するとき、あなたはコードとプロンプトでアプリケーションロジックを規定しようと試みます。しかし、実際にLLMを実行するまで、このロジックが何をするかはわかりません。
何か問題が起きたとき、あなたは失敗した単一のコード行を見つけるのではなく、以下のような問いを立てることになります:
なぜエージェントはedit_fileを呼び出すと決めたのか?
その決定に影響を与えたコンテキストとプロンプトの指示は何か?
この2分間、200ステップの軌跡のどこでエージェントは道を外れたのか?
従来のトレーシングツールはこれらの質問に答えることができません。200ステップのトレースは人間が解析するには大きすぎます。また、従来のトレースは各決定の背後にある推論のコンテキストを捉えません。それらは、どのサービスが呼び出され、それぞれにどれだけ時間がかかったかだけを記録します。
エージェントの評価 ≠ ソフトウェアの評価
従来のソフトウェアテストは、決定的なアサーションに依存します: 出力 == 期待される出力 をチェックするテストを書きます。
1. コードパスではなく、推論をテストする
従来のソフトウェアには、さまざまな粒度(単体、結合、E2E)のテストがあり、読み取り修正可能な決定的なコードパスをテストします。エージェントも異なるレベルでのテストが必要ですが、もはやコードパスをテストしているのではありません。あなたは推論をテストしているのです:
- 単一ステップ: この瞬間にエージェントは正しい決定をしたか?
- 完全実行: エージェントはエンドツーエンドの実行で良好なパフォーマンスを発揮したか?
- マルチターン: エージェントは会話全体でコンテキストを維持したか?
2. 本番環境があなたの主要な教師となる
従来のソフトウェアでは、オフラインテスト(単体テスト、結合テスト、ステージング環境)でほとんどの正確性の問題を捕捉できます。カナリアデプロイや機能フラグを通じて本番環境でもテストは行いますが、その目的は見逃したエッジケースや統合問題を捕捉することです。
エージェントにおいて、本番環境は異なる役割を果たします。すべての自然言語入力はユニークであるため、ユーザーがどのようにリクエストを表現するか、どのようなエッジケースが存在するかを予測することはできません。本番環境のトレースは、予測できなかった失敗モードを明らかにし、実際のユーザーインタラクションにおいて「正しい振る舞い」が実際にどのようなものかを理解するのに役立ちます。
これは評価の考え方を変えます。本番環境は、見逃したバグを捕捉するだけの場所ではなく、オフラインで何をテストすべきかを発見する場所になります。本番環境のトレースはテストケースとなり、あなたの評価スイートは、単に設計されたシナリオだけでなく、実世界の例から継続的に成長していきます。
エージェント可観測性のプリミティブ
エージェントの可観測性は、非決定的な推論を捉えるために3つのコアプリミティブを使用します:
- 実行 (Runs): 単一の実行ステップ(入力/出力を含む1回のLLM呼び出し)
- トレース (Traces): すべての実行とそれらの関係を示す完全なエージェント実行
- スレッド (Threads): 時間を跨いだ複数のトレースをグループ化したマルチターン会話
これらは従来の可観測性(例: トレース、スパン)と同じ概念を使用しますが、サービス呼び出しとタイミングではなく、推論のコンテキストを捉えます。
実行: 単一ステップでLLMが何をしたかを捉える
実行 (Run) は、単一の実行ステップを捉えます。これは、特定の時点でLLMがどのように振る舞ったかを捉えるのに最も有用です。これには、すべての指示、使用されたツール、コンテキストを含む、LLM呼び出しの完全なプロンプトが記録されます。
これらの実行は二重の目的に役立ちます:
- デバッグ用: 任意のステップでエージェントが正確に何を考えていたかを確認する。プロンプトには何が含まれていたか? どのツールが利用可能だったか? なぜこのアクションを選択したのか?
- 評価用: この実行に対してアサーションを書く。エージェントは正しいツールを、正しい引数で呼び出したか?
トレース: 軌跡を捉える
トレース (Trace) は、発生したすべての実行をリンクさせることで、完全なエージェント実行を捉えます。推論トレースは以下を捉えます:
- 各ステップでモデルに入力されるすべての情報(トレースを構成する実行として記録)
- 引数と結果を含むすべてのツール呼び出し
- ステップ間の関係を示すネスト構造
エージェントのトレースは膨大です。典型的な分散トレースが数百バイトであるのに対し、エージェントのトレースは桁違いに大きくなる可能性があります。複雑で長時間実行されるエージェントの場合、トレースは数百メガバイトに達することもあります。このコンテキストは、エージェントの推論をデバッグし評価するために必要です。
スレッド: マルチターン会話のコンテキスト
単一のトレースは1回のエージェント実行を捉えますが、エージェントはユーザーやシステムとの複数のインタラクションを含むセッションを跨いで動作することがよくあります。スレッド (Thread) は、複数のエージェント実行(トレース)を単一の会話セッションにグループ化し、以下を保持します:
- マルチターンコンテキスト: ユーザーとエージェント間のすべてのインタラクションを時系列順に
- 状態の進化: エージェントのメモリ、ファイル、または他の成果物がターン間でどのように変化したか
- 時間スパン: 会話は数分、数時間、または数日続く可能性がある
10ターンは正常に動作したが、11ターン目で突然ミスをし始めたコーディングエージェントのデバッグを考えてみてください。単独の11ターン目のトレースは、エージェントが妥当なツールを呼び出しているように見えるかもしれません。しかし、完全なスレッドを調べると、6ターン目でエージェントが誤った仮定で自身のメモリを更新し、11ターン目までにその悪いコンテキストが積み重なってバグのある振る舞いになったことがわかります。
スレッドは、エージェントの振る舞いが時間とともにどのように進化し、コンテキストがインタラクションを跨いでどのように蓄積(または劣化)するかを理解するために不可欠です。
これがエージェント評価に与える影響
エージェントの振る舞いは実行時にのみ現れ、可観測性(実行、トレース、スレッド)によってのみ捉えられます。これは、振る舞いを評価するためには、可観測性データを評価する必要があることを意味します。これにより、2つの重要な疑問が生じます:
エージェントをどの粒度で評価するか? 実行レベル、トレースレベル、それともスレッドレベルか?
いつエージェントを評価するか? 振る舞いがエージェントを実行したときにのみ現れるなら、オフラインで評価することはできるのか?
原文を表示
You don't know what your agents will do until you actually run them — which means agent observability is different and more important than software observability
Agents often do complex, open-ended tasks, which means evaluating them is different than evaluating software
Because traces document where agent behavior emerges, they power evaluation in a multitude of ways
When something goes wrong in traditional software, you know what to do: check the error logs, look at the stack trace, find the line of code that failed. But AI agents have changed what we're debugging. When an agent takes 200 steps over two minutes to complete a task and makes a mistake somewhere along the way, that’s a different type of error. There’s no stack trace - because there’s no code that failed. What failed was the agent’s reasoning.
From debugging code to debugging reasoning
You still write code to define your agent, e.g. which tools exist, what data is available. You write prompts and tool descriptions to guide the agent's behavior, but you won't know how the LLM will interpret these instructions until you run it. The source of truth thus shifts from code to traces that show what the agent actually did.
Agent engineering is an iterative process, and tracing + evaluation are how you close the loop. In this post, we'll explore why agent observability and evaluation are fundamentally different from traditional software, what new primitives and practices you need, and how observability powers evaluation in ways that make them inseparable.
Agent observability ≠ software observability
Pre-LLMs, software was largely deterministic — given the same input, you'd get the same output. Logic was codified. You could read the code and know exactly how the system behaved. When something went wrong, logs pointed you to which service or function failed, then you'd go back to the code to understand why it happened and fix it.
AI agents break the assumptions of determinism and code as a source of truth. As we're moving from traditional software to LLM applications to agents, each step introduces more uncertainty. LLM apps make a single call to an LLM with context, introducing natural language's inherent "fuzziness" but remain constrained to one LLM call.
However, agents call LLMs and tools in a loop until they determine a task is done — and can reason across dozens or hundreds of steps, calling tools, maintaining state, and adapting behavior based on context. When building an agent, you attempt to recommend the application logic in code and prompts. But you don't know what this logic will do until actually running the LLM.
When something goes wrong, you're not finding a single line of code that failed. Instead, you're asking:
Why did the agent decide to call edit_file
What context and prompt instructions informed that decision?
Where in this two-minute, 200-step trajectory did the agent go off track?
Traditional tracing tools can't answer these questions. A 200-step trace is too large for a human to parse, and traditional traces don't capture the reasoning context behind each decision; they only capture which services were called and how long each took.
Agent evaluation ≠ software evaluation
Traditional software testing relies on deterministic assertions: write tests that check output == expected_output
- You're testing reasoning, not code paths
Traditional software has tests at different levels of granularity (unit, integration, e2e), testing deterministic code paths you can read and modify. Agents also need testing at different levels, but you're no longer testing code paths — you're testing reasoning:
Single-step: Did the agent make the right decision at this moment?
Full-turn: Did the agent perform well in an end-to-end execution?
Multi-turn: Did the agent maintain context across a conversation?
- Production becomes your primary teacher
In traditional software, you can catch most correctness issues with offline tests (unit tests, integration tests, staging). You still test in production through canary deployments and feature flags, but the goal is to catch edge cases and integration issues you missed.
With agents, production plays a different role. Because every natural language input is unique, you can't anticipate how users will phrase requests or what edge cases exist. Production traces reveal failure modes you couldn't have predicted and help you understand what "correct behavior" actually looks like for real user interactions.
This shifts how you think about evaluation: production isn't just where you catch missed bugs. It's where you discover what to test for offline. Production traces become test cases, and your evaluation suite grows continuously from real-world examples, not just engineered scenarios.
The primitives of agent observability
Agent observability uses three core primitives to capture non-deterministic reasoning:
Runs: A single execution step (one LLM call with its input/output)
Traces: A complete agent execution showing all runs and their relationships
Threads: Multi-turn conversations grouping multiple traces over time
These use the same concepts as traditional observability (e.g. traces, spans) but capture reasoning context rather than service calls and timing
Runs: capturing what the LLM did at a single step
A run captures a single execution step. This is most useful for capturing how the LLM behaved at a particular point in time. This captures the complete prompt for an LLM call, including all instructions, tools used, and context.
These runs serve dual purposes:
For debugging: See exactly what the agent was thinking at any step. What was in the prompt? What tools were available? Why did it choose this action?
For evaluation: Write assertions against this run. Did the agent call the right tool? With the right arguments?
Traces: capturing trajectories
A trace captures a complete agent execution by linking together all the runs that occurred. A reasoning trace captures:
All information about what goes into the model at each step, captured as runs that make up the trace
All tool calls with their arguments and results
The nested structure showing how steps relate to each other
Agent traces are massive. While a typical distributed trace might be a few hundred bytes, agent traces can be orders of magnitude larger. For complex, long-running agents, traces can reach hundreds of megabytes. This context is necessary for debugging and evaluating the agent's reasoning.
Threads: multi-turn conversation context
A single trace captures one agent execution, but agents often operate across sessions involving multiple interactions with a user or system. A thread groups multiple agent executions (traces) into a single conversational session, preserving:
Multi-turn context: All interactions between user and agent in chronological order
State evolution: How the agent's memory, files, or other artifacts changed across turns
Time span: Conversations can last minutes, hours, or days
Consider debugging a coding agent that worked fine for 10 turns but suddenly started making mistakes in turn 11. The turn 11 trace in isolation might show the agent calling a reasonable tool. But when you examine the full thread, you discover that in turn 6 the agent updated its memory with an incorrect assumption, and by turn 11 that bad context had compounded into buggy behavior.
Threads are essential for understanding how agent behavior evolves over time and how context accumulates (or degrades) across interactions.
How this influences agent evaluation
Agent behavior only emerges at runtime, and is only captured by observability (runs, traces, and threads). This means that to evaluate behavior you need to evaluate your observability data. This raises two key questions:
At what granularity do you evaluate agents? At the run, trace, or thread level?
When do you evaluate agents? If behavior only emerges when you run the agents, can you evaluate them offline in the same way you do software?
Evaluations agents at different levels of granularity
You can evaluate agents at different levels of granularity, which map 1:1 to the observability primitives. What you're evaluating determines which primitive you need:
Single-step evaluation validates individual runs → Did the agent make the right decision at a specific step?
Full-turn evaluation validates complete traces → Did the agent execute the full task correctly?
Multi-turn evaluation validates threads → Did the agent maintain context across a conversation?
Single-step evaluation: unit tests for decisions
Sometimes, you need to validate a specific decision point without running the entire agent. You may want to see if the agent choose the right tool in a specific scenario, or whether it used the correct arguments.
This is like a unit test for agent reasoning: set up a specific state (conversation history, available tools, current task), run the agent for one step, and assert that it made the right decision. Single-step evaluation validates runs, i.e. individual LLM calls.
Example: Testing a calendar agent's tool selection
A scheduling agent needs to find available meeting times before scheduling. You want to verify it checks availability first rather than immediately trying to create the meeting:
Your single-step test:
Setup state: Conversation history = user said "Schedule a meeting with Harrison tomorrow morning", available tools = [find_meeting_times
schedule_meeting
Run one step: Agent generates next action
Assert: Agent chose find_meeting_times
schedule_meeting
Why you need runs: Single step tests often come from real production cases that error. In order to recreate these, you need the exact state of the agent before that step. Detailed run captures are the only way to get this!
Single-step evaluations are efficient and catch regressions at individual decision points. In practice, about half of agent test suites use these single-step tests to isolate and validate specific reasoning behaviors without the overhead of full agent execution.
- Full-turn evaluation: end-to-end trajectory assessment
Other times, you need to see a complete agent execution. Full-turn evaluation validates traces, i.e. complete agent executions with all their runs, and let you test multiple dimensions:
Trajectory: Did the agent call the necessary tools? For a coding agent fixing a bug, you might assert: "The agent should have called read_file
Final response: Was the output correct and helpful? For open-ended tasks like research or coding, the quality of the final answer often matters more than the specific path taken.
State changes: Did the agent create the right artifacts? For a coding agent, you'd inspect the files it wrote and verify they contain the correct code. For an agent with memory, you'd check that it stored the right information.
Testing that an agent remembers user preferences also requires validating three things:
Trajectory: Did the agent call edit_file
Final response: Did the agent confirm the update to the user?
State: Does the memory file actually contain the preference?
Each assertion requires different parts of the trace. You can't evaluate these dimensions without capturing the full trajectory and state changes.
- Multi-turn evaluation: realistic conversation flows
Some agent behaviors only emerge over multiple turns. The agent might maintain context correctly for 5 turns but fail on turn 6, or handle individual requests fine but struggle when requests build on each other.
Multi-turn evaluation validates threads, i.e. conversational sessions with multiple agent executions. You test whether the agent accumulates context correctly, maintains state across turns, and handles conversational flows that build on previous exchanges.
For example, testing context persistence:
Turn 1: User shares a preference ("I prefer Python over JavaScript")
Turn 2: User asks a question building on that ("Show me an exam
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み