Lab 003:只给错误日志,不给代码上下文,Agent 能修好吗?
很多团队会把失败日志直接丢给 Agent,让它“帮我修一下”。但只给日志不一定足够,Agent 可能会猜错框架、猜错文件、甚至编造不存在的配置。本文通过实验拆解:错误日志能提供什么信息,缺什么上下文,以及最小上下文包应该如何构造。
一、实验问题
我们想回答三个问题:
| 问题 | 观察方式 |
|---|---|
| 只给日志时 Agent 能否定位原因 | 看它提出的假设是否命中真实文件 |
| Agent 会请求哪些上下文 | 记录它要求读取的文件和命令 |
| 最小上下文包要包含什么 | 对比不同上下文组合下的修复成功率 |
二、实验分组
groups:
log_only:
input:
- "完整错误日志"
expected_behavior:
- "只输出假设和需要的上下文,不直接改代码"
log_plus_file_tree:
input:
- "完整错误日志"
- "项目文件树"
expected_behavior:
- "定位候选模块"
minimal_context:
input:
- "完整错误日志"
- "项目文件树"
- "失败测试文件"
- "被测实现文件"
- "运行命令"
expected_behavior:
- "生成可验证补丁"三、错误日志样例
FAILED tests/api/test_users.py::test_create_user_duplicate_email
E assert 500 == 409
E + where 500 = <Response [500 Internal Server Error]>.status_code
sqlalchemy.exc.IntegrityError:
duplicate key value violates unique constraint "users_email_key"
DETAIL: Key (email)=(a@example.com) already exists.只看日志,我们能知道:
- 数据库唯一约束被触发
- API 没有把
IntegrityError转换成业务错误 - 期望 HTTP 409,实际返回 500
但还不知道:
- 使用 FastAPI、Django 还是 Flask
- 异常处理在路由层、中间件还是 service 层
- 创建用户的函数在哪里
- 项目约定的错误响应格式是什么
四、推荐 Prompt
你将根据错误日志帮助定位问题。
## 重要规则
- 如果上下文不足,不要直接编写补丁
- 先列出最多 5 个可能原因
- 明确说明每个假设需要哪些文件验证
- 只在给出最小上下文后再生成修改方案
## 错误日志
{{error_log}}
## 输出格式
1. 问题摘要
2. 候选原因
3. 需要的最小上下文文件
4. 下一步验证命令五、最小上下文包
当 Agent 请求上下文后,可以给它一个结构化上下文包:
context_pack:
runtime:
framework: "FastAPI"
python: "3.11"
orm: "SQLAlchemy 2.0"
failing_test:
path: "tests/api/test_users.py"
node: "test_create_user_duplicate_email"
implementation_files:
- "app/api/users.py"
- "app/services/users.py"
- "app/core/errors.py"
conventions:
error_response:
shape: "{ code: string, message: string }"
duplicate_resource_status: 409
verify:
command: "pytest tests/api/test_users.py::test_create_user_duplicate_email -q"参数说明
| 参数 | 说明 |
|---|---|
runtime |
框架、语言、ORM 等基本环境 |
failing_test |
失败测试路径和测试节点 |
implementation_files |
最小候选实现文件 |
conventions |
项目错误响应约定 |
verify.command |
单点验证命令 |
六、可能的修复代码
下面是 FastAPI 项目中一种常见修复方式。
from fastapi import HTTPException
from sqlalchemy.exc import IntegrityError
def create_user(db, payload):
user = User(email=payload.email, name=payload.name)
db.add(user)
try:
db.commit()
except IntegrityError as exc:
db.rollback()
if "users_email_key" in str(exc.orig):
raise HTTPException(
status_code=409,
detail={
"code": "duplicate_email",
"message": "email already exists",
},
) from exc
raise
db.refresh(user)
return user配套测试:
def test_create_user_duplicate_email(client):
payload = {"email": "a@example.com", "name": "A"}
assert client.post("/users", json=payload).status_code == 201
response = client.post("/users", json=payload)
assert response.status_code == 409
assert response.json()["detail"]["code"] == "duplicate_email"七、实验记录表
| 分组 | 是否直接修复 | 是否请求上下文 | 最终是否通过 | 主要失败原因 |
|---|---|---|---|---|
log_only |
否 | 是 | 不适用 | 上下文不足 |
log_plus_file_tree |
部分 | 是 | 低概率 | 候选文件不完整 |
minimal_context |
是 | 否 | 高概率 | 取决于项目约定是否清楚 |
八、判断 Agent 是否在瞎猜
出现这些信号时,应该暂停:
- 引用了项目中不存在的文件
- 改了和日志无关的模块
- 没有询问框架和错误处理约定
- 没有补失败测试
- 给出无法运行的验证命令
九、结论
只给错误日志,Agent 更适合做“诊断助手”,不适合直接改代码。真正高效的流程是:先让 Agent 从日志中提出假设和上下文需求,再提供最小上下文包,最后让它生成补丁和验证结果。
总结
错误日志是入口,不是完整上下文。团队应该把“日志 + 文件树 + 失败测试 + 候选实现 + 项目约定 + 验证命令”封装成最小上下文包,这比盲目把整个仓库塞给 Agent 更稳定、更便宜。