LLMアプリのTraceとSpanをMicrosoft Agent Frameworkで考える
LLMアプリやAIエージェントを見ていると、Trace と Span という言葉がよく出てくる。
Microsoft Agent FrameworkもOpenTelemetryベースのObservabilityに対応しており、Agent、LLM、Tool、Workflowなどの実行をTraceとして追跡できる。Microsoft Agent FrameworkのDevUIでも、Agent Frameworkが出力したOpenTelemetry Traceを表示できる。
チャットで考える
まず、チャット全体を Session と考える。
Session
├─ ユーザー質問1
├─ AI回答1
├─ ユーザー質問2
├─ AI回答2
└─ ...
その中の、
1回のユーザー入力から回答が返るまで
を1つの Trace と考えると分かりやすい。
User
「顧客Aの売上を調べて要約して」
↓
Trace
↓
Assistant
「売上は○○でした」
つまり、
Session
├─ Trace 1
├─ Trace 2
└─ Trace 3
となる。
Spanとは
Span はTraceを構成する個々の処理区間。
AgentがToolを使う場合なら、
Trace
├─ Span: Agent実行
│
├─ Span: LLM Call
│
├─ Span: Tool Call
│ └─ Span: MCP Request
│
├─ Span: LLM Call
│
└─ Span: 最終回答
という形になる。
Microsoft Agent FrameworkのTraceも、概念的には
Agent Execution
├─ LLM Call
├─ Tool Call
└─ LLM Call
のようなSpan階層として確認できる。
Spanを見ることで、
- どこに時間がかかったか
- どのToolを呼んだか
- どこで失敗したか
- 部分失敗だったのか
- どのAgentが実行されたか
などを確認できる。
Workflowではさらに細かく見える
Microsoft Agent FrameworkのWorkflowでは、Workflow全体だけでなく、
workflow.session
workflow_invoke
executor.process
edge_group.process
message.send
などのSpanが出力される。
workflow.session はWorkflow実行全体、executor.process は各Executorの処理、message.send はExecutor間のメッセージ送信を表す。
例えば、
Workflow
├─ Executor A
│ └─ Agent
│ ├─ LLM
│ └─ Tool
│
├─ message.send
│
└─ Executor B
└─ Agent
└─ LLM
という処理をTraceとして追える。
OpenTelemetry
Microsoft Agent FrameworkのObservabilityはOpenTelemetryを利用する。
.NETで見ると、OpenTelemetryのSpanはSystem.Diagnostics.Activityに対応する。つまり.NET側ではActivityとして処理を計測し、それをOpenTelemetry Traceとして外部の監視基盤へ送ることができる。
例えば、
Microsoft Agent Framework
↓
OpenTelemetry
↓
Azure Monitor
Jaeger
Zipkin
Datadog
など
という形で利用できる。Agent FrameworkのTraceは標準的なOpenTelemetry Traceとして外部ツールにもExportできる。
一言で言うと
Session = 会話全体
Trace = 1回の質問から回答までの処理全体
Span = その中の個々の処理
Agentアプリでは、
Agent
↓
LLM
↓
Tool
↓
MCP
↓
LLM
という複数の処理が連鎖する。
そのため単に「APIが成功したか」だけを見るのではなく、
どのAgentが動き、どのLLMを呼び、どのToolを実行し、どこで時間がかかり、どこで失敗したか
をTrace / Spanで見ることが重要になる。
Microsoft Agent Frameworkを使う場合も、このTrace / Spanの考え方を押さえておくと、AgentやWorkflowのデバッグ、性能監視、部分失敗の調査がかなり理解しやすくなる。
補足すると、Microsoft Agent FrameworkのWorkflowでは workflow.session と workflow_invoke が明確に分かれているので、「Session = 会話全体、Trace = 1往復」だけで完全に固定しない方が正確。この記事では理解しやすさを優先した説明にしている。