过程分析 · 轨迹阅读 · 第 1 讲
读一条 Agent 轨迹:八阶段解题过程模型
Agent 做完一道 SWE-bench 题,会留下一条完整的解题轨迹(trajectory)——推理日志、工具调用、执行输出,一应俱全。 但轨迹不是流水账:对 5 个真实任务的约 1700 行推理日志做行为序列抽取后,会发现 Agent 解题有一个稳定的八阶段结构, 每个阶段由谁控制(Prompt 骨架还是 Agent 自主)、在哪里形成循环、在哪里走弯路,都有规律可循。 这一页教你像读源码一样读轨迹——它是后续两讲(PRA 过程评分、问题 step 分类)的地基。
概览
8
解题阶段(S0-S7)
5
真实任务实证
3
层嵌套结构
2
迭代循环
| 项目 | 说明 |
|---|---|
| 本卡定位 | 「轨迹分析与过程评估」单元第 1 讲 · 学会读轨迹(结构化视角) |
| 前置知识 | 知道 SWE-bench 任务是什么(swe-bench-intro);知道 Agent = harness + LLM(agent-harness-loop) |
| 读完会什么 | 拿到一条 Agent 推理日志,能按 S0-S7 划分阶段边界、标出控制源、识别循环与弯路;理解「Prompt 骨架决定做什么,Agent 决定怎么做」的人机分工 |
| 实证数据 | 5 个真实任务(最短 99 行日志、最长 902 行),全部可在本仓 experiments/ 与归档复盘中对照 |
第一篇 · 轨迹长什么样:三层嵌套结构
第 1 讲 · 1 模型 + 1 图
图 1 · 三层嵌套模型:L1 是 Agent 的"内心博弈",L2 是人注入的约束,L3 是实际干活的过程。
三层嵌套:元决策层 · Prompt 骨架层 · Agent 执行层
一条轨迹(如 .traj 文件或 kimi-run.log 推理日志)记录了 Agent 从收到任务书到交付补丁的全部行为:思考段(读题、归因、方案对比)与动作段(读文件、装依赖、跑测试、改代码)。把 5 份日志的行为序列抽出来对齐,会发现它们共享同一个三层嵌套骨架:
flowchart TB
L1["L1 元决策层 · Pre-flight
检查可用 Skill → 权衡指令优先级 → 制定计划
控制源:Agent 自主"] L2["L2 Prompt 骨架层 · 外部约束
步骤顺序 STEP1-8 · 约束红线 · 输出格式
控制源:外部注入(人写的任务书)"] L3["L3 Agent 执行层 · 实际动作
理解 → 探索 → 复现 → 定位 → 修复 → 验证
控制源:Agent 自主 + 骨架约束
内含弯路恢复子循环(按需触发)"] L1 --- L2 L2 --- L3
检查可用 Skill → 权衡指令优先级 → 制定计划
控制源:Agent 自主"] L2["L2 Prompt 骨架层 · 外部约束
步骤顺序 STEP1-8 · 约束红线 · 输出格式
控制源:外部注入(人写的任务书)"] L3["L3 Agent 执行层 · 实际动作
理解 → 探索 → 复现 → 定位 → 修复 → 验证
控制源:Agent 自主 + 骨架约束
内含弯路恢复子循环(按需触发)"] L1 --- L2 L2 --- L3
| 层 | 职责 | 控制源 | 实证证据 |
|---|---|---|---|
| L1 元决策层 | 检查可用 Skill、权衡指令优先级、制定计划 | Agent 自主 | 每份日志开头固定的"要不要调 skill"内心博弈(如 sqlfluff-1733 前 60 行) |
| L2 Prompt 骨架层 | 规定步骤顺序(STEP 1~8)、约束(不改测试文件)、输出格式(以 git diff 结尾) | 外部注入 | 出题器渲染的 ca-task-prompt.md 任务书模板 |
| L3 Agent 执行层 | 实际的文件读写、命令执行、代码编辑、推理决策 | Agent 自主 + 骨架约束 | 日志中的工具调用与执行输出 |
核心洞察(人机分工第一课):Prompt 骨架决定"做什么、按什么顺序做",Agent 执行层决定"具体怎么做、卡住了怎么办"。
两层之间存在张力——Agent 可能因环境弯路偏离骨架顺序(如 pvlib-1072 在复现阶段反复修环境,环境修复耗掉日志约 60% 的篇幅)。
读轨迹时先分清"这一步是任务书要求的,还是 Agent 自己的决定",很多问题就出在两者的错位上。
素材:wiki/32 §二 三层嵌套模型
关联:harness + LLM 心智
第二篇 · 八阶段模型:S0 元决策到 S7 交付
第 2 讲 · 8 阶段 + 1 流程图
图 2 · 八阶段流程图:实线主干之外有两个关键循环——S3 自循环(环境修复)与 S6→S4 回退环(验证失败重新定位根因)。
S0 元决策 → S7 交付:每个阶段做什么、由谁控制
| 阶段 | 名称 | 目标 | 控制源 | 弯路高发 |
|---|---|---|---|---|
| S0 | 元决策 | Skill 检查 + 制定计划 | Agent 自主 | 否 |
| S1 | 理解任务 | 解析任务书(issue.json),建立任务表征 | Prompt 驱动 | 否 |
| S2 | 探索代码 | 定位嫌疑代码,理解数据结构与调用链 | Prompt 驱动 | 否 |
| S3 | 复现问题 | 构建环境并确认 bug 真实存在 | 混合 | 是 |
| S4 | 根因定位 | 锁定缺陷行(精确到行),制定修复策略 | Agent 自主 | 否 |
| S5 | 最小修复 | 按方案修改源码(不改测试文件) | Prompt 驱动 | 否 |
| S6 | 验证修复 | 确认修复有效且无回归 | Prompt 驱动 | 中 |
| S7 | 交付结果 | 产出 unified diff + 修复摘要 | Prompt 驱动 | 否 |
flowchart TB
Start([收到任务指令]) --> S0
S0["S0 元决策
Skill 检查 + 制定计划 · Agent 自主"] -->|计划就绪| S1 S1["S1 理解任务
读 issue.json 提取 F2P/P2P · Prompt 驱动"] -->|任务理解完成| S2 S2["S2 探索代码
定位嫌疑文件 梳理调用链 · Prompt 驱动"] -->|嫌疑代码定位| S3 S3["S3 复现问题 弯路高发
建 venv 装依赖 写 repro 脚本 · 混合控制"] -->|环境错误| S3fix["恢复循环
错误信号 → 归因 → 规避"] S3fix --> S3 S3 -->|bug 复现成功| S4 S4["S4 根因定位
追踪缺陷机理 选最小方案 · Agent 自主"] -->|方案确定| S5 S5["S5 最小修复
编辑源码 不碰测试文件 · Prompt 驱动"] -->|改动完成| S6 S6["S6 验证修复
重跑 repro + F2P + P2P · Prompt 驱动"] -->|测试失败| S4 S6 -->|repro 过 且 F2P 全过 且 P2P 全过| S7 S7["S7 交付结果
git diff + 修复摘要 · Prompt 驱动"] --> End([交付 unified diff])
Skill 检查 + 制定计划 · Agent 自主"] -->|计划就绪| S1 S1["S1 理解任务
读 issue.json 提取 F2P/P2P · Prompt 驱动"] -->|任务理解完成| S2 S2["S2 探索代码
定位嫌疑文件 梳理调用链 · Prompt 驱动"] -->|嫌疑代码定位| S3 S3["S3 复现问题 弯路高发
建 venv 装依赖 写 repro 脚本 · 混合控制"] -->|环境错误| S3fix["恢复循环
错误信号 → 归因 → 规避"] S3fix --> S3 S3 -->|bug 复现成功| S4 S4["S4 根因定位
追踪缺陷机理 选最小方案 · Agent 自主"] -->|方案确定| S5 S5["S5 最小修复
编辑源码 不碰测试文件 · Prompt 驱动"] -->|改动完成| S6 S6["S6 验证修复
重跑 repro + F2P + P2P · Prompt 驱动"] -->|测试失败| S4 S6 -->|repro 过 且 F2P 全过 且 P2P 全过| S7 S7["S7 交付结果
git diff + 修复摘要 · Prompt 驱动"] --> End([交付 unified diff])
控制源分布是模型的灵魂:8 个阶段里,S0 / S4 由 Agent 自主控制(要不要用工具、根因在哪——考验"智力"),
S1 / S2 / S5 / S6 / S7 由 Prompt 驱动(按任务书规定的顺序与红线走——考验"约束设计"),
S3 是混合(Prompt 要求复现,但环境修复靠 Agent 自主恢复)。
出题人优化 Prompt 骨架,本质上是在优化这 5 个 Prompt 驱动阶段的确定性。
两个真实阶段的实证切片
- S2 探索(astroid-1196):读 node_classes.py → 发现 Dict.getitem 中 DictUnpack 分支直接调 value.getitem(),而 value 是无该属性的 Name 节点——嫌疑代码定位完成
- S4 根因(sqlfluff-1733):"prev_newline 在第一个空白段后被置 False,导致第二个空白段被误判为多余空格"——根因陈述精确到变量与条件
- S5 修复的实测规模:5 个任务的改动量为 1 行(sqlfluff-1733)~ 13 行(astroid-1196),git status 验证无一触碰测试文件
素材:wiki/32 §三 八阶段定义
第三篇 · 流程不是直线:两个循环 + 弯路恢复模式
第 3 讲 · 2 循环 + 5 弯路实证
S3 环境修复循环与 S6→S4 验证回退环
| 循环 | 触发条件 | 路径 | 性质 |
|---|---|---|---|
| S3 内部环境修复循环 | 环境类错误:解释器缺失、依赖不兼容、权限被拦截 | 复现失败 → 诊断环境错误 → 调整(换 Python / 降依赖版本)→ 重试 | 阶段内闭环,不回退前序阶段 |
| S6→S4 验证失败回退环 | F2P 测试未通过,或 P2P 出现回归 | S5 修复完成 → S6 验证 → 仍失败 → 回 S4 重新定位根因 → 再修复 → 再验证 | 全流程最体现"智能"的部分——Agent 要根据失败信号修正对根因的判断 |
弯路恢复模式:固定四元组
每个弯路都遵循 错误信号 → 归因 → 规避策略 → 验证绕过成功 的固定结构。以下是 5 个实测任务里记录到的弯路库:
| # | 错误信号 | 归因 | 规避策略 |
|---|---|---|---|
| 1 | python: command not found | 系统仅有 python3 | 改用 python3 |
| 2 | SafeConfigParser AttributeError | Python 3.14 移除旧 API | 降级到 python3.11 重建 venv |
| 3 | np.Inf AttributeError | NumPy 2.0 破坏性变更 | 固定 numpy<2(配 pandas 1.x) |
| 4 | ModuleNotFoundError: wrapt | 依赖未安装 | pip install 缺失包 |
| 5 | /tmp 写入被拦截 | IDE sandbox 限制 | 工作目录放项目目录内 |
弯路库的教学用法:它可随实验积累持续扩充。出题时针对已知弯路在题目 hints 中预埋提示(如注明 Python 版本要求),能直接减少 Agent 的弯路耗时——
这是"人从轨迹里学到的知识,反哺给下一次人机协作"的最小闭环。
素材:wiki/32 §四-§五
第四篇 · 会读轨迹之后:应用与量化发现
第 4 讲 · 1 量化发现 + 5 应用
日志长度 ≈ 任务复杂度的代理指标
5 个实证任务里,最简任务(marshmallow-1343)日志仅 99 行,最难的(astroid-1196)达 902 行,5 份合计约 1700 行。 日志越长,Agent 经历的推理轮次与环境弯路越多——这个相关性让"日志行数"成为出题时预判任务难度的廉价信号。
| 任务 | instance_id | 日志行数 | 结果 |
|---|---|---|---|
| 1 | pylint-dev__astroid-1196 | 902 | resolved |
| 2 | sqlfluff__sqlfluff-1733 | 399 | resolved |
| 3 | sqlfluff__sqlfluff-2419 | 169 | resolved |
| 4 | pvlib__pvlib-python-1072 | 148 | gold 冒烟失败(环境不兼容) |
| 5 | marshmallow-code__marshmallow-1343 | 99 | resolved |
五个应用场景
- 轨迹标注:把推理日志按阶段 Schema 标注成结构化数据,统计各阶段耗时与动作数(本仓 step_annotator 已做自动化)
- 难度预判:用各阶段动作数、回退次数、日志长度作为任务难度特征(出题选型参考)
- 流程监控:orchestrator 按 phase_id 追踪 Agent 进度,支持断点判断与心跳观测
- 出题设计:针对弯路高发的 S3 阶段,在题目 hints 中预埋环境提示(Python 版本、依赖版本)
- Prompt 优化:明确哪些阶段该由 Prompt 约束(S1/S2/S5/S7)、哪些该留给 Agent 自主(S0/S4)——约束放错位置要么勒死灵活性、要么放跑风险
思考与讨论
- 同一段日志里,你怎么区分"Agent 自主的探索"与"任务书要求的步骤"?找一条真实轨迹试着标出控制源边界。
- S3 复现阶段是弯路高发区——如果允许你在任务书里加 3 行提示,你会写什么?依据是哪条弯路?
- "日志长度 ≈ 复杂度"在什么情况下会失效?(提示:一个反复读大文件但从不改代码的 Agent)
素材:wiki/32 §1.3/§八
下一篇:给过程打分(PRA)
收口:这一讲在全单元的位置
一页总结:轨迹 = L1 元决策 + L2 Prompt 骨架 + L3 执行的三层嵌套;L3 可展开为 S0-S7 八阶段,
控制源在"Agent 自主 / Prompt 驱动 / 混合"之间分布;S3 自循环与 S6→S4 回退环是智能的集中体现;弯路遵循"错误信号→归因→规避"四元组。
- 下一篇(PRA):把这一讲的结构变成可打分的量表——复现先行 10 分、验证真实性 25 分、一票否决……
- 第三篇(分类学):把轨迹里的"问题 step"分成无用 / 冗余 / 低效 / 错误四类,配上真实数据案例
- 第四篇(点+线与 Linting):把单条轨迹的分析抬升到方法论层级,看长时序与形式化检查