SWE-agent Traj Analysis
SWE-Agent Trajectory 分析报告
Traj 文件:
scikit-learn__scikit-learn-i25076.traj分析日期: 2026-07-06
目录
- 什么是 SWE-Agent 和 Traj 文件?
- 本次任务概述
- Traj 文件结构详解
- Agent 执行过程逐步分析
- 核心问题诊断
- 失败原因深度分析
- 关键指标与数据
- 初学者阅读 Traj 的指南
- 总结与启示
1. 什么是 SWE-Agent 和 Traj 文件?
SWE-Agent 是什么?
SWE-Agent 是一个自动化软件工程 Agent。它像是一个 AI 程序员,能够:
- 阅读 GitHub 上的 Issue / PR 描述
- 理解需要修改什么代码
- 自己在代码仓库中搜索、读取文件
- 编写脚本复现问题
- 修改源代码来修复 Bug
- 验证修复是否生效
可以把 SWE-Agent 想象成一个”AI 初级工程师”,你给它一个任务描述,它会自动尝试完成。
Traj(Trajectory)文件是什么?
Traj = Trajectory = 轨迹。这个文件记录了 Agent 的每一步思考和行动,就像一个”黑匣子”:
- Agent 看到了什么(observation / 观察)
- Agent 想了什么(thought / 思考)
- Agent 做了什么(action / 动作)
- 花了多长时间(execution_time / 执行时间)
- 结果是什么(observation / 观察结果)
阅读 traj 文件,就像回放 Agent 的整个工作过程。这对于调试、分析失败原因、改进 Agent 非常有价值。
本次使用的模型
从配置文件可以看到,本次使用的是
openai/qwen-local——一个部署在本地的
Qwen(通义千问)开源模型,通过
http://localhost:8000/v1 提供 API 服务。这不是
GPT-4 或 Claude 等高级模型,而是一个本地运行的开源小模型。
2. 本次任务概述
任务来源
- 仓库: scikit-learn/scikit-learn(著名的 Python 机器学习库)
- Issue: #25076 → 对应的 PR 为 #25024
任务内容
在 scikit-learn 的文档配置文件
doc/conf.py中,将以下 URL 添加到linkcheck_ignore列表中:
1 https://github.com/joblib/threadpoolctl/#setting-the-maximum-size-of-thread-pools
背景说明: - scikit-learn 使用 Sphinx 构建文档 -
Sphinx 的 linkcheck 功能会自动检查文档中外链的有效性 -
但是有些链接在浏览器中可以正常打开,却因为各种原因被
linkcheck 误报为”broken”(损坏的链接) -
linkcheck_ignore 是一个配置列表,放在
doc/conf.py 中,用来告诉 Sphinx “这些链接不用检查” - 这个
PR 的目的就是把 threadpoolctl 的链接加入忽略列表
一句话总结:这个任务非常简单——找到配置文件,在已有的忽略列表里加一行 URL。
3. Traj 文件结构详解
这个 traj 文件是一个 JSON 格式的文件,包含以下几个顶层字段:
1 | ├── trajectory (核心) - 28 个步骤的详细记录 |
3.1 trajectory 数组中每个步骤的结构
每一步(step)都是一个 JSON 对象:
1 | { |
重要字段说明:
| 字段 | 含义 | 谁看 |
|---|---|---|
action |
Agent 决定执行的 bash 命令 | 环境执行 |
observation |
命令的 stdout/stderr 输出 | 反馈给 Agent |
response |
Agent 生成的自然语言回复 | 用户看到 |
thought |
Agent 的推理过程 | 用户看到 |
query |
发送给 LLM 的完整 prompt | 模型处理 |
3.2 query 中的消息类型
每条 query 消息都有 message_type 标识:
| message_type | 含义 |
|---|---|
system_prompt |
系统提示词,定义 Agent 的角色 |
observation |
环境反馈(用户消息形式,包含执行结果) |
action |
Agent 的决策结果(模型输出) |
3.3 info 中的关键指标
1 | { |
4. Agent 执行过程逐步分析
整个轨迹共有 28 步(Step 0 ~ Step 27)。下面按照不同阶段来分析。
阶段一:重复的错误循环(Step 0 ~ Step 23,共 24 步)
这是整个轨迹最显著的特征——Agent 在 24 个连续步骤中做的是完全相同的事情。
每一步发生了什么呢?
Agent 的 Action(动作):
1 | python test_link.py |
Environment 的 Observation(反馈):
1
python: can't open file '//test_link.py': [Errno 2] No such file or directory
Agent 的 Response(回复) - 每次都几乎一样:
“To address the issue described in the PR description, we need to add the specified URL to the
linkcheck_ignorelist…”然后 Agent 会重复说明一个 5 步方案: 1. 找到并阅读相关代码 2. 创建一个
test_link.py脚本来复现错误 3. 编辑conf.py文件,添加 URL 4. 重新运行脚本验证修复 5. 考虑边缘情况
画成流程图
1 | ┌─────────────────────────────────────────────────┐ |
核心问题:Agent 在”说”但不在”做”
Agent 的 response 和 thought
中描述了要做的事情,但它的 action 从未跟进: - 它说”创建
test_link.py”但从不执行 echo '...' > test_link.py 或
cat > test_link.py - 它说”编辑 conf.py”但从不使用
str_replace_editor 工具 - 它说了 24
次”让我们找到配置文件”,但从未执行过 find 或
grep 命令
阶段二:尝试直接执行 Python 代码(Step 24 ~ Step 26,共 3 步)
在 Step 24-26 中,Agent 改变了行为——但仍然不对:
Step 24 的 Action:
1 | import subprocess |
Agent 开始尝试把 Python 代码直接当作 bash
命令执行。Bash 当然无法理解
import subprocess,所以这次更是毫无效果。
关键观察:Step 24-26 的 observation
都是空字符串,这说明命令可能: 1.
根本没有被执行(因为格式错误被拦截) 2. 执行了但不产生任何输出(比如
Python 解释器因为语法错误静默退出)
阶段三:终止(Step 27)
Step 27: - action: 空字符串 -
observation: 空字符串 - response: “Exit due to
repeated format/blocklist/bash syntax errors”
exit_status = exit_format
这表示 SWE-Agent 框架检测到 Agent 一直在产生格式错误(也许是输出无法被正确解析为 “讨论+命令” 的格式),达到了最大重试次数,强制终止了 Agent。
5. 核心问题诊断
5.1 问题一:HTML 实体编码(关键发现!)
仔细查看 action 中的内容,你会发现一个重大问题:
1 | "action": "python test_link.py\n" |
再看 response 中 Python 代码的写法:
1 | result = subprocess.run(['make', 'linkcheck'], capture_output=True, text=True) |
' 是 HTML 实体编码,代表单引号
'。这意味着:
Agent 的输出被 HTML 实体编码污染了!
当 Agent 尝试写文件时,如果内容中包含 ' 等 HTML
实体,那么写出来的 Python 代码就会是语法错误的。
这是 SWE-Agent 框架输出解析的问题,也可能是本地 Qwen 模型输出格式不规范导致解析器进行了错误的转义处理。
5.2 问题二:Agent 陷入了”描述循环”
这是典型的 LLM Agent 失败模式:
1 | Agent 发现错误 → Agent 描述解决方案 → Agent 不执行方案 → 再次遇到同样错误 → 再次描述方案 → ... |
为什么会这样?
可能的原因: 1. 模型能力不足:Qwen-local 是开源小模型,工具调用能力远不如 GPT-4/Claude 2. 上下文混乱:随着对话越来越长(52 条消息),模型迷失在上下文中 3. 缺乏工具使用训练:模型更擅长”解释怎么做”而不是”实际去做” 4. 框架格式限制:SWE-Agent 要求特定格式(DISCUSSION + 代码块),模型可能无法稳定生成
5.3 问题三:从未使用搜索工具
优秀的 SWE-Agent 执行流程应该是:
1 | 1. find / -name "conf.py" ← 找到配置文件 |
但本 Agent 的实际流程是:
1 | 1. python test_link.py ← 跳过所有搜索,直接运行不存在的脚本 |
Agent 从未执行过以下关键命令: - find —
搜索文件 - grep — 搜索内容 - ls — 列出目录 -
cat — 读取文件内容 - str_replace_editor —
编辑文件
5.4 问题四:没有尝试写文件
即使 Agent 知道要创建
test_link.py,它从未执行过真正的文件创建操作,比如:
1 | cat > test_link.py << 'EOF' |
或使用 str_replace_editor create /test_link.py。
6. 失败原因深度分析
6.1 直接原因表
| 序号 | 直接原因 | 严重程度 |
|---|---|---|
| 1 | Agent 重复执行不存在文件的命令 24 次 | ⭐⭐⭐⭐⭐ |
| 2 | 从未创建 test_link.py 脚本文件 |
⭐⭐⭐⭐⭐ |
| 3 | 从未使用搜索命令查找配置文件 | ⭐⭐⭐⭐⭐ |
| 4 | 从未编辑任何源代码文件 | ⭐⭐⭐⭐⭐ |
| 5 | HTML 实体编码污染 action 内容 | ⭐⭐⭐⭐ |
| 6 | Step 24-26 试图在 bash 中运行 Python 代码 | ⭐⭐⭐⭐ |
| 7 | 被框架因”格式错误”强制终止 | ⭐⭐⭐ |
6.2 根本原因分析
1 | ┌──────────────────────────────────────────────────┐ |
6.3 如果换用强模型会怎样?
假设相同的任务给 GPT-4 或 Claude,典型的正确执行路径可能是:
1 | Step 1: find / -name "conf.py" -type f |
7. 关键指标与数据
7.1 执行统计
| 指标 | 数值 | 说明 |
|---|---|---|
| 总步数 | 28 | 包括最后的空步骤 |
| 有效步骤 | 0 | 没有任何一步产生了有意义的文件修改 |
| 重复操作 | 24 次 | python test_link.py × 24 |
| 总执行时间 | ~3.8 秒 | 所有步骤的 execution_time 总和 |
| 实际修改文件数 | 0 | 没有编辑任何文件 |
| 退出状态 | exit_format |
因格式错误被强制退出 |
7.2 Token 消耗
| 指标 | 数值 |
|---|---|
| 发送 Token | 236,887 |
| 接收 Token | 15,035 |
| 总共 Token | 251,922 |
| API 调用次数 | 27 |
| 花费 | $0(本地模型) |
思考:23.7 万 token 全部浪费在重复循环中。如果 Agent 在第一步就正确工作,可能只需要 5000-10000 token 就能完成这个简单任务。
7.3 模型配置
| 参数 | 值 |
|---|---|
| 模型名称 | openai/qwen-local |
| 温度 | 0.0(确定性输出) |
| Top P | 1.0 |
| API 地址 | http://localhost:8000/v1 |
| 执行超时 | 30 秒/命令 |
| 总超时 | 1800 秒(30 分钟) |
| 重试次数 | 最多 20 次 |
8. 初学者阅读 Traj 的指南
8.1 拿到一个 Traj,应该看什么?
第一步:看概览 1
2# 统计总步数和 exit_status
python3 -c "import json; d=json.load(open('xxx.traj')); print(len(d['trajectory']), d['info']['exit_status'])"
第二步:扫描步骤摘要 1
2
3
4
5
6
7# 看每一步的 action 和 observation
python3 -c "
import json
d=json.load(open('xxx.traj'))
for i, s in enumerate(d['trajectory']):
print(f'Step {i}: {s[\"action\"][:80]} | {s[\"observation\"][:80]}')
"
第三步:看关键信息 1
2
3
4
5// info 中的关键字段
exit_status: "exit_format" | "exit_context" | "exit_cost" | ...
edited_files: 实际修改了哪些文件
submission: 是否成功提交
model_stats: token 消耗和成本
第四步:定位问题步骤 - 如果发现连续的相同 action → 可能陷入循环 - 如果发现 observation 为空 → 命令可能格式错误 - 如果发现 action 中有 HTML 实体 → 存在编码问题 - 如果 response 和 action 不匹配 → 模型执行能力差
8.2 正常 Traj vs 异常 Traj
正常的 Traj 特征: 1
2
3
4
5Step 0: action=find ... ; observation=找到多个文件
Step 1: action=cat /path/to/file ; observation=显示文件内容
Step 2: action=str_replace_editor ... ; observation=文件已修改
Step 3: action=python test.py ; observation=测试通过
Step 4: action=submit ; observation=提交成功
异常的 Traj 特征(本次): 1
2
3
4
5Step 0: action=python test.py ; observation=文件不存在
Step 1: action=python test.py ; observation=文件不存在
...
Step 23: action=python test.py ; observation=文件不存在 ← 重复24次!
Step 27: action="" ; exit_status=exit_format ← 强制退出
8.3 快速评估 Agent 表现的检查清单
9. 总结与启示
9.1 本 Traj 的结论
这是一个完全失败的 SWE-Agent 执行案例:
- 任务本身极其简单:在配置文件的列表里加一行 URL
- Agent 的表现非常差:28 步中零进展,没有编辑任何文件
- 核心失败模式:Agent 能”说”不能”做”——描述了 24 次解决方案但从未执行
- 根本原因:开源小模型(Qwen-local)的工具调用能力不足 + HTML 实体编码问题 + 缺少循环检测机制
9.2 对 Agent 开发的启示
| 启示 | 说明 |
|---|---|
| 模型选型至关重要 | 开源小模型和前沿模型的差距在 Agent 场景下被放大 |
| 需要更好的格式解析 | HTML 实体编码污染是框架层面的 bug |
| 需要循环检测 | 检测到重复 action 应当终止并尝试不同策略 |
| Prompt 可以更具体 | 提供具体命令示例比抽象指导更有效 |
| 工具描述要清晰 | 确保模型真正理解如何使用每个工具 |
9.3 对 LLM Agent 学习者的建议
- 从分析 Traj 开始学习:通过回放 Agent 的”思维过程”,能最直观地理解 Agent 的能力边界
- 注意 “说” 和 “做” 的差距:这是当前 LLM Agent 最常见的失败模式
- 模型能力是第一要素:同样的 SWE-Agent 框架 + 不同模型 = 天壤之别的结果
- Debug Agent 时先看 action:observation 是结果,action 才是 Agent 的决策,两者对比能快速定位问题
9.4 可复现的改进方案
如果想让这个 Agent 成功,可以尝试:
- 换更强的模型:使用 GPT-4、Claude 等强模型
- 修复 HTML 编码问题:在框架层对 action 进行 HTML 解码
- 优化 Prompt:添加具体的工具使用示例
- 添加循环检测:连续 3 次相同 action → 自动切换策略
- 提供更详细的实例模板:在 prompt 中展示正确的执行流程
文件信息 - 源文件:
scikit-learn__scikit-learn-i25076.traj- Traj 文件大小: ~2.4 MB - 总步数: 28 - 框架版本: SWE-Agent 1.1.0 / SWE-Rex 1.4.0 - 模型: openai/qwen-local - 结果: ❌ 完全失败(exit_format)