mcpField
M
massgen-log-analyzer

massgen-log-analyzer

github.com/massgen测试与质量1.1k87 次安装20 周前更新
代码仓库

关于 massgen-log-analyzer

为 MassGen 实验提供运行、追踪和日志分析流程的技能,面向调试多 Agent 协作与性能的开发者。可结合 Logfire 查询追踪,也能从本地日志生成 Markdown 报告。

主要功能

  1. 01运行并监测 MassGen 实验
  2. 02分析本地日志与 Logfire 追踪
  3. 03检查 Agent 行为和协作
  4. 04定位性能瓶颈与异常
  5. 05生成 Markdown 分析报告

适用场景

  1. 01排查 Agent 重试及失败原因
  2. 02比较多轮实验的耗时表现
  3. 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 实验
  • 分层查询和分析跟踪记录
  • 调试 Agent 行为和协作模式
  • 衡量性能并识别瓶颈
  • 改进日志结构本身
  • 生成 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 在指定的日志目录中使用此技能。

多 Agent 自我分析
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,让多个 Agent 从不同角度(正确性、效率、行为)分析日志,并生成一份综合的 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 决策(位于 agent_*/*/vote.json)
  • 查看协调流程表(位于 coordination_table.txt)
  • 获取费用和令牌汇总(位于 metrics_summary.json)

在以下情况下使用 Logfire:

  • 需要精确到毫秒的计时数据
  • 分析 Span 层级和父子关系
  • 查找异常和错误堆栈跟踪
  • 创建可分享的追踪链接以便协作
  • 跨多个会话查询(例如,“查找所有出错的会话”)
  • 实时监控正在运行的实验

**速率限制:**如果 Logfire 返回速率限制错误,请等待最多 60 秒后重试,而不是改用本地日志。速率限制会很快重置;当需要进行计时/层级分析时,等待 Logfire 数据是值得的。

主要本地日志文件:

文件内容
status.json实时状态,包含 Agent 可靠性指标(强制执行事件、缓冲区丢失)
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): 这是最详细的调试资料。每个 Agent 快照都包含一份执行追踪,其中包括:

  • 完整的工具调用及完整参数(未截断)
  • 完整的工具结果(未截断)
  • 来自模型的推理/思考内容块
  • 时间戳和轮次标记

当你需要确切了解某个 Agent 做了什么以及原因时,请使用执行追踪——它会记录 Agent 在该次回答/投票迭代中看到和生成的所有内容。

强制执行可靠性(status.json): status.json 文件包含按 Agent 划分的可靠性指标,用于跟踪工作流强制执行事件:

{
  "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_toolAgent 调用了工具,但没有调用 vote 或 new_answer
no_tool_callsAgent 仅提供文本响应,未调用任何工具
invalid_vote_idAgent 投票给了不存在的 Agent ID
vote_no_answersAgent 在没有答案时尝试投票
vote_and_answerAgent 在同一响应中同时使用了 vote 和 new_answer
answer_limitAgent 达到答案数量上限
answer_novelty答案与现有答案过于相似
answer_duplicate答案与现有答案完全重复
api_errorAPI/流式传输错误(例如,“peer closed connection”)
connection_recoveryAPI 流提前结束,已通过保留的上下文恢复
mcp_disconnectedMCP 服务在会话中途断开连接(例如,“Server 'X' not connected”)

这些数据对于了解Agent 为何需要重试以及强制执行重启导致丢失了多少内容非常有用。

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 服务的读取令牌
  1. 前往 https://logfire.pydantic.dev/ 并登录
  2. 前往项目设置
  3. 创建一个读取令牌(这与用于身份验证的写入令牌不同)
  4. 复制此令牌,以便在步骤 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_id
  • agents[].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_namespan 的名称(例如,“agent.agent_a.round_0”)
span_id此 span 的唯一标识符
parent_span_id父 span 的 ID(根 span 为 null)
trace_id对单个跟踪记录中的所有 span 进行分组
duration时间,单位为秒
start_timestampspan 的开始时间
end_timestampspan 的结束时间
attributes包含自定义属性的 JSON 数据
message日志消息
is_exception表示是否发生错误的布尔值
exception_type异常类型(如果有)
exception_message异常消息
MassGen Span 层级结构

MassGen 会创建分层 span:

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_idAgent 标识符(agent_a、agent_b)
massgen.iteration当前迭代次数
massgen.round此 Agent 的轮次编号
massgen.round_type“initial_answer”、“voting” 或 “presentation”
massgen.backend后端提供方名称
massgen.num_context_answers上下文中的答案数量
massgen.is_winner在 presentation 跨度中为 True
massgen.outcome“vote”、“answer” 或 “error”(轮次完成后设置)
massgen.voted_for投票选中的 Agent ID(仅对投票设置)
massgen.voted_for_label投票选中的答案标签(例如,“agent1.1”,仅对投票设置)
massgen.answer_label分配的答案标签(例如,“agent1.1”,仅对答案设置)
massgen.error_message错误消息(仅当 outcome 为 “error” 时设置)
massgen.usage.input输入 token 数量
massgen.usage.output输出 token 数量
massgen.usage.reasoning推理 token 数量
massgen.usage.cached_input缓存的输入 token 数量
massgen.usage.cost以 USD 计的估算成本

第 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. Agent 轮次性能
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. 大模型调用性能
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

Agent 对比:

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.sessioncoordination_tracker.py根会话跨度
agent.{id}.round_{n}orchestrator.pyAgent 执行轮次
agent.{id}.presentationorchestrator.py获胜者的最终展示
mcp.{server}.{tool}mcp_tools/client.pyMCP 工具执行
llm.{provider}.streambackends大模型流式调用
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 中的 tracer:

from massgen.structured_logging import get_tracer

tracer = get_tracer()
with tracer.span("my_operation", attributes={
    "massgen.custom_key": "value",
}):
    do_work()
上下文传播说明

已知限制: 多个 Agent 通过 asyncio.create_task 并发运行时,子跨度可能无法正确嵌套在 Agent 轮次跨度下。这是 OpenTelemetry 在并发异步代码中的上下文传播问题。由于 presentation 阶段只有一个 Agent 运行,因此该阶段可以正常工作。

解决方法: 若要在并发场景中实现准确嵌套,需要通过 contextvars.copy_context() 显式传递上下文。

Logfire 文档参考

主要文档: https://logfire.pydantic.dev/docs/

需要了解的关键页面
主题URL描述
快速入门/docs/概览、设置和核心概念
手动追踪/docs/guides/onboarding-checklist/add-manual-tracing/创建 span、添加属性
SQL 浏览器/docs/guides/web-ui/explore/在界面中编写 SQL 查询
实时视图/docs/guides/web-ui/live/实时追踪监控
查询 API/docs/how-to-guides/query-api/以编程方式访问数据
OpenAI 集成/docs/integrations/llms/openai/对大模型调用进行插桩
Logfire 概念

Span 与日志:

  • Span 表示具有可测量持续时间的操作(使用 with logfire.span():)
  • 日志 捕获某一时刻发生的事件(使用 logfire.info()、logfire.error() 等)
  • Span 块内的 span 和日志会成为该 span 的子项

Span 名称与消息:

  • 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 实时视图界面(https://logfire.pydantic.dev/)提供:

  • 实时流式传输,在追踪到达时显示
  • SQL 搜索窗格(按 / 打开),支持自动补全
  • 自然语言转 SQL——描述所需内容并获取查询
  • 时间线直方图,显示一段时间内的 span 数量
  • 追踪详情面板,包含属性、异常和 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'
大模型插桩

配置后,Logfire 会自动为 OpenAI 调用插桩:

  • 捕获对话显示内容、令牌用量和响应元数据
  • 为流式请求和响应分别创建 span
  • 同时适用于同步和异步客户端

MassGen 的后端使用此功能创建 llm.{provider}.stream span。

参考文档

Logfire:

MassGen:

  • 自动化模式:AI_USAGE.md
  • 状态文件参考:docs/source/reference/status_file.rst
  • 结构化日志:massgen/structured_logging.py

高效分析提示

  1. 始终同时使用两个标志: --automation --logfire
  2. 长任务应在后台运行,以便监控进度
  3. 按 trace_id 查询,以隔离特定会话
  4. 检查 parent_span_id,以了解层级关系
  5. 使用 duration 识别瓶颈
  6. 查看 attributes,了解 MassGen 特定上下文
  7. 创建追踪链接,与团队分享发现

请注意,你可能会遇到如下错误:

Error: Error executing tool arbitrary_query: b'{"detail":"Rate limit exceeded for organization xxx: per minute
     limit reached."}'

遇到这种情况时,请等待片刻(最多一分钟)后重试。

第 6 部分:全面日志分析报告

收到分析 MassGen 日志运行的请求时,请生成一份 Markdown 报告,并保存到 [log_dir]/turn_N/ANALYSIS_REPORT.md,其中 N 为正在分析的轮次。每个轮次(协调会话)都应有独立的分析报告,与尝试目录处于同一级。报告必须涵盖下方的标准分析问题。

重要:基准答案与正确性

关键:除非用户明确提供基准答案,否则不要假定任何 Agent 的回答是“正确的”。

  • 报告每个 Agent 声称或给出的内容,不要断言其正确性
  • 说明 Agent 之间是否一致或有分歧,但不要声称一致就代表正确
  • 如果 Agent 给出的答案不同,请中立地呈现双方答案
  • 只有在用户提供实际答案时,才将答案标记为正确或错误
  • 避免使用的表述:“正确地识别出”“给出了正确答案”“正确地解决了”
  • 建议使用的表述:“声称”“给出”“提交”“得出”
标准分析问题

每份分析报告都必须回答以下问题:

1. 正确性
  • 协调是否成功完成?
  • 所有 Agent 是否都提交了答案?
  • 投票是否正确进行?
  • 是否选出了获胜者,且该 Agent 是否给出了最终答案?
2. 效率与瓶颈
  • 总耗时是多少,各阶段分别耗时多少?
  • 最慢的操作有哪些?
  • 哪些工具耗时最长?
  • 构建一张按 Agent 排序的逐轮计时表,包括:
    • 回合开始/结束时间戳
    • 回合总耗时
    • 工具墙钟时间
    • 非工具耗时(模型/流式传输/等待)
  • 将每个包含清单的回合拆分为:
    • 评估 = 回合开始 -> 首次 submit_checklist 开始
    • 清单->提议 = 首次 submit_checklist 结束 -> 首次 draft_approach 开始
    • 实施 = 首次 draft_approach 结束 -> 回合结束
    • 清单后(无提议) = 首次 submit_checklist 结束 -> 回合结束(若未进行 draft_approach)
  • 报告评估与实施的时间占比:
    • 在所有包含清单的时段中
    • 仅在实际包含 draft_approach 的时段中
3. 命令模式分析
  • 是否频繁重复执行了本可避免的命令?(例如 openskills read、npm install、ls -R)
  • 哪些命令产生了不必要的长输出?(例如技能文档、目录列表)
  • 最慢的 execute_command 模式有哪些?(例如网页抓取、软件包安装)
4. 工作重复分析
  • 是否不必要地重复了耗时的工作(例如图像生成)?
  • 两个 Agent 是否生成了相似/相同的素材?
  • 是否在重启后重新生成素材,而没有复用?
  • 缓存或共享是否可以节省时间/成本?
5. Agent 行为与决策
  • **Agent 如何评估之前的答案?**他们给出了什么推理?
  • Agent 如何决定投票还是提供新答案?
  • Agent 是否确实在彼此工作的基础上继续推进,还是各自独立工作?
  • 是否发生超时或未完成的回合?
6. 成本与 Token 分析
  • 总成本及各 Agent 的成本明细
  • Token 用量(输入、输出、推理、缓存)
  • 缓存命中率
7. 错误与问题
  • 是否发生异常或失败?
  • 是否发生超时?
  • 是否存在 Agent 错误?
8. Agent 推理与行为分析(关键)

这是最重要的部分。 分析 Agent 的思考和行动方式,有助于揭示成功与失败的根本原因。

数据来源:

  • agent_outputs/agent_*.txt - 完整输出,包括推理内容(如果有)
  • agent_*/*/execution_trace.md - 完整的工具调用、参数和结果
  • streaming_debug.log - 原始流式数据块

注意:某些模型不会输出明确的推理轨迹。对于这些模型,应改为分析工具调用模式和内容——行动顺序依然能体现决策过程。

对每个 Agent 进行分析:

  1. 策略 - 它们采取了什么方法?(根据推理内容或工具调用顺序)
  2. 工具响应 - 它们如何处理成功、失败或不一致的结果?
  3. 错误恢复 - 它们是否发现了问题?是否采取了变通方案?
  4. 决策质量 - 是否存在逻辑错误?验证过度或不足?分析瘫痪?
  5. 跨 Agent 比较 - 哪个 Agent 的推理最佳?哪些模式带来了成功?

关键模式:

模式良好表现不良表现
故障检测失败 2-3 次后调整方向6 次或更多地重复无效方法
结果验证交叉验证输出不加核实地接受第一个结果
不一致处理调查冲突忽略矛盾
变通方案陷入困境时寻找创造性的替代方案放弃或陷入循环
时间管理有把握时提交无休止地验证,不给出答案

**提取关键证据:**对每个 Agent,引用 2-3 条内容(如果有推理记录),或描述能体现其决策质量的关键工具调用顺序。

9. 工具可靠性分析

分析工具行为模式,而不只是简单列出错误:

  1. 一致性 - 相同输入是否得到相同输出?记录差异。
  2. 误报/漏报 - 工具是否错误地报告成功或失败状态?
  3. 根因假设 - 针对每种故障模式,提出可能的原因(路径问题、速率限制、模型限制等)。
10. 强制执行与工作流可靠性分析

数据来源:status.json → agents[].reliability

检查 Agent 是否因违反工作流而需要重试。关键指标:

  • total_enforcement_retries - Agent 被强制重试的次数
  • total_buffer_chars_lost - 因重启而丢弃的内容量
  • unknown_tools - 幻觉出的工具名称
  • by_round - 出现问题的轮次

**危险信号:**每轮重试 >=2 次、丢失 >5000 个字符、unknown_tools 列表非空。

完整的数据结构和原因代码,请参阅“关键本地日志文件”部分中的“强制执行可靠性”。

11. 答案质量的演进

数据来源:agent_outputs/agent_*.txt、agent_*/*/execution_trace.md、agent_*/*/vote.json

对每个 Agent,追踪其答案质量在各轮中的变化:

  • 答案 N 与答案 N+1 之间具体发生了哪些变化?
  • 这些变化是实质性的(新方法、新功能、结构改进)还是表面性的(措辞上的细微调整、小幅风格修改)?
  • 是否有 Agent 在看到其他人的答案后退步,给出了更差的答案?
  • 哪些评估标准逐轮改善,哪些停滞不前?

对每轮之间的变化评分:

  • 🟢 实质性改进 — 至少在一个重要维度上有明显提升
  • 🟡 边际改进 — 表述更加完善,但没有新增能力或见解
  • 🔴 没有改进 / 出现退步 — 尽管付出了成本,答案仍相同或更差
12. 改进提案质量

数据来源: agent_outputs/agent_*.txt(查找差距分析、诊断部分、改进计划)、agent_*/*/vote.json

在给出每个新答案之前,Agent(或协调系统)都会提出改进建议。逐项分析:

  • 具体性:提案是否指出了问题失败的原因,还是只说明问题失败了?(“动画时长与 5 秒观看窗口不匹配”与“改进动画”)
  • 可执行性:下游 Agent 能否无需额外推理就实施该提案?
  • 准确性:提案是否正确诊断了根本问题,还是只处理了表面症状?
  • 完整性:提案是否涵盖所有关键差距,还是遗漏了决定性的差异点?

评估每项提案:

提案具体?可执行?准确?是否判断正确?
[提案摘要]是/否是/否是/否是/否 — [原因]

另请注明:改进建议是由 Agent 自行提出的(自我反思)、通过同行评估提出的,还是根据评估标准中的差距推断得出的。

13. 轮次投资回报(“值得吗?”)

数据来源: metrics_summary.json、coordination_events.json、Agent 输出

评估每一轮的投资回报:

  • 成本:本轮的 token 数量 × 模型费率
  • 耗时:本轮的实际用时(秒)
  • 质量变化:与之前的最佳答案相比,发生了哪些实质性变化
  • 结论:这一轮是否值得付出相应的成本和时间?
轮次Agent成本耗时质量变化结论
R0agent_a$XXs基线—
R1agent_a$XXs[变化内容]🟢/🟡/🔴

检测边际收益递减:从哪一轮开始,额外迭代不再带来有意义的改进?系统是否错过了明确的停止时机?

另请标记:是否有 Agent 花费高成本进行轮次迭代,却只是验证结果,而非改进结果?

14. 委派与模型分配分析

数据来源: agent_outputs/agent_*.txt、execution_trace.md、metrics_summary.json

分析每个 Agent 的工作中,机械性任务与需要真正智能的任务各占多少比例,以及是否使用了合适的模型层级。

按轮次分类每个 Agent 的工作:

  • 机械性任务(可预测、模板化、较弱的模型也能完成——且消耗的上下文足够多,值得委派):

    • 结构验证(元素数量、尺寸检查、格式合规性)——尤其是会生成大量 shell 输出的任务
    • 样板代码生成(循环、坐标计算、填充模板)——大量重复的代码块
    • 二元清单评分(E1–E4 风格:功能 X 是否存在?)——涉及许多工具调用或较长输出时
    • 证据收集(运行 shell 命令、解析输出、像素差异比较)——Token 成本高,但推理内容少

    注意:任务状态更新、工作流工具调用等协议步骤不值得委派——它们所需上下文少,主模型在行内处理的成本很低。关键在于委派是否能节省有意义的 Token,而不仅仅是较弱模型理论上能否完成。

  • 质量/智能(需要真正的推理、综合或创造力):

    • 根因诊断(将症状与底层设计缺陷联系起来)
    • 跨 Agent 综合(从 N 个答案中找出最佳要素,并规划混合方案)
    • 创新方案设计(提出以往答案中都没有的功能或设计)
    • 教学或领域推理(例如,“这个动画的节奏错过了 5s 的注意力窗口”)
    • 权衡分析(针对特定目标,解释为何一种设计选择优于另一种)

针对每个 Agent/轮次,估算:

  • 机械性任务与质量推理各占的百分比
  • 哪些具体活动属于机械性任务,哪些需要智能
  • 引用片段:机械式填充模板与真正的诊断洞见

总体评估:

  • 整个运行中,机械性任务占总上下文(Token)的多少?
  • 更便宜的模型(例如 Haiku)能否处理机械性任务,而不降低输出质量?
  • 是否有质量至关重要的环节交给了较弱的子 Agent(或本应升级模型)?
  • 如果将机械性任务分配给更便宜的模型层级,预计可节省多少成本?
各问题的数据来源
问题主要来源次要来源
正确性coordination_events.json、coordination_table.txtLogfire 协调事件
效率metrics_summary.jsonLogfire 耗时查询
命令模式streaming_debug.log(grep 搜索 "command":)-
工作重复streaming_debug.log(grep 搜索工具提示词/参数)metrics_summary.json 工具计数
Agent 决策agent_*/*/vote.json、coordination_events.jsonLogfire 投票跨度
评估与实现耗时status.json、metrics_events.jsonevents.jsonl、Logfire 跨度时长
成本/Tokenmetrics_summary.jsonLogfire 使用量属性
错误coordination_events.json、metrics_summary.jsonLogfire 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")'

计算每轮评估与实现的耗时(按 Agent 排序):

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]
生成报告的工作流
  1. 先读取本地文件(metrics_summary.json、coordination_table.txt、coordination_events.json、status.json、metrics_events.json)
  2. 构建按 Agent 排序的逐轮计时表,包括总时间、工具时间和非工具时间
  3. 计算清单阶段的时间窗口(pre_checklist、checklist_to_propose、post_propose、post_checklist_no_propose),以及评估和实现所占百分比
  4. 对于大型日志,并行分析工作流:为每个 Agent/工作流通道分配一个子 Agent,并合并其计时表
  5. 查询 Logfire,获取 trace_id 和计时数据(如果可用;遇到速率限制时请等待并重试)
  6. 分析 streaming_debug.log 中的命令模式
  7. 检查 vote.json 文件,了解 Agent 的推理过程
  8. 使用模板生成报告
  9. 保存到 [log_dir]/turn_N/ANALYSIS_REPORT.md(N = 正在分析的轮次)
  10. 向用户打印摘要
  11. 根据发现建议创建 Linear 事项——如果会话处于交互模式,请先征求用户批准
  12. 在 Linear 中使用 log-analysis 标签创建已批准的事项

