massgen-log-analyzer について
MassGen の実験実行とログ・トレース分析を支援するスキルです。マルチエージェントの挙動や性能を調べる開発者向けで、ローカルログや Logfire から Markdown レポートを作成できます。
主な機能
- 01MassGen 実験の実行と監視
- 02ローカルログと Logfire トレースの分析
- 03エージェントの挙動と連携の確認
- 04ボトルネックと例外の特定
- 05Markdown 分析レポートの生成
活用シーン
- 01エージェントの再試行や失敗の調査
- 02実験ターン間の所要時間の比較
- 03ツール呼び出しや投票判断の確認
MCP 対応
オプションで Logfire MCP サーバーを利用し、トレースのクエリ、例外の検索、トレースリンクの作成を行えます。未設定の場合はローカルログのみを分析します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ massgen/ massgen --skill massgen-log-analyzerインストール後、Claude Code で/massgen-log-analyzerを入力して読み込まれたか確認します。
詳細
MassGen ログアナライザー
このスキルでは、MassGen の実験を実行し、Logfire を使用して生成されたトレースとログを分析するための、構造化されたワークフローを提供します。
目的
ログアナライザースキルを使用すると、次のことができます。
- 適切な計装を行って MassGen の実験を実行する
- トレースを階層的にクエリして分析する
- エージェントの動作と連携パターンをデバッグする
- パフォーマンスを測定し、ボトルネックを特定する
- ログ構造自体を改善する
- ログディレクトリに保存する Markdown 分析レポートを生成する
CLI クイックリファレンス
massgen logs CLI を使用すると、ログ分析にすばやくアクセスできます。
分析ステータス付きでログを一覧表示
uv run massgen logs list # Show all recent logs with analysis status
uv run massgen logs list --analyzed # Only logs with ANALYSIS_REPORT.md
uv run massgen logs list --unanalyzed # Only logs needing analysis
uv run massgen logs list --limit 20 # Show more logs
分析プロンプトを生成
# Run from within your coding CLI (e.g., Claude Code) so it sees output
uv run massgen logs analyze # Analyze latest turn of latest log
uv run massgen logs analyze --log-dir PATH # Analyze specific log
uv run massgen logs analyze --turn 1 # Analyze specific turn
プロンプトの出力は、指定したログディレクトリにこのスキルを使用するよう、コーディング CLI に指示します。
マルチエージェントによる自己分析
uv run massgen logs analyze --mode self # Run 3-agent analysis team (prompts if report exists)
uv run massgen logs analyze --mode self --force # Overwrite existing report without prompting
uv run massgen logs analyze --mode self --turn 2 # Analyze specific turn
uv run massgen logs analyze --mode self --config PATH # Use custom config
自己分析モードでは、複数のエージェントで MassGen を実行し、さまざまな観点(正確性、効率、動作)からログを分析して、統合された ANALYSIS_REPORT.md を生成します。
マルチターンセッション
MassGen のログディレクトリでは、複数のターン(連携セッション)がサポートされています。各ターンには turn_N/ ディレクトリがあり、その中に試行が格納されます。
log_YYYYMMDD_HHMMSS/
├── turn_1/ # First coordination session
│ ├── ANALYSIS_REPORT.md # Report for turn 1
│ ├── attempt_1/ # First attempt
│ └── attempt_2/ # Retry if orchestration restarted
├── turn_2/ # Second coordination session (if multi-turn)
│ ├── ANALYSIS_REPORT.md # Report for turn 2
│ └── attempt_1/
分析時に --turn フラグを指定すると、分析対象のターンを指定できます。指定しない場合は、最新のターンが分析されます。
Logfire とローカルログの使い分け
ローカルログファイルを使用する場合:
- コマンドのパターンや繰り返しを分析するとき(コマンドは
streaming_debug.logに記録されています) - 詳細なツール引数と出力を確認するとき(
coordination_events.json) - 投票理由やエージェントの判断を読むとき(
agent_*/*/vote.json) - 調整フローの表を表示するとき(
coordination_table.txt) - コスト/トークンの概要を確認するとき(
metrics_summary.json)
Logfire を使用する場合:
- ミリ秒単位の精度で正確なタイミングデータが必要な場合
- スパンの階層や親子関係を分析する場合
- 例外やエラーのスタックトレースを見つける場合
- 共同作業用に共有可能なトレースリンクを作成する場合
- 複数のセッションを横断してクエリを実行する場合(例:「エラーが発生したすべてのセッションを見つける」)
- 実行中の実験をリアルタイムで監視する場合
レート制限: Logfire がレート制限エラーを返した場合は、ローカルログに切り替えるのではなく、最大 60 秒待ってから再試行してください。レート制限はすぐにリセットされます。タイミング/階層の分析が必要な場合は、Logfire のデータを待つ価値があります。
主なローカルログファイル:
| ファイル | 内容 |
|---|---|
status.json | エージェントの信頼性メトリクス(強制イベント、バッファ損失)を含むリアルタイムのステータス |
metrics_summary.json | コスト、トークン、ツールの統計、ラウンド履歴 |
coordination_events.json | ツール呼び出しを含む完全なイベントタイムライン |
coordination_table.txt | 人が読みやすい調整フロー |
streaming_debug.log | コマンド文字列を含む生のストリーミングデータ |
agent_*/*/vote.json | 投票理由とコンテキスト |
agent_*/*/execution_trace.md | 完全なツール呼び出し、引数、結果、推論 — デバッグに非常に役立ちます |
execution_metadata.yaml | 設定とセッションのメタデータ |
実行トレース(execution_trace.md):
これらは最も詳細なデバッグ成果物です。各エージェントのスナップショットには、次の内容を含む実行トレースがあります。
- 完全な引数を含むツール呼び出し(省略なし)
- ツールの完全な結果(省略なし)
- モデルによる推論/思考ブロック
- タイムスタンプとラウンドマーカー
エージェントが何を行い、なぜそうしたのかを正確に把握する必要がある場合は、実行トレースを使用してください。回答/投票の反復中にエージェントが見たもの、生成したものがすべて記録されています。
強制の信頼性(status.json):
status.json ファイルには、ワークフローの強制イベントを追跡するエージェントごとの信頼性メトリクスが含まれています。
{
"agents": {
"agent_a": {
"reliability": {
"enforcement_attempts": [
{
"round": 0,
"attempt": 1,
"max_attempts": 3,
"reason": "no_workflow_tool",
"tool_calls": ["search", "read_file"],
"error_message": "Must use workflow tools",
"buffer_preview": "First 500 chars of lost content...",
"buffer_chars": 1500,
"timestamp": 1736683468.123
}
],
"by_round": {"0": {"count": 2, "reasons": ["no_workflow_tool", "invalid_vote_id"]}},
"unknown_tools": ["execute_command"],
"workflow_errors": ["invalid_vote_id"],
"total_enforcement_retries": 2,
"total_buffer_chars_lost": 3000,
"outcome": "ok"
}
}
}
}
強制理由コード:
| 理由 | 説明 |
|---|---|
no_workflow_tool | エージェントはツールを呼び出しましたが、vote も new_answer も呼び出しませんでした |
no_tool_calls | エージェントはテキストのみの応答を返し、ツールを呼び出しませんでした |
invalid_vote_id | エージェントは存在しないエージェント ID に投票しました |
vote_no_answers | エージェントは回答がない状態で投票しようとしました |
vote_and_answer | エージェントは同じ応答内で vote と new_answer の両方を使用しました |
answer_limit | エージェントは回答数の上限に達しました |
answer_novelty | 回答が既存の回答と類似しすぎています |
answer_duplicate | 既存の回答と完全に重複しています |
api_error | API/ストリーミングエラー(例:「peer closed connection」) |
connection_recovery | API ストリームが早期に終了し、保持されたコンテキストで復旧しました |
mcp_disconnected | MCP サーバーがセッション中に切断されました(例:「Server 'X' not connected」) |
このデータは、エージェントが再試行を必要とした理由や、強制による再起動でどれだけのコンテンツが失われたかを把握するのに非常に役立ちます。
Logfire のセットアップ
このスキルを使用する前に、可観測性のために Logfire をセットアップする必要があります。
ステップ 1:可観測性サポート付きで MassGen をインストールする
pip install "massgen[observability]"
# Or with uv
uv pip install "massgen[observability]"
ステップ 2:Logfire アカウントを作成する
https://logfire.pydantic.dev/ にアクセスし、無料アカウントを作成します。
ステップ 3:Logfire で認証する
# This creates ~/.logfire/credentials.json
uv run logfire auth
# Or set the token directly as an environment variable
export LOGFIRE_TOKEN=your_token_here
ステップ 4:MCP サーバー用の読み取りトークンを取得する
- https://logfire.pydantic.dev/ にアクセスしてログインします
- プロジェクトの設定に移動します
- 読み取りトークンを作成します(これは認証に使用する書き込みトークンとは異なります)
- ステップ 5 で使用するトークンをコピーします
ステップ 5:Logfire MCP サーバーを追加する
claude mcp add logfire -e LOGFIRE_READ_TOKEN="your-read-token-here" -- uvx logfire-mcp@latest
その後、Claude Code を再起動し、このスキルを再度呼び出します。
前提条件
Logfire MCP サーバー(任意ですが推奨):
Logfire MCP サーバーを使用すると、正確なタイミングデータとセッションをまたいだクエリにより、分析を強化できます。LOGFIRE_READ_TOKEN が設定されていない場合、自己分析モードでは Logfire MCP が自動的に無効化され、ローカルのログファイルのみを使用します。
設定すると、MCP サーバーから以下のツールを利用できます:
mcp__logfire__arbitrary_query- logfire データに対して SQL クエリを実行しますmcp__logfire__schema_reference- データベースのスキーマを取得しますmcp__logfire__find_exceptions_in_file- ファイル内の例外を検索しますmcp__logfire__logfire_link- UI 内のトレースへのリンクを作成します
必須フラグ:
--automation- プログラムで解析しやすい出力にします。このフラグの詳細については、massgen-develops-massgenスキルを参照してください--logfire- Logfire のトレースを有効にします(任意ですが、Logfire データを記録するには必要です)
パート 1:MassGen 実験の実行
基本的なコマンド形式
uv run massgen --automation --logfire --config [config_file] "[question]"
バックグラウンドで実行する(推奨)
run_in_background: true(またはタスクをバックグラウンドで実行する方法)を使用すると、実験を非同期で実行できます。進行状況を監視し、必要に応じて早めに終了できます。
想定される出力(最初の行):
LOG_DIR: .massgen/massgen_logs/log_YYYYMMDD_HHMMSS_ffffff
STATUS: .massgen/massgen_logs/log_YYYYMMDD_HHMMSS_ffffff/turn_1/attempt_1/status.json
QUESTION: Your task here
[Coordination in progress - monitor status.json for real-time updates]
LOG_DIR を確認してください - ファイルベースの分析に必要になります!
進行状況の監視
status.json は 2 秒ごとに更新されます。これを使用して進行状況を追跡してください。
cat [log_dir]/turn_1/attempt_1/status.json
監視する主なフィールド:
coordination.completion_percentage(0~100)coordination.phase- "initial_answer"、"enforcement"、"presentation"results.winner- 実行中は null、完了時は agent_idagents[].status- "waiting"、"streaming"、"answered"、"voted"、"error"agents[].error- 正常な場合は null、失敗した場合はエラーの詳細
最終結果の読み取り
完了後(終了コード 0):
# Read the final answer
cat [log_dir]/turn_1/attempt_1/final/[winner]/answer.txt
その他の便利なファイル:
execution_metadata.yaml- 設定と実行の詳細全体coordination_events.json- イベントログ全体coordination_table.txt- 人が読みやすい形式の連携サマリー
パート 2:Logfire のクエリ
データベーススキーマ
メインテーブルは records で、以下の主要な列があります:
| 列 | 説明 |
|---|---|
span_name | スパンの名前(例:"agent.agent_a.round_0") |
span_id | このスパンの一意の識別子 |
parent_span_id | 親スパンの ID(ルートの場合は null) |
trace_id | 1 つのトレース内のすべてのスパンをまとめます |
duration | 秒単位の時間 |
start_timestamp | スパンの開始時刻 |
end_timestamp | スパンの終了時刻 |
attributes | カスタム属性を含む JSON データ |
message | ログメッセージ |
is_exception | エラーかどうかを示すブール値 |
exception_type | 例外がある場合の種類 |
exception_message | 例外メッセージ |
MassGen のスパン階層
MassGen は階層構造のスパンを作成します:
coordination.session (root)
├── Coordination event: coordination_started
├── agent.agent_a.round_0
│ ├── llm.openrouter.stream
│ ├── mcp.filesystem.write_file
│ └── Tool execution: mcp__filesystem__write_file
├── agent.agent_b.round_0
├── Agent answer: agent1.1
├── agent.agent_a.round_1 (voting round)
├── Agent vote: agent_a -> agent1.1
├── Coordination event: winner_selected
└── agent.agent_a.presentation
├── Winner selected: agent1.1
├── llm.openrouter.stream
└── Final answer from agent_a
カスタム属性
MassGen のスパンには、以下のカスタム属性が含まれます(attributes->'key' からアクセスできます)。
| 属性 | 説明 |
|---|---|
massgen.agent_id | エージェント識別子(agent_a、agent_b) |
massgen.iteration | 現在の反復回数 |
massgen.round | このエージェントのラウンド番号 |
massgen.round_type | 「initial_answer」、「voting」、または「presentation」 |
massgen.backend | バックエンドプロバイダー名 |
massgen.num_context_answers | コンテキスト内の回答数 |
massgen.is_winner | プレゼンテーションのスパンでは True |
massgen.outcome | 「vote」、「answer」、または「error」(ラウンド完了後に設定) |
massgen.voted_for | 投票したエージェント ID(投票の場合のみ設定) |
massgen.voted_for_label | 投票した回答ラベル(例:「agent1.1」、投票の場合のみ設定) |
massgen.answer_label | 割り当てられた回答ラベル(例:「agent1.1」、回答の場合のみ設定) |
massgen.error_message | エラーメッセージ(outcome が「error」の場合のみ設定) |
massgen.usage.input | 入力トークン数 |
massgen.usage.output | 出力トークン数 |
massgen.usage.reasoning | 推論トークン数 |
massgen.usage.cached_input | キャッシュされた入力トークン数 |
massgen.usage.cost | 米ドルでの推定コスト |
パート 3:一般的な分析クエリ
1. トレース階層の表示
SELECT span_name, span_id, parent_span_id, duration, start_timestamp
FROM records
WHERE trace_id = '[YOUR_TRACE_ID]'
ORDER BY start_timestamp
LIMIT 50
2. 最近のセッションの検索
SELECT span_name, trace_id, duration, start_timestamp
FROM records
WHERE span_name = 'coordination.session'
ORDER BY start_timestamp DESC
LIMIT 10
3. エージェントのラウンドごとのパフォーマンス
SELECT
span_name,
duration,
attributes->>'massgen.agent_id' as agent_id,
attributes->>'massgen.round' as round,
attributes->>'massgen.round_type' as round_type
FROM records
WHERE span_name LIKE 'agent.%'
ORDER BY start_timestamp DESC
LIMIT 20
4. ツール呼び出しの分析
SELECT
span_name,
duration,
parent_span_id,
start_timestamp
FROM records
WHERE span_name LIKE 'mcp.%' OR span_name LIKE 'Tool execution:%'
ORDER BY start_timestamp DESC
LIMIT 30
5. エラーの検索
SELECT
span_name,
exception_type,
exception_message,
trace_id,
start_timestamp
FROM records
WHERE is_exception = true
ORDER BY start_timestamp DESC
LIMIT 20
6. LLM 呼び出しのパフォーマンス
SELECT
span_name,
duration,
attributes->>'gen_ai.request.model' as model,
start_timestamp
FROM records
WHERE span_name LIKE 'llm.%'
ORDER BY start_timestamp DESC
LIMIT 30
7. 階層を含む完全なトレース(ネストされた表示)
SELECT
CASE
WHEN parent_span_id IS NULL THEN span_name
ELSE ' └─ ' || span_name
END as hierarchy,
duration,
span_id,
parent_span_id
FROM records
WHERE trace_id = '[YOUR_TRACE_ID]'
ORDER BY start_timestamp
8. コーディネーションイベントのタイムライン
SELECT span_name, message, duration, start_timestamp
FROM records
WHERE span_name LIKE 'Coordination event:%'
OR span_name LIKE 'Agent answer:%'
OR span_name LIKE 'Agent vote:%'
OR span_name LIKE 'Winner selected:%'
ORDER BY start_timestamp DESC
LIMIT 30
パート 4:分析ワークフロー
ステップ 1:実験を実行する
uv run massgen --automation --logfire --config [config] "[prompt]" 2>&1
ステップ 2:トレースを見つける
最近のセッションをクエリします。
SELECT trace_id, duration, start_timestamp
FROM records
WHERE span_name = 'coordination.session'
ORDER BY start_timestamp DESC
LIMIT 5
ステップ 3:階層を分析する
トレース構造全体を取得します。
SELECT span_name, span_id, parent_span_id, duration
FROM records
WHERE trace_id = '[trace_id_from_step_2]'
ORDER BY start_timestamp
ステップ 4:特定の問題を調査する
遅いツール呼び出し:
SELECT span_name, duration, parent_span_id
FROM records
WHERE trace_id = '[trace_id]' AND span_name LIKE 'mcp.%'
ORDER BY duration DESC
エージェントの比較:
SELECT
attributes->>'massgen.agent_id' as agent,
COUNT(*) as rounds,
SUM(duration) as total_time,
AVG(duration) as avg_round_time
FROM records
WHERE trace_id = '[trace_id]' AND span_name LIKE 'agent.%'
GROUP BY attributes->>'massgen.agent_id'
ステップ 5:トレースリンクを作成する
MCP ツールを使用して、表示可能なリンクを作成します。
mcp__logfire__logfire_link(trace_id="[your_trace_id]")
パート 5:ログ構造の改善
現在のスパンタイプ
| スパンパターン | ソース | 説明 |
|---|---|---|
coordination.session | coordination_tracker.py | ルートセッションのスパン |
agent.{id}.round_{n} | orchestrator.py | エージェントの実行ラウンド |
agent.{id}.presentation | orchestrator.py | 勝者の最終プレゼンテーション |
mcp.{server}.{tool} | mcp_tools/client.py | MCP ツールの実行 |
llm.{provider}.stream | backends | LLM ストリーミング呼び出し |
Tool execution: {name} | base_with_custom_tool.py | ツールラッパー |
Coordination event: * | coordination_tracker.py | コーディネーションイベント |
Agent answer: {label} | coordination_tracker.py | エージェントによる回答の提出 |
Agent vote: {from} -> {to} | coordination_tracker.py | 投票の実施 |
新しいスパンの追加
structured_logging のトレーサーを使用します。
from massgen.structured_logging import get_tracer
tracer = get_tracer()
with tracer.span("my_operation", attributes={
"massgen.custom_key": "value",
}):
do_work()
コンテキスト伝播に関する注意事項
既知の制限事項: 複数のエージェントを asyncio.create_task で同時に実行すると、子スパンがエージェントのラウンドスパンの下に正しくネストされないことがあります。これは、並行する非同期コードにおける OpenTelemetry のコンテキスト伝播の問題です。プレゼンテーションフェーズでは実行するエージェントが 1 つだけなので、正しく動作します。
回避策: 並行シナリオで正確にネストするには、contextvars.copy_context() を使用した明示的なコンテキストの受け渡しが必要です。
Logfire ドキュメントの参照先
主なドキュメント: https://logfire.pydantic.dev/docs/
知っておくべき主要ページ
| トピック | URL | 説明 |
|---|---|---|
| はじめに | /docs/ | 概要、セットアップ、基本概念 |
| 手動トレース | /docs/guides/onboarding-checklist/add-manual-tracing/ | スパンの作成、属性の追加 |
| SQL エクスプローラー | /docs/guides/web-ui/explore/ | UI での SQL クエリの作成 |
| ライブビュー | /docs/guides/web-ui/live/ | リアルタイムのトレース監視 |
| クエリ API | /docs/how-to-guides/query-api/ | データへのプログラムからのアクセス |
| OpenAI インテグレーション | /docs/integrations/llms/openai/ | LLM 呼び出しの計装 |
Logfire の概念
スパンとログ:
- スパンは、測定可能な所要時間を持つ操作を表します(
with logfire.span():を使用します) - ログは、特定の時点で発生したイベントを記録します(
logfire.info()、logfire.error()などを使用します) - スパンブロック内のスパンとログは、そのスパンの子になります
スパン名とメッセージ:
span_name= 最初の引数(フィルタリングに使用します。カーディナリティを低く保ってください)message= 属性値が埋め込まれたフォーマット済みの結果- 例:
logfire.info('Hello {name}', name='Alice')→ span_name="Hello {name}", message="Hello Alice"
属性:
- キーワード引数は構造化 JSON 属性になります
- SQL では
attributes->>'key'またはattributes->'key'でアクセスします - 必要に応じてキャストします:
(attributes->'cost')::float
ライブビューの機能
Logfire のライブビュー UI(https://logfire.pydantic.dev/)には、次の機能があります:
- トレースが到着するとリアルタイムにストリーミング
- オートコンプリート機能付きのSQL 検索ペイン(
/を押して開きます) - 自然言語から SQL への変換:必要な内容を説明すると、クエリが生成されます
- 時間経過に伴うスパン数を表示するタイムラインヒストグラム
- 属性、例外、OpenTelemetry データを表示するトレース詳細パネル
- trace_id/span_id を介した SQL の結果とトレースビュー間の相互リンク
SQL エクスプローラーのヒント
Explore ページでは Apache DataFusion の SQL 構文を使用します(Postgres に似ています):
-- Subqueries and CTEs work
WITH recent AS (
SELECT * FROM records
WHERE start_timestamp > now() - interval '1 hour'
)
SELECT * FROM recent WHERE is_exception;
-- Access nested JSON
SELECT attributes->>'massgen.agent_id' as agent FROM records;
-- Cast JSON values
SELECT (attributes->'token_count')::int as tokens FROM records;
-- Time filtering is efficient
WHERE start_timestamp > now() - interval '30 minutes'
LLM の計装
Logfire は設定すると OpenAI の呼び出しを自動で計装します:
- 会話の表示、トークン使用量、レスポンスのメタデータを記録します
- ストリーミングリクエストとレスポンスに対して、それぞれ別のスパンを作成します
- 同期クライアントと非同期クライアントの両方で動作します
MassGen のバックエンドでは、これを llm.{provider}.stream スパンに使用しています。
リファレンスドキュメント
Logfire:
- メインドキュメント:https://logfire.pydantic.dev/docs/
- ライブビュー:https://logfire.pydantic.dev/docs/guides/web-ui/live/
- SQL エクスプローラー:https://logfire.pydantic.dev/docs/guides/web-ui/explore/
- クエリ API:https://logfire.pydantic.dev/docs/how-to-guides/query-api/
- 手動トレース:https://logfire.pydantic.dev/docs/guides/onboarding-checklist/add-manual-tracing/
- OpenAI インテグレーション:https://logfire.pydantic.dev/docs/integrations/llms/openai/
- スキーマリファレンス:
mcp__logfire__schema_referenceツールを使用します
MassGen:
- 自動化モード:
AI_USAGE.md - ステータスファイルのリファレンス:
docs/source/reference/status_file.rst - 構造化ログ:
massgen/structured_logging.py
効果的な分析のヒント
- 必ず両方のフラグを使用してください:
--automation --logfire - 長時間かかるタスクはバックグラウンドで実行して進捗を監視します
- 特定のセッションを分離するには trace_id でクエリします
- 階層を把握するには parent_span_id を確認します
- ボトルネックの特定には duration を使用します
- MassGen 固有のコンテキストを把握するには 属性を確認します
- チームと調査結果を共有するには トレースリンクを作成します
次のようなエラーが発生する場合があります:
Error: Error executing tool arbitrary_query: b'{"detail":"Rate limit exceeded for organization xxx: per minute
limit reached."}'
その場合は、最大 1 分間待機してから、もう一度お試しください。
パート 6:包括的なログ分析レポート
MassGen のログ実行の分析を依頼された場合は、分析対象のターンを N として、[log_dir]/turn_N/ANALYSIS_REPORT.md に保存する Markdown レポートを生成します。各ターン(調整セッション)には、attempt ディレクトリと同じ階層に独自の分析レポートを作成します。レポートでは、以下の 標準分析項目を扱う必要があります。
重要:グラウンドトゥルースと正確性
重要:ユーザーが明示的にグラウンドトゥルースを提示しない限り、エージェントの回答が「正しい」と仮定しないでください。
- 各エージェントが主張した、または出力した内容を報告し、正しさを断定しないでください
- エージェント間で意見が一致しているか、食い違っているかを記載しますが、一致していることを正しさの根拠にしないでください
- エージェントの回答が異なる場合は、両方を中立的に提示してください
- ユーザーが実際の回答を提示した場合に限り、回答を正解または不正解と判定してください
- 避ける表現:「正しく特定した」「正解を得た」「正しく解決した」
- 使用する表現:「主張した」「出力した」「提出した」「たどり着いた」
標準的な分析の質問
すべての分析レポートで、次の質問に回答する必要があります。
1. 正確性
- 調整は正常に完了しましたか?
- すべてのエージェントが回答を提出しましたか?
- 投票は正しく行われましたか?
- 勝者が選出され、そのエージェントは最終回答を提示しましたか?
2. 効率性とボトルネック
- 合計所要時間とフェーズごとの内訳はどうなっていますか?
- 最も時間のかかった処理は何ですか?
- 最も時間がかかったツールはどれですか?
- エージェント別に並べ替えた、ラウンドごとのタイミング表を作成してください。次の項目を含めます。
- ラウンドの開始/終了タイムスタンプ
- ラウンドの合計時間
- ツールの実時間
- ツール以外の時間(モデル/ストリーミング/待機)
- チェックリストを含む各ラウンドを、次のように分割します。
- 評価 = ラウンド開始から最初の
submit_checklistの開始まで - チェックリストから提案まで = 最初の
submit_checklistの終了から最初のdraft_approachの開始まで - 実装 = 最初の
draft_approachの終了からラウンド終了まで - チェックリスト後(提案なし) = 最初の
submit_checklistの終了からラウンド終了まで(提案が行われなかった場合)
- 評価 = ラウンド開始から最初の
- 評価と実装の割合を報告します。
- チェックリストを含むすべてのセグメントについて
- 実際に
draft_approachを含むセグメントのみについて
3. コマンドのパターン分析
- 頻繁に繰り返され、回避できたコマンドはありましたか?(例:
openskills read、npm install、ls -R) - 不必要に長い出力を生成したコマンドは何ですか?(例:スキルのドキュメント、ディレクトリ一覧)
- 最も時間がかかった
execute_commandのパターンは何ですか?(例:ウェブスクレイピング、パッケージのインストール)
4. 作業の重複分析
- 画像生成など、コストのかかる作業が不必要にやり直されましたか?
- 両方のエージェントが、類似または同一のアセットを生成しましたか?
- 再起動後にアセットを再利用せず、再生成していましたか?
- キャッシュや共有によって、時間やコストを節約できた可能性はありますか?
5. エージェントの行動と意思決定
- エージェントは以前の回答をどのように評価しましたか? どのような理由を示しましたか?
- 投票するか、新しい回答を提示するかを、エージェントはどのように判断しましたか?
- エージェントは互いの作業を実際に発展させましたか、それとも別々に作業しましたか?
- タイムアウトや未完了のラウンドはありましたか?
6. コストとトークンの分析
- 合計コストとエージェント別の内訳
- トークン使用量(入力、出力、推論、キャッシュ)
- キャッシュヒット率
7. エラーと問題
- 例外や失敗はありましたか?
- タイムアウトはありましたか?
- エージェントのエラーはありましたか?
8. エージェントの推論と行動の分析(重要)
これは最も重要なセクションです。 エージェントの思考や行動を分析することで、成功と失敗の根本原因が明らかになります。
データソース:
agent_outputs/agent_*.txt- 推論を含む完全な出力(利用可能な場合)agent_*/*/execution_trace.md- 引数と結果を含むツール呼び出しの全記録streaming_debug.log- ストリーミングチャンクの生データ
注: 明示的な推論トレースを出力しないモデルもあります。その場合は、ツール呼び出しのパターンと内容を分析してください。行動の順序から、意思決定の過程を読み取れます。
各エージェントについて、以下を分析してください:
- 戦略 - どのようなアプローチを取りましたか?(推論またはツールの実行順序から判断)
- ツールの応答 - 成功、失敗、矛盾にどのように対処しましたか?
- エラーからの回復 - 問題を検出しましたか? 回避策を実装しましたか?
- 意思決定の質 - 論理的な誤りはありましたか? 検証が過剰または不足していましたか? 分析が行き詰まっていませんでしたか?
- エージェント間の比較 - 推論が最も優れていたのはどのエージェントですか? 成功につながったパターンは何ですか?
主なパターン:
| パターン | 良い兆候 | 悪い兆候 |
|---|---|---|
| 失敗の検出 | 2~3回の失敗後に方針を転換する | うまくいかないアプローチを6回以上繰り返す |
| 結果の検証 | 出力を相互検証する | 最初の結果を疑わずに受け入れる |
| 矛盾への対処 | 矛盾を調査する | 矛盾を無視する |
| 回避策 | 行き詰まったときに創造的な代替案を見つける | あきらめる、または同じことを繰り返す |
| 時間管理 | 確信が持てたら回答を確定する | 終わりのない検証を続け、回答しない |
重要な証拠を抽出する: 各エージェントについて、推論が利用可能な場合は引用を2~3件含めるか、意思決定の質を示す主要なツール実行順序を説明してください。
9. ツールの信頼性分析
単純にエラーを列挙するのではなく、ツールの動作パターンを分析してください。
- 一貫性 - 同じ入力に対して同じ出力が返されますか? 出力のばらつきを記録してください。
- 偽陽性/偽陰性 - ツールが成功または失敗のステータスを誤って報告していませんか?
- 根本原因の仮説 - 失敗パターンごとに、考えられる原因(パスの問題、レート制限、モデルの制約など)を提案してください。
10. 制約の適用とワークフローの信頼性分析
データソース: status.json → agents[].reliability
ワークフロー違反により、エージェントが再試行を必要としたかどうかを確認してください。主な指標:
total_enforcement_retries- エージェントが再試行を強制された回数total_buffer_chars_lost- 再起動によって破棄されたコンテンツunknown_tools- 幻覚されたツール名by_round- 問題が発生したラウンド
危険信号: 1ラウンドあたり2回以上の再試行、5000文字を超える損失、unknown_tools リストに項目があること。
スキーマ全体と理由コードについては、「主なローカルログファイル」セクションの「制約の適用に関する信頼性」を参照してください。
11. 回答品質の推移
データソース: agent_outputs/agent_*.txt、agent_*/*/execution_trace.md、agent_*/*/vote.json
各エージェントについて、ラウンドごとに回答品質がどのように推移したかを追跡してください。
- 回答Nと回答N+1の間で、具体的に何が変わりましたか?
- 変更は実質的(新しいアプローチ、新しい機能、構造的な改善)でしたか、それとも表面的(わずかな表現の修正、小さなスタイルの調整)でしたか?
- 他のエージェントの回答を見た後、回答の質が低下したエージェントはいましたか?
- 各ラウンドで改善した評価基準と、停滞した評価基準はどれですか?
ラウンドごとの推移を評価してください:
- 🟢 実質的な改善 — 重要な側面の少なくとも1つで大幅に向上
- 🟡 わずかな改善 — 洗練されたが、新しい能力や洞察はない
- 🔴 改善なし/後退 — コストをかけたにもかかわらず、同じか、それより悪い
12. 改善提案の品質
データソース: agent_outputs/agent_*.txt(ギャップ分析、診断セクション、改善計画を確認)、agent_*/*/vote.json
新しい回答を作成する前に、エージェント(または調整システム)が改善案を提案します。それぞれを分析してください。
- 具体性:提案は失敗の理由を特定していましたか、それとも失敗した事実を述べただけでしたか?(「5秒の表示時間にアニメーションのタイミングが合っていない」対「アニメーションを改善する」)
- 実行可能性:後続のエージェントが、追加の推論なしで提案を実装できましたか?
- 正確性:提案は根本的な問題を正しく診断していましたか、それとも症状に対処していましたか?
- 網羅性:主要なギャップをすべて網羅していましたか、それとも決定的な差別化要因を見落としていましたか?
各提案を評価してください:
| 提案 | 具体的か? | 実行可能か? | 正確か? | 適切な判断だったか? |
|---|---|---|---|---|
| [提案の概要] | Yes/No | Yes/No | Yes/No | Yes/No — [理由] |
また、改善案がエージェント自身によるもの(自己振り返り)、相互評価によるもの、あるいは評価基準のギャップから推測されたものかも記録してください。
13. ラウンドの投資対効果(「その価値はあったか?」)
データソース: metrics_summary.json、coordination_events.json、エージェントの出力
各ラウンドの投資対効果を評価してください。
- コスト:このラウンドのトークン数 × モデルの料金
- 時間:このラウンドの実時間(秒)
- 品質の変化:直前の最良回答と比べて、実質的に何が変わったか
- 判定:コストと時間に見合うラウンドでしたか?
| ラウンド | エージェント | コスト | 時間 | 品質の変化 | 判定 |
|---|---|---|---|---|---|
| R0 | agent_a | $X | Xs | ベースライン | — |
| R1 | agent_a | $X | Xs | [変更点] | 🟢/🟡/🔴 |
収穫逓減の検出:追加の反復で有意な改善が見られなくなったのは何ラウンド目ですか?システムが見逃した明確な停止点はありましたか?
また、改善ではなく検証や確認だけに、コストの高いラウンドを費やしたエージェントがいなかったかも記録してください。
14. 委任とモデル割り当ての分析
データソース: agent_outputs/agent_*.txt、execution_trace.md、metrics_summary.json
各エージェントの作業のうち、どの程度が機械的な作業で、どの程度に真の知性が必要だったか、また適切なモデル層が使われていたかを分析します。
各ラウンドで、エージェントごとの作業を分類します:
-
機械的(予測可能で、定型的なため、より弱いモデルでも実行可能であり、かつ委任する価値があるだけのコンテキストを消費する作業):
- 構造検証(要素数、寸法の確認、形式への準拠)—特に大量のシェル出力が発生する場合
- 定型コードの生成(ループ、座標計算、テンプレートの穴埋め)—大規模で反復的なコードブロック
- 二択のチェックリストによる評価(E1~E4形式:機能 X が存在するか)—多くのツール呼び出しや長い出力を伴う場合
- エビデンスの収集(シェルコマンドの実行、出力の解析、ピクセル差分の確認)—推論内容が少ない一方でトークンコストが高い作業
注:タスクのステータス更新やワークフローツールの呼び出しといったプロトコル上の手順は、委任する価値がありません。コンテキスト消費が少なく、メインモデルがインラインで低コストに処理できるためです。問うべきなのは、より弱いモデルでも理論上実行できるかではなく、委任によって意味のあるトークン削減が得られるかどうかです。
-
品質/知性(真の推論、統合、創造性が必要な作業):
- 根本原因の診断(症状を根底にある設計上の欠陥と結び付ける)
- エージェント間の統合(N 個の回答から最良の要素を見極め、組み合わせる計画を立てる)
- 新しいアプローチの考案(既存の回答にはない機能や設計)
- 教育的または専門分野に関する推論(例:「このアニメーションのタイミングでは、5 秒間の注意持続時間を逃してしまう」)
- トレードオフ分析(特定の目標に対して、ある設計上の選択が別の選択より優れている理由)
エージェント/ラウンドごとに推定します:
- 機械的作業と品質重視の推論の割合(%)
- 機械的な作業と、知性を要する作業の具体例
- 引用箇所:機械的なテンプレートの穴埋めと、真の診断的洞察
全体評価:
- 実行全体のコンテキスト(トークン)のうち、機械的な作業に使われた割合はどの程度か
- より安価なモデル(例:Haiku)で機械的な作業を担当しても、出力品質を損なわずに済んだか
- 品質に重大な影響を及ぼす場面を、より弱いサブエージェントが担当していなかったか(または、上位モデルにエスカレーションすべきではなかったか)
- 機械的な作業をより安価なモデル層に割り当てていた場合の、推定コスト削減額
質問ごとのデータソース
| 質問 | 主なソース | 副次的なソース |
|---|---|---|
| 正確性 | coordination_events.json、coordination_table.txt | Logfire の調整イベント |
| 効率性 | metrics_summary.json | Logfire の実行時間クエリ |
| コマンドパターン | streaming_debug.log("command": を grep) | - |
| 作業の重複 | streaming_debug.log(ツールのプロンプト/引数を grep) | metrics_summary.json のツール呼び出し回数 |
| エージェントの判断 | agent_*/*/vote.json、coordination_events.json | Logfire の投票スパン |
| 評価と実装の所要時間 | status.json、metrics_events.json | events.jsonl、Logfire のスパン所要時間 |
| コスト/トークン | metrics_summary.json | Logfire の使用量属性 |
| エラー | coordination_events.json、metrics_summary.json | Logfire の is_exception=true |
| 遵守状況 | status.json → agents[].reliability | - |
分析コマンド
繰り返し実行されたコマンドを検索:
grep -o '"command": "[^"]*"' streaming_debug.log | sed 's/"command": "//;s/"$//' | sort | uniq -c | sort -rn | head -30
generate_media のプロンプトを検索(重複を確認):
grep -o '"prompts": \[.*\]' streaming_debug.log
投票理由を確認:
cat agent_*/*/vote.json | jq '.reason'
タイムアウトイベントを検索:
cat coordination_events.json | jq '.events[] | select(.event_type == "agent_timeout")'
エージェントごとに並べ替えて、ラウンドごとの評価と実装の所要時間を算出:
python - <<'PY'
import json
from collections import defaultdict
from pathlib import Path
base = Path(".")
status = json.loads((base / "status.json").read_text())
metrics = json.loads((base / "metrics_events.json").read_text())
def m(seconds):
return seconds / 60.0
def union(intervals):
if not intervals:
return 0.0
intervals = sorted(intervals)
cs, ce = intervals[0]
total = 0.0
for s, e in intervals[1:]:
if s <= ce:
ce = max(ce, e)
else:
total += ce - cs
cs, ce = s, e
total += ce - cs
return total
segments = []
for agent_id, agent_data in status["agents"].items():
rounds = sorted(agent_data.get("round_history", []), key=lambda r: r["start_time"])
for idx, r in enumerate(rounds, 1):
segments.append({
"agent": agent_id,
"seg_idx": idx,
"round_number": r["round_number"],
"round_type": r["round_type"],
"outcome": r["outcome"],
"start": float(r["start_time"]),
"end": float(r["end_time"]),
"duration": float(r["duration_ms"]) / 1000.0,
})
by_segment = defaultdict(list)
for t in metrics["tool_executions"]:
ts = float(t["start_time"])
te = float(t["end_time"])
candidates = [
s for s in segments
if s["agent"] == t["agent_id"] and not (te < s["start"] or ts > s["end"])
]
if not candidates:
continue
best = max(
candidates,
key=lambda s: max(0.0, min(te, s["end"]) - max(ts, s["start"])),
)
by_segment[(best["agent"], best["seg_idx"])].append(t)
rows = []
for s in sorted(segments, key=lambda x: (x["agent"], x["start"])):
calls = sorted(by_segment.get((s["agent"], s["seg_idx"]), []), key=lambda t: t["start_time"])
submit = [t for t in calls if t["tool_name"] == "mcp__massgen_checklist__submit_checklist"]
propose = [t for t in calls if t["tool_name"] == "mcp__massgen_checklist__draft_approach"]
# round-level tool wall time
ints = []
for t in calls:
ts, te = float(t["start_time"]), float(t["end_time"])
ov = max(0.0, min(te, s["end"]) - max(ts, s["start"]))
if ov > 0:
ints.append((max(ts, s["start"]), min(te, s["end"])))
tool_wall = union(ints)
non_tool = max(0.0, s["duration"] - tool_wall)
eval_pre = mid = impl_post = post_no_propose = 0.0
first_submit = submit[0] if submit else None
first_propose = propose[0] if propose else None
if first_submit:
eval_pre = max(0.0, min(s["end"], float(first_submit["start_time"])) - s["start"])
elif first_propose:
eval_pre = max(0.0, min(s["end"], float(first_propose["start_time"])) - s["start"])
if first_submit and first_propose:
mid = max(0.0, min(s["end"], float(first_propose["start_time"])) - float(first_submit["end_time"]))
impl_post = max(0.0, s["end"] - float(first_propose["end_time"]))
elif first_submit and not first_propose:
post_no_propose = max(0.0, s["end"] - float(first_submit["end_time"]))
elif first_propose and not first_submit:
impl_post = max(0.0, s["end"] - float(first_propose["end_time"]))
rows.append({
**s,
"tool_wall": tool_wall,
"non_tool": non_tool,
"submit_count": len(submit),
"propose_count": len(propose),
"eval_pre": eval_pre,
"mid": mid,
"impl_post": impl_post,
"post_no_propose": post_no_propose,
})
print("| Agent | Segment | Round | Type | Outcome | Total (min) | Tool wall (min) | Non-tool (min) | Eval pre (min) | Checklist->Propose (min) | Improve post-propose (min) | Post-checklist no-propose (min) |")
print("|---|---:|---:|---|---|---:|---:|---:|---:|---:|---:|---:|")
for r in rows:
print(
f"| {r['agent']} | {r['seg_idx']} | {r['round_number']} | {r['round_type']} | {r['outcome']} | "
f"{m(r['duration']):.2f} | {m(r['tool_wall']):.2f} | {m(r['non_tool']):.2f} | "
f"{m(r['eval_pre']):.2f} | {m(r['mid']):.2f} | {m(r['impl_post']):.2f} | {m(r['post_no_propose']):.2f} |"
)
PY
レポートテンプレート
このレポートを [log_dir]/turn_N/ANALYSIS_REPORT.md に保存します(N は分析対象のターン番号です):
# MassGen Log Analysis Report
**Session:** [log_dir name]
**Trace ID:** [trace_id if available]
**Generated:** [timestamp]
**Logfire Link:** [link if available]
## Executive Summary
[2-3 sentence summary of the run: what was the task, did it succeed, key findings]
## Session Overview
| Metric | Value |
|--------|-------|
| Duration | X minutes |
| Agents | [list] |
| Winner | [agent_id] |
| Total Cost | $X.XX |
| Total Answers | X |
| Total Votes | X |
| Total Restarts | X |
## 1. Correctness Analysis
### Coordination Flow
[Timeline of key events]
### Status
- [ ] All phases completed
- [ ] All agents submitted answers
- [ ] Voting completed correctly
- [ ] Winner selected
- [ ] Final answer delivered
### Issues Found
[List any correctness issues]
## 2. Efficiency Analysis
### Phase Duration Breakdown
| Phase | Count | Avg (s) | Max (s) | Total (s) | % of Total |
|-------|-------|---------|---------|-----------|------------|
| initial_answer | | | | | |
| voting | | | | | |
| presentation | | | | | |
### Per-Round Timing (Sorted by Agent)
| Agent | Segment | Round | Type | Outcome | Start-End | Total (min) | Tool wall (min) | Non-tool (min) |
|-------|---------|-------|------|---------|-----------|-------------|-----------------|----------------|
| agent_a | 1 | r0 | initial_answer | answer | HH:MM:SS-HH:MM:SS | | | |
| ... | | | | | | | | |
### Evaluation vs Implementation Timing (Checklist-Gated Phases)
**Phase definitions used in this report:**
- Evaluation = round start -> first `submit_checklist` start
- Checklist->Propose = first `submit_checklist` end -> first `draft_approach` start
- Implementation = first `draft_approach` end -> round end
- Post-checklist (no propose) = first `submit_checklist` end -> round end (if no propose happened)
| Scope | Evaluation (min / %) | Checklist->Propose (min / %) | Implementation (min / %) | Post-checklist no-propose (min / %) |
|-------|-----------------------|-------------------------------|---------------------------|--------------------------------------|
| All checklist-containing segments | | | | |
| Only segments with draft_approach | | | | |
### Per-Round Evaluation vs Improvement Table
| Agent | Segment | Round | Total (min) | Eval pre-checklist (min) | Checklist->Propose (min) | Improve post-propose (min) | Post-checklist no-propose (min) | Eval vs Improve verdict |
|-------|---------|-------|-------------|----------------------------|---------------------------|-----------------------------|----------------------------------|-------------------------|
| agent_c | 2 | r1 | | | | | | [which side dominates and why] |
| ... | | | | | | | | |
### Top Bottlenecks
1. [Operation] - X seconds (X% of total)
2. [Operation] - X seconds
3. [Operation] - X seconds
## 3. Command Pattern Analysis
### Frequently Repeated Commands
| Command | Times Run | Issue | Recommendation |
|---------|-----------|-------|----------------|
| `openskills read pptx` | X | Long output (~5KB) re-read after restarts | Cache skill docs |
| `npm install ...` | X | Reinstalled after each restart | Persist node_modules |
| ... | | | |
### Commands with Excessive Output
| Command | Output Size | Issue |
|---------|-------------|-------|
| | | |
### Slowest Command Patterns
| Pattern | Max Time | Avg Time | Notes |
|---------|----------|----------|-------|
| Web scraping (crawl4ai) | Xs | Xs | |
| npm install | Xs | Xs | |
| PPTX pipeline | Xs | Xs | |
## 4. Work Duplication Analysis
### Duplicated Work Found
| Work Type | Times Repeated | Wasted Time | Wasted Cost |
|-----------|----------------|-------------|-------------|
| Image generation | X | X min | $X.XX |
| Research/scraping | X | X min | - |
| Package installs | X | X min | - |
### Specific Examples
[List specific examples of duplicated work with prompts/commands]
### Recommendations
1. [Specific recommendation to avoid duplication]
2. [Specific recommendation]
## 5. Agent Behavior Analysis
### Answer Progression
| Label | Agent | Time | Summary |
|-------|-------|------|---------|
| agent1.1 | agent_a | HH:MM | [brief description] |
| agent2.1 | agent_b | HH:MM | [brief description] |
| ... | | | |
### Voting Analysis
| Voter | Voted For | Reasoning Summary |
|-------|-----------|-------------------|
| agent_b | agent1.1 | "[key quote from reasoning]" |
### Vote vs New Answer Decisions
[Explain how agents decided whether to vote or provide new answers]
### Agent Collaboration Quality
- Did agents read each other's answers? [Yes/No with evidence]
- Did agents build upon previous work? [Yes/No with evidence]
- Did agents provide genuine evaluation? [Yes/No with evidence]
### Timeouts/Incomplete Rounds
[List any timeouts with context]
## 6. Cost & Token Analysis
### Cost Breakdown
| Agent | Input Tokens | Output Tokens | Reasoning | Cost |
|-------|--------------|---------------|-----------|------|
| agent_a | | | | $X.XX |
| agent_b | | | | $X.XX |
| **Total** | | | | **$X.XX** |
### Cache Efficiency
- Cached input tokens: X (X% cache hit rate)
### Tool Cost Impact
| Tool | Calls | Est. Time Cost | Notes |
|------|-------|----------------|-------|
| generate_media | X | X min | |
| command_line | X | X min | |
## 7. Errors & Issues
### Exceptions
[List any exceptions with type and message]
### Failed Tool Calls
[List any failed tools]
### Agent Errors
[List any agent-level errors]
### Timeouts
[List any timeouts with duration and context]
## 8. Recommendations
### High Priority
1. **[Issue]**: [Specific actionable recommendation]
2. **[Issue]**: [Specific actionable recommendation]
### Medium Priority
1. **[Issue]**: [Recommendation]
### Low Priority / Future Improvements
1. **[Issue]**: [Recommendation]
## 9. Suggested Linear Issues
Based on the analysis, the following issues are suggested for tracking. If you have access to the Linear project and the session is interactive, **present these to the user for approval before creating.** Regardless of access, you should write them in a section as below, as we want to learn from the logs to propose and later solve concrete issues:
| Priority | Title | Description | Labels |
|----------|-------|-------------|--------|
| High | [Short title] | [1-2 sentence description] | log-analysis, [area] |
| Medium | [Short title] | [Description] | log-analysis, [area] |
**After user approval**, create issues in Linear with:
- Project: MassGen
- Label: `log-analysis` (to identify issues from log analysis)
- Additional labels as appropriate (e.g., `performance`, `agent-behavior`, `tooling`)
## Appendix
### Configuration Used
[Key config settings from execution_metadata.yaml]
### Files Generated
[List of output files in the workspace]
レポート生成のワークフロー
- まずローカルファイルを読み込みます(metrics_summary.json、coordination_table.txt、coordination_events.json、status.json、metrics_events.json)
- エージェント別に並べ替えたラウンドごとのタイミング表を作成します。合計時間、ツール実行時間、ツール以外の時間を含めます
- チェックリストのフェーズ期間(
pre_checklist、checklist_to_propose、post_propose、post_checklist_no_propose)と、評価と実装の割合を算出します - ログが大きい場合は、ワークフロー分析を並列化します。エージェント/ワークフローのレーンごとにサブエージェントを割り当て、タイミング表を統合します
- Logfire に問い合わせて、trace_id とタイミングデータを取得します(利用可能な場合。レート制限がある場合は待機して再試行します)
- streaming_debug.log を分析して、コマンドのパターンを確認します
- vote.json ファイルを確認して、エージェントの推論を調べます
- テンプレートを使用してレポートを生成します
- 次の場所に保存します:[log_dir]/turn_N/ANALYSIS_REPORT.md(N は分析対象のターン番号)
- 概要をユーザーに表示します
- 調査結果に基づいて Linear の課題を提案します。セッションが対話形式の場合は、ユーザーに承認を求めます
- 承認された課題を
log-analysisラベル付きで Linear に作成します
パート 7:クイックリファレンス — SQL クエリ
正確性に関するクエリ
-- Check coordination flow
SELECT span_name, start_timestamp, duration
FROM records
WHERE trace_id = '[TRACE_ID]'
AND (span_name LIKE 'Coordination event:%'
OR span_name LIKE 'Agent answer:%'
OR span_name LIKE 'Agent vote:%'
OR span_name LIKE 'Winner selected:%'
OR span_name LIKE 'Final answer%')
ORDER BY start_timestamp
効率性に関するクエリ
-- Phase duration breakdown
SELECT
CASE
WHEN span_name LIKE 'agent.%.round_0' THEN 'initial_answer'
WHEN span_name LIKE 'agent.%.round_%' THEN 'voting'
WHEN span_name LIKE 'agent.%.presentation' THEN 'presentation'
ELSE 'other'
END as phase,
COUNT(*) as count,
ROUND(AVG(duration)::numeric, 2) as avg_duration_sec,
ROUND(MAX(duration)::numeric, 2) as max_duration_sec,
ROUND(SUM(duration)::numeric, 2) as total_duration_sec
FROM records
WHERE trace_id = '[TRACE_ID]'
AND span_name LIKE 'agent.%'
GROUP BY 1
ORDER BY total_duration_sec DESC
エラーに関するクエリ
-- Find all exceptions
SELECT span_name, exception_type, exception_message, start_timestamp
FROM records
WHERE trace_id = '[TRACE_ID]' AND is_exception = true
ORDER BY start_timestamp
コストに関するクエリ
-- Token usage by agent
SELECT
attributes->>'massgen.agent_id' as agent,
SUM((attributes->'massgen.usage.input')::int) as total_input_tokens,
SUM((attributes->'massgen.usage.output')::int) as total_output_tokens,
SUM((attributes->'massgen.usage.cost')::float) as total_cost_usd
FROM records
WHERE trace_id = '[TRACE_ID]'
AND span_name LIKE 'agent.%'
AND attributes->>'massgen.usage.input' IS NOT NULL
GROUP BY attributes->>'massgen.agent_id'
パート 8:経過時間のフェーズ分析
経過時間のボトルネックを調べる際は、ラウンドごと、エージェントごとに作業をフェーズに分け、思考時間とツール実行時間を算出して、クリティカルパスを特定します。このセクションは、その分析を行う際の参考資料です。
フェーズの分類
ラウンド内のエージェント作業の各区間は、次のいずれかのカテゴリに分類します。
| カテゴリ | 説明 | シグナル |
|---|---|---|
| THINKING | ツール呼び出しを伴わないモデル推論(拡張思考、頭の中での計画) | ラウンド内で最初の tool_start の前に長い空白がある、またはツール呼び出しがまったくない |
| SCAFFOLD | プロジェクトのセットアップ作業(changedoc、CONTEXT.md、タスク計画、スキル文書の読み込み) | 計画文書への write_file、openskills read、ラウンド開始時のタスクステータス更新 |
| BUILD | 成果物の作成または書き換え | 生成ツール、スクリプト、アセットに対する write_file/execute_command |
| VERIFY | 成果物の正確性の確認 | read_media、スクリーンショットのキャプチャ、ピクセル差分、ファイル構造の確認 |
| FIX | 検証で見つかった問題の修正 | VERIFY ブロックの直後に続く編集/書き換えのサイクル |
| SCORE | チェックリストの評価と改善計画 | submit_checklist、draft_approach、診断レポート |
| HANDOFF | ラウンド終了時の記録作業 | 検証メモ、必須ファイルのマニフェスト、タスクステータスの完了への更新 |
| WASTE | 非生産的な作業(迷走、失敗の繰り返し) | 同じアプローチで 3 回以上連続して失敗する、ツールのクラッシュ、環境の問題 |
execution_trace.md または events.jsonl を読み、目的ごとに連続したツール呼び出しをまとめてカテゴリを割り当てます。密接に入り交じっている場合は、1 つのブロックに複数のカテゴリ(例:VERIFY+FIX)を含めてもかまいません。
events.jsonl から思考時間とツール実行時間を計算する
主なデータソースは、試行ディレクトリ内の events.jsonl です。各行には、timestamp(ISO)、event_type、agent_id、round_number、data フィールドを含む JSON オブジェクトがあります。
関連するイベントタイプ:
| イベントタイプ | 主な data フィールド | 備考 |
|---|---|---|
round_start | — | エージェントのラウンド開始を示します |
round_end | — | ラウンドの終了を示します |
tool_start | tool_id、tool_name、args、server_name | ツール実行の開始 |
tool_complete | tool_id、tool_name、elapsed_seconds、status | ツール実行の終了 |
アルゴリズム:
- イベントを
agent_idとround_numberで絞り込みます。 tool_idを使ってtool_startとtool_completeを対応付けます。- すべての
[tool_start.timestamp, tool_complete.timestamp]区間の和集合を、ツール実行時間として計算します(並行/バックグラウンドのツールについて、重複する区間を結合します)。 - 思考時間 = ラウンドの所要時間 − ツール実行時間の和集合。この時間には、モデルの推論、API レイテンシ、SDK のオーバーヘッド、追跡されていない空白時間が含まれます。
- 各フェーズブロック(同じカテゴリのツール呼び出しが連続するまとまり)について、思考時間(ツール間の空白時間)と実行時間(ツールの所要時間)を個別に報告します。
from datetime import datetime
from collections import defaultdict
def parse_events(events, agent_id, round_number):
"""Return tool intervals and round boundaries for one agent-round."""
starts = {} # tool_id -> timestamp
intervals = []
round_start = round_end = None
for e in events:
if e["agent_id"] != agent_id:
continue
ts = datetime.fromisoformat(e["timestamp"])
if e["event_type"] == "round_start" and e["round_number"] == round_number:
round_start = ts
elif e["event_type"] == "round_end" and e["round_number"] == round_number:
round_end = ts
elif e["event_type"] == "tool_start" and e["round_number"] == round_number:
starts[e["data"]["tool_id"]] = ts
elif e["event_type"] == "tool_complete" and e["round_number"] == round_number:
tid = e["data"]["tool_id"]
if tid in starts:
intervals.append((starts[tid], ts, e["data"]["tool_name"]))
return round_start, round_end, intervals
def compute_think_vs_exec(round_start, round_end, intervals):
"""Return total think and exec seconds, plus merged exec intervals."""
if not round_start or not round_end:
return 0, 0
# Merge overlapping intervals
sorted_iv = sorted((s.timestamp(), e.timestamp()) for s, e, _ in intervals)
merged = []
for s, e in sorted_iv:
if merged and s <= merged[-1][1]:
merged[-1] = (merged[-1][0], max(merged[-1][1], e))
else:
merged.append((s, e))
exec_total = sum(e - s for s, e in merged)
round_total = (round_end - round_start).total_seconds()
return round_total - exec_total, exec_total
クリティカルパスの特定
各ラウンドのクリティカルパスエージェントは、そのラウンドの実時間が最も長いエージェントです。ラウンド内ではエージェントが並行して実行されるためです。
- 各ラウンドについて、最大の(エージェントのラウンド所要時間)を求めます。そのエージェントに
[CP]の印を付けます。 - すべてのラウンドにおける CP エージェントの所要時間に、ラウンド前に実行されるブロッキングフェーズ(基準の生成、分解)を加算し、クリティカルパスの合計時間を求めます。
- クリティカルパスの内訳は、実時間が実際にどこで使われているかを示します。新たなボトルネックにならない限り、CP ではないエージェントを最適化しても意味はありません。
出力テーブルの形式:
| フェーズ | 所要時間 | 合計に占める割合 |
|---|---|---|
| Criteria gen | Xm | X% |
Round 0 (agent_b) [CP] | Xm | X% |
Round 1 (agent_a) [CP] | Xm | X% |
抽出する主要な指標
TTFT(最初のツール呼び出しまでの時間): そのラウンドにおけるエージェントの round_start から、最初の tool_start までの時間です。TTFT が長い(2 分超)場合、モデルが行動を起こす前に拡張思考で計画を立てていることを示します。TTFT が一貫して長いエージェントは、ツールを段階的に使うよう促すプロンプト変更の候補です。
bg_wait 時間: custom_tool__wait_for_background_tool 呼び出しの合計所要時間(events.jsonl 内で tool_id を使って対応付けるか、tool_name に wait_for_background_tool が含まれる tool_complete イベントの elapsed_seconds を合計します)。これは、エージェントが read_media や generate_media などの非同期処理を待つためにブロックされている時間を測定します。
タイプ別のツール呼び出し回数: エージェントごと、ラウンドごとに tool_start イベントを tool_name でグループ化します。計画用ツールの呼び出し回数が多い場合(例:タスクステータスの更新が 24 回)、またはコマンドの失敗が繰り返される場合は、調査すべきオーバーヘッドがあることを示します。
ラウンドごとのコスト: metrics_summary.json、またはエージェントのラウンドスパンごとの Logfire massgen.usage.cost 属性から取得します。
既知のデータ不足
| 不足 | 影響 | 測定できないこと |
|---|---|---|
| Claude Code のバックエンドには API のタイミング計測がない | 思考時間を API レイテンシ、モデルの推論、SDK オーバーヘッドに分解できません | claude_code.py は start_api_call_timing/end_api_call_timing を呼び出しません。13 分の TTFT はブラックボックスです。 |
| Codex はツール呼び出しごとではなく、ラウンドごとに API 呼び出しを 1 回記録します | 個々のツール間の思考時間の差を分解できません | TTFT はセッションレベルでのみ利用可能で、ツール間の空白時間は不明です。 |
| 推論と出力生成を分けられません | 長い空白時間が、モデルの思考によるものか、大きな出力(例:90KB の SVG)の生成によるものか判断できません | すべてのバックエンドに該当します。 |
| read_media/generate_media には内部のタイミング計測がありません | マルチモーダルモデルのレイテンシと、バックグラウンドのツールフレームワークのオーバーヘッドを区別できません | 内訳のない 30~70 秒の待ち時間が発生します。 |
| Criteria gen サブエージェントにはターンごとの内訳がありません | ラウンド開始前のブロッキング時間について、内部のステップが見えません | 合計所要時間のみ利用可能です。 |
これらの不足が分析に影響する場合は、推測するのではなく、レポートで明示してください。実行可能な課題として、計測の修正(例:「Claude Code バックエンドに API のタイミング計測を追加する」)を推奨してください。
フェーズ分析レポートの構成
壁時計時間のフェーズ分析を作成する場合は、エージェントごと、ラウンドごとに次の構成を使用してください。
### ROUND N -- Xm wall time | $X.XX
#### agent_id (Backend / Model) -- Xm | $X.XX | N tools [CP]
| # | Category | Duration | Think | Exec | Tools | What |
|---|----------|----------|-------|------|-------|------|
| 1 | SCAFFOLD | 0.9m | 0.9m | 0.0m | 3 | Create changedoc, task plan |
| 2 | BUILD | 4.4m | 4.4m | 0.0m | 6 | Write SVG generator |
| ... | | | | | | |
| | **Total** | **Xm** | **Xm** | **Xm** | **N** | |
続けて、以下を記載してください。
- クリティカルパスの概要テーブル(ラウンドごとの CP エージェント、クリティカルパスの合計時間)
- カテゴリ別集計(クリティカルパスのみ:全ラウンドのカテゴリ別時間の合計)
- 時間の内訳(モデルの思考、TTFT、bg_wait、シェルコマンド、その他のツール実行、未計上)
- 構造的なパターン(繰り返される足場、終わりのない改善ループ、無駄な寄り道など、重要な所見を番号付きリストで記載)
- 実行可能な改善機会(壁時計時間への影響が大きい順)