第 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 部分:墙钟时间阶段分析

分析运行过程中的墙钟时间瓶颈时,请按每轮、每个 Agent 划分阶段,计算思考时间与工具执行时间,并确定关键路径。本节为执行此类分析提供参考。

阶段类别

每轮中 Agent 工作的每个片段都归入以下类别之一:

类别描述信号
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,按用途对连续的工具调用分组,并据此分配类别。如果多个阶段紧密交错,一个区块可以包含多个类别(例如 VERIFY+FIX)。

根据 events.jsonl 计算思考时间与工具执行时间

主要数据源是尝试目录中的 events.jsonl。每行都是一个 JSON 对象,包含以下字段:timestamp(ISO 格式)、event_type、agent_id、round_number、data。

相关事件类型:

事件类型data 中的关键字段说明
round_start—标记某个 Agent 一轮的开始
round_end—标记某一轮的结束
tool_starttool_id、tool_name、args、server_name工具开始执行
tool_completetool_id、tool_name、elapsed_seconds、status工具执行结束

算法:

  1. 按 agent_id 和 round_number 筛选事件。
  2. 根据 tool_id 配对 tool_start 和 tool_complete。
  3. 将所有 [tool_start.timestamp, tool_complete.timestamp] 时间区间合并,计算工具执行时间总和(并发或后台工具的重叠区间需合并)。
  4. 思考时间 = 一轮持续时间减去工具执行时间总和。该时间包括模型推理、API 延迟、SDK 开销,以及任何未跟踪的间隔。
  5. 对于每个阶段区块(具有相同类别的连续工具调用组),分别报告思考时间(工具之间的间隔)和执行时间(工具执行时长)。
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
确定关键路径

每轮的关键路径 Agent 是该轮墙钟时间最长的 Agent,因为各 Agent 在一轮内并发运行。

  1. 对每轮,找出最长的 Agent 一轮持续时间,并将该 Agent 标记为 [CP]。
  2. 将所有轮次中 CP Agent 的持续时间与任何阻塞性的轮前阶段(标准生成、任务分解)相加,得到关键路径总时间。
  3. 关键路径细分展示了墙钟时间的实际去向——优化非 CP Agent 无关紧要,除非它成为新的瓶颈。

输出表格格式:

阶段持续时间占总时间的百分比
标准生成XmX%
第 0 轮(agent_b)[CP]XmX%
第 1 轮(agent_a)[CP]XmX%
要提取的关键指标

TTFT(首次工具调用时间): 从该 Agent 在该轮的 round_start 到首次 tool_start 的时间。较长的 TTFT(>2 min)表示模型在采取行动前进行了较长时间的扩展思考。TTFT 持续偏高的 Agent 值得考虑调整提示词,以鼓励渐进式使用工具。

bg_wait 时间: custom_tool__wait_for_background_tool 调用的总时长(在 events.jsonl 中根据 tool_id 配对,或对 tool_name 包含 wait_for_background_tool 的 tool_complete 事件中的 elapsed_seconds 求和)。这用于衡量 Agent 等待 read_media 或 generate_media 等异步工作的阻塞时间。

按类型统计工具调用次数: 按 Agent 和轮次对 tool_start 事件中的 tool_name 分组。规划工具调用次数过多(例如,24 次任务状态更新)或重复失败的命令,都表明存在值得调查的开销。

每轮成本: 从 metrics_summary.json 获取,或从每轮 Agent span 的 Logfire massgen.usage.cost 属性获取。

已知数据缺口
缺口影响无法测量的内容
Claude Code 后端没有 API 计时无法将思考时间拆分为 API 延迟、模型推理和 SDK 开销claude_code.py 不会调用 start_api_call_timing/end_api_call_timing。13 分钟的 TTFT 是个黑箱。
Codex 每轮跟踪 1 次 API 调用,而非每次工具调用无法分解各个工具之间的思考间隔只能在会话级别获取 TTFT;工具间隔无法查明。
未区分推理和输出生成无法判断较长的间隔是模型思考还是生成大量输出(例如 90KB 的 SVG)适用于所有后端。
read_media / generate_media 没有内部计时无法区分多模态模型延迟与后台工具框架开销等待时间为 30-70 秒,但没有细分。
Criteria gen 子 Agent 没有逐轮细分阻塞式轮次前时间不可见,无法了解内部步骤只能获取总时长。

如果这些缺口影响分析,请在报告中明确说明,不要猜测。建议将计时功能改进(例如“为 Claude Code 后端添加 API 计时”)列为可执行事项。

阶段分析报告结构

生成墙钟时间阶段分析时,按每个 Agent 的每一轮使用以下结构:

### 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** | |

后续内容包括:

  • 关键路径摘要表格(每轮中哪个 Agent 位于关键路径上、关键路径总时间)
  • 类别汇总(仅关键路径:汇总所有轮次中各类别的时间)
  • 总时间细分(模型思考、TTFT、bg_wait、Shell 命令、其他工具执行、未计入项)
  • 结构模式(关键观察事项的编号列表:重复脚手架、无限改进循环、浪费时间的探索等)
  • 按墙钟时间影响排序的可执行机会

评论

支持 Markdown