1. 这篇文章真正要解决的问题
如果你最近在用 Claude Code、Codex、Cursor 这类编程智能体(Coding Agent),大概率会遇到一个熟悉的场景:智能体在一个 issue 上跑得挺好,你正准备夸它,结果你随手在某个文件里动了一行代码,加上一段注释,或者把一个函数的参数名改了一下,智能体接下来的表现立刻“失智”——要么反复改你已经改过的地方,要么把你刚加的代码覆盖掉,要么干脆陷入循环。
这个场景不是个例,而是当前编程智能体落地时最让人头疼的问题之一。大家平时看到的评测数字,比如 SWE-bench Verified 上百分之四五十的通过率,看起来很漂亮,但这些评测的玩法是:给定一个 issue,让智能体独立完成修复,期间用户不干预,最后看测试用例通过没有。
但真实开发不是这样。
真实开发里,用户会不断“触碰”代码:中途改需求、补充新约束、调整某个函数签名、甚至只是手动改了某个局部逻辑。这个时候智能体该怎么表现?它能理解用户已经动过哪些地方吗?它能避免在用户改完的地方重复修改吗?它能根据用户的新改动调整自己的计划吗?
这就是 SWE-Touch 这篇工作要回答的核心问题:当用户中途触碰代码时,编程智能体的能力到底还剩多少。
这篇文章会从三个角度展开:
- 拆解 SWE-Touch 的评测设计,弄清楚它到底在测什么,以及它为什么比传统 SWE-bench 更接近真实开发。
- 对比 SWE-Touch 和现有评测基准的差异,帮助你在选型或评估智能体时少走弯路。
- 给出实际使用编程智能体时的工程建议,让你知道在用户会介入的场景下,怎么配置提示词、怎么组织任务、怎么验证结果。
先给一个明确判断:如果你的团队准备把编程智能体接入真实开发流程,SWE-Touch 反映的问题比 SWE-bench 的通过率更值得关注。因为“用户会碰代码”不是边界情况,而是常态。
2. 核心概念:什么是 Coding Agent 评测基准
2.1 为什么需要专门的评测基准
评测基准(Benchmark)本质上是一个“标准化考试”。它的作用是回答一个问题:某个智能体在特定任务上到底行不行。
没有基准,大家就只能靠感觉。有的人说“我用着挺好的”,有的人说“一塌糊涂”,谁也说服不了谁。有了基准,至少可以在同一个数据集、同一个评估规则下做横向对比。
SWE-bench 是目前最流行的编程智能体评测基准。它的做法是:从 GitHub 上收集真实 issue 和对应的 PR,把 issue 描述作为任务输入,把 PR 里改动的代码作为参考答案,用测试用例是否通过作为评分标准。
SWE-bench 的出现让编程智能体的评测第一次有了统一标尺。但它有一个致命短板:它假设智能体在无人干预的情况下独立完成任务。
这个假设在几年前的 AI 编程工具时代是合理的,因为那时候智能体只是“自动补全器”。但到了 2025 年,编程智能体已经从“自动补全”进化到“自主执行任务”,用户和智能体之间的协作关系越来越紧密。这时候再用“无人干预”的评测标准,就有点像是你用“答题卡判卷”的标准去衡量一个“讨论式面试”的候选人。
2.2 从 SWE-bench 到 SWE-Touch:评测视角的转变
SWE-Touch 的论文标题很直白:“Benchmarking Coding Agents When Users Touch the Code”,翻译过来就是“当用户触碰代码时的编码智能体评测”。
什么是“用户触碰代码”?简单说,就是智能体在执行任务的过程中,用户对代码库做了一些修改,而这些修改并不在原始任务描述里。
这看起来是个很小的改动,但带来的挑战是巨大的。
传统评测模式下,智能体面对的是一个“静态”任务:代码库是固定的,任务描述是固定的,目标也是固定的。它只需要理解现状,然后做修改。
引入用户触碰之后,任务变成了“动态”的:代码库在变,而且变得不可预测。用户可能加了一个功能,可能改了一个变量名,可能在某个文件里临时写了一段调试代码,可能把原本要改的文件结构调整了。智能体必须在执行过程中持续跟踪这些变化,判断哪些是它自己改的,哪些是用户改的,然后调整自己的方案。
这个能力在学术上叫“状态跟踪”和“计划修正”,在工程上叫“不要帮倒忙”。
2.3 SWE-Touch 评测设计的关键点
从公开材料看,SWE-Touch 的设计有几个关键特征:
- 它构建了一系列“用户会在某个时刻触碰代码”的交互场景。
- 评测关注的不只是最终能不能通过测试,还关注智能体在用户介入后的行为模式。
- 它试图量化“用户介入”对智能体最终结果的影响。
换句话说,SWE-Touch 不只是在问“代码最终修好了没有”,还在问“用户碰了代码之后,智能体是更快还是更慢”“用户碰过的地方,智能体是正确处理了还是覆盖了用户改动”。
这些问题的答案,才是真实开发最关心的。
2.4 为什么“用户会碰代码”这件事这么难
从技术角度说,编程智能体的核心工作流是:观察代码库状态 -> 生成修改计划 -> 执行修改 -> 验证结果。这个循环通常由大语言模型驱动,而大语言模型的注意力窗口和上下文管理决定了它只能看到“某个时刻的代码库快照”。
当用户中途碰了代码,智能体手里的“快照”就过期了。它可能会:
- 基于过期的上下文做决策,改到已经被用户改过的地方。
- 把用户的新改动误当作自己的改动,导致逻辑冲突。
- 重复执行已经失效的修改步骤,浪费时间和 token。
- 在用户改动的文件上强行重写,直接覆盖用户手写代码。
这本质上是一个“信息同步”问题。智能体缺乏一种机制来区分“这个改动是我做的”和“这个改动是用户做的”,更缺乏一种机制来决定“当前任务还需要继续吗”。
SWE-Touch 的意义,就是把这个问题从“你可能会遇到”变成了“评测标准里明确要求你必须具备这个能力”。
3. SWE-Touch 和传统评测基准的差异对比
为了更直观地理解 SWE-Touch 的价值,这里把它和 SWE-bench 做一次对比。
| 对比维度 | SWE-bench 系列 | SWE-Touch |
|---|---|---|
| 核心问题 | 智能体能独立修复 issue 吗 | 用户介入后智能体还能完成任务吗 |
| 用户交互 | 无 | 有,且用户会在中途修改代码 |
| 代码库状态 | 静态 | 动态,任务过程中会变化 |
| 评测重点 | 最终测试是否通过 | 最终结果 + 用户改动是否被尊重 |
| 对应真实场景 | 智能体全自动“无人区”开发 | 用户和智能体协同开发的常态 |
| 适合评估的能力 | 理解 issue、定位代码、生成补丁 | 状态跟踪、变更感知、计划修正 |
从使用场景看,这两类评测不是谁取代谁的关系,而是互补关系。
如果你的业务场景是“我把 issue 丢给智能体,它自己搞定,我过几个小时回来看结果”,那 SWE-bench 类评测结果更贴近你的需求。
如果你的业务场景是“我坐在电脑前面,和智能体一起改代码,我改它也改”,那 SWE-Touch 评测所覆盖的问题才是你真正会遇到的。
现实情况是,绝大多数专业开发者的日常属于后者。你在写代码时,脑子里一直在修正方案:这里加个判断,那里改个类型,临时把某个函数的逻辑调整一下。这些操作如果发生在智能体已经开工之后,正是同类基准最难覆盖的交互维度。
这里需要特别提醒一点:SWE-Touch 并不是对 SWE-bench 的全盘否定,而是补上了一个关键测试盲区。SWE-bench 依然有它的价值,尤其是用来衡量模型的基础代码理解和修复能力。但 SWE-Touch 的出现,让人们开始认真思考“协作智能”这个此前被忽略的维度。
4. 从 SWE-Touch 看编程智能体当前的真正短板
SWE-Touch 的评测视角非常有价值,因为它揭示的其实是编程智能体在“交互能力”上的普遍不足。
4.1 智能体的工作记忆与代码库状态脱节
大语言模型本身没有“持久工作记忆”。每轮生成都依赖当前上下文窗口里的内容。当用户中途改了代码,智能体的下一轮推理并不会自动感知这个变化,除非它主动做一次全库扫描或读取对应文件。
但大部分智能体的工作流里,“读取文件”是需要成本和用户提示的。智能体在已经规划好任务的前提下,往往倾向于“直捣黄龙”直接生成修改方案,而不会停下来确认“用户是不是已经改过了”。
这就是 SWE-Touch 想暴露的问题:智能体缺少一个默认的“检查用户是否动过代码”的环节。
4.2 智能体对自己的修改缺乏“记忆标记”
人类开发者天然知道哪些代码是自己写的,哪些是同事写的。但智能体没有这种天然的区分能力。它拿到一个代码库,看到新增代码,唯一能判断的依据是读取文件的修改历史,或者 diff 信息。如果用户手动改了文件,但没有提交,智能体很难通过普通文件读取发现这些改动。
更复杂的情况是,智能体自己执行了修改,然后用户在这个修改基础上又做了调整。这时候智能体面对的是一堆“混合改动”,任何简单的“重试”“继续执行”都可能覆盖用户新改的部分。
4.3 智能体缺乏“任务有效性”判断
真实协作场景里,用户中途修改代码往往意味着需求变了,或者实现思路变了。这时候最佳策略不一定是“继续完成任务”,而是“停下来重新评估任务”。
SWE-Touch 所模拟的场景把这个问题暴露得很清楚:用户在某些文件里做了修改,可能意味着旧方案已经不合适,也可能意味着用户解决了某个子问题。智能体如果继续按照原计划执行,很可能是白费功夫,甚至会给用户添乱。
协作智能区别于独立智能的根本,就在于它拥有“什么时候该停下问一句”的判断力。
5. 在实际项目中如何应用 SWE-Touch 的思路
5.1 不要只看 Throughput,要看 Throughput with Touch
如果你正在评估编程智能体产品,最直接的应用方式就是:在看官方评测报告时,不要只看基准测试通过率,要关注他们有没有提供“用户中途介入”场景下的测试结果。如果供应商没有提供,可以自己在本地用几个典型场景测一遍。
这里给出一个本地化的测试思路:
- 准备一个多模块项目和一段完整可行的编码任务。
- 让智能体开始执行任务。
- 在智能体执行到中途时,手动修改其中某个关键文件,并改变任务约束。
- 观察智能体能否正确感知新约束、调整原有计划,并在用户已经修改过的文件上做增量修改而不是覆盖。
一个粗略但有效的判断标准是:
- 四轮以上交互仍然围绕已经被用户改过的代码区域打转,说明状态跟踪能力弱。
- 智能体多次重复读取同一文件但没提出新的解决思路,说明它在旧上下文里“绕圈”。
- 智能体改完之后,用户原有改动被覆盖,说明它没有做增量处理。
5.2 在真实开发流程中设计“用户触碰点”
即使不用 SWE-Touch 做正式评测,你在团队里也可以自己定义几个“用户触碰点”来检验智能体的协作能力:
| 触碰场景 | 执行方式 | 期望智能体行为 |
|---|---|---|
| 用户改参数 | 在智能体执行中,修改任务相关函数的参数类型 | 主动提问或调整调用代码,而不是沿用旧类型继续 |
| 用户加注释 | 在智能体计划修改的文件中新增约束性注释 | 读取注释并遵循新约束 |
| 用户调整结构 | 将目标文件中的函数拆成两个文件 | 停止旧方案,基于新结构重新规划 |
| 用户删除代码 | 删除智能体计划依赖的某段功能 | 发现依赖缺失,重新规划或明确求助 |
这比拿着 SWE-bench 测“能不能修 issue”更贴近工程实际。
5.3 通过提示词工程缓解“用户触达”问题
在实际使用编程智能体时,提示词的设计可以缓解一部分状态同步问题。下面是一个通用提示模板,适合在协同修改前发给智能体:
你正在执行一个代码库修改任务。任务开始后,用户可能在任意时间修改代码库。请遵守以下规则: 1. 在每轮修改前,先读取目标文件的最新内容。 2. 如果发现目标文件内容与你上一次读取时不一致,立即停止当前修改计划,重新分析变更。 3. 如果发现用户新增了注释、常量或类型定义,优先遵循用户的新定义。 4. 绝不覆盖用户手动改动的代码。如果必须合并修改,请在最终结果中明确标注哪些是你改的,哪些是保留的用户代码。 5. 如果你不确定某处代码是用户写的还是你自己改的,先询问,再动手。这段提示词的核心目的是强制智能体在每次行动前获取最新状态,弥补它没有“自动感知变化”能力的短板。
5.4 建立“修改前快照 + 修改后对比”的工程习惯
SWE-Touch 反映的问题不止存在于智能体侧,也提醒我们:在引入智能体协作时,用户侧需要有良好的版本管理习惯。
建议工作流程如下:
git add -A git commit -m "chore: snapshot before agent task"在给智能体下达任务前,先创建一个快照提交。这有两个好处:
- 如果智能体运行结果混乱,可以随时回滚到任务开始前。
- 智能体的 diff 能通过 commit 记录直观展示,方便你审查它改了哪些文件、是否触碰了不该触碰的代码。
这里还需要提醒一句:**不要把智能体的代码修改直接合入主干,也不要让智能体在未受版本控制的工作区里运行长任务。**所有变更都要经过 review 流程。
6. 一个最小示例:模拟“用户触碰”场景下的智能体表现
为了让大家更清楚地理解 SWE-Touch 评测的场景,下面用一个最小示例演示“用户触碰”对智能体任务的影响。
6.1 任务设定
假设我们有一个简单的 Python 模块,功能是把用户名字格式化为欢迎语:
# 文件路径:greeting.py def get_greeting(name: str) -> str: return f"Hello, {name}!"我们给智能体下达的任务是:
请将 get_greeting 函数扩展为支持多语言的版本, 增加一个参数 lang,支持 "en" 和 "zh" 两种语言。智能体开始执行后,常见的工作方式是:
# 文件路径:greeting.py(智能体修改后) def get_greeting(name: str, lang: str = "en") -> str: if lang == "zh": return f"你好,{name}!" return f"Hello, {name}!"但此时,用户中途“触碰”了代码,手动在文件里新增了一个逻辑:
# 文件路径:greeting.py(用户触碰后) def get_greeting(name: str, lang: str = "en") -> str: if lang == "zh": return f"你好,{name}!" if name == "admin": return "Welcome, admin!" return f"Hello, {name}!"用户新增了“admin 用户返回特殊欢迎语”的逻辑。接下来,如果智能体继续执行它的测试或重构步骤,很可能会出现下面这种行为:
# 文件路径:greeting.py(智能体覆盖后) def get_greeting(name: str, lang: str = "en") -> str: if lang == "zh": return f"你好,{name}!" return f"Hello, {name}!"用户刚加的 admin 判断被覆盖掉了。
这个最小示例就是 SWE-Touch 想强调的典型问题:在传统静态基准测试里,智能体的修改方案输出环节可能完全通过;但一旦用户中途触碰代码,智能体的覆盖行为就带来了实际回归风险。它没有检测到用户新增代码,也没有保留用户改动的意识。
6.2 更好的智能体行为
一个具备“用户触碰感知”的智能体,应该在执行修改前重新读取文件,发现自己上次读取后文件发生了变化,然后采取以下行动:
- 对比新旧文件,识别出用户新增的
if name == "admin"分支。 - 保留用户新增逻辑。
- 在最终输出中说明用户新增加载的功能,例如:
检测到用户新增了 admin 用户的特殊欢迎语逻辑。 在原计划基础上,保留该逻辑,并增加语言参数支持。# 文件路径:greeting.py(保留用户改动的智能体输出) def get_greeting(name: str, lang: str = "en") -> str: if lang == "zh": return f"你好,{name}!" if name == "admin": return "Welcome, admin!" return f"Hello, {name}!"这两种智能体行为,在最终“测试用例是否通过”这个维度上可能看不出差别,但在用户实际体验和代码演进质量上差别巨大。SWE-Touch 评测的价值,就是把这个差别量化和显式化。
7. 运行结果判断与常见问题排查
7.1 如何判断智能体是否具备“用户触碰感知”能力
你可以通过几个操作简单测出智能体在这方面的能力:
- 运行一个任务,在中途手动修改目标文件,加入一条注释“不要修改以下代码”,然后观察智能体是否继续修改这段代码。
- 运行一个任务,在中途手动删除智能体依赖的某个函数,然后观察智能体是停下来报错,还是忽略缺失继续硬写。
- 运行一个任务,在中途手动修改一个函数签名,然后观察智能体的后续调用是否同步更新。
如果智能体连续出现以下现象,说明它缺乏用户触碰感知:
- 反复修改用户刚改过的地方。
- 覆盖用户注释或代码。
- 在多轮对话里反复使用第一次读取时的旧代码内容。
- 用户明确说了“这个文件我已经改了”,智能体仍然按旧逻辑执行。
如果智能体具备用户触碰感知,通常的表现是:
- 主动读取文件最新内容。
- 发现变动后先说明“检测到代码变化”,再重新规划。
- 在生成内容里明确区分“这是你改的”“这是我加的”。
- 遇到不确定的改动,会先向用户确认。
7.2 常见问题排查表
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 智能体覆盖了用户手动修改的代码 | 未在修改前重新读取文件 | 检查交互日志中智能体最后读取文件的时间点 | 在提示词中增加“每次修改前必须重新读取目标文件最新内容”的指令 |
| 智能体循环修改同一区域 | 上下文中的旧代码快照导致误判 | 查看模型输入 token 中是否包含旧代码内容 | 清理会话上下文,重新开启新会话并重新读取文件 |
| 用户改了函数签名后智能体仍使用旧签名 | 智能体只记住了第一次函数定义 | 检查调用链中函数签名的引用来源 | 在任务开始前先执行一次全库索引或函数签名扫描 |
| 智能体修改了用户注释 | 智能体把注释当作可优化内容 | 查看修改 diff 中注释变更信息 | 在提示词中声明“所有注释均视为用户意图,不得修改” |
| 智能体无法感知用户新需求 | 任务目标固定,缺少动态更新机制 | 检查智能体系统提示词是否包含任务重新评估规则 | 在提示词中增加“如果用户修改代码,先重新评估任务目标再行动” |
| Git 历史被污染,无法定位智能体修改范围 | 没有在任务开始前创建快照 commit | 查看 git reflog 最近变动 | 在任务开始前先执行git add -A && git commit -m "snapshot" |
7.3 如何判断任务最终成功
判断任务是否成功的标准不应该是“智能体跑完了”,而应该是以下几点:
- 用户手动改动的代码块在 diff 中保持原样。
- 智能体新增的改动与用户改动之间无逻辑冲突。
- 所有测试用例通过,包括用户手动改动后新增的断言。
- 智能体的最终回复中明确说明了它检测到哪些用户改动,以及如何适配这些改动。
如果第 1 条和第 4 条不满足,即使测试全部通过,也是一次不成功的协作。
8. 最佳实践与工程建议
8.1 使用编程智能体的安全边界
SWE-Touch 所暴露的问题,提醒我们在生产环境中使用编程智能体时要有清晰的边界意识。
首先是文件边界。建议在任务描述中明确哪些文件可以由智能体自由修改,哪些文件属于“只读区域”。例如:
可修改文件: - src/services/payment_service.py - src/utils/format.py 只读文件: - src/config.py - src/models/user.py其次是操作边界。建议明确禁止智能体执行某些危险操作,例如:
禁止执行以下操作: - git push - git pull --force - 删除任何测试用例文件 - 修改数据库迁移文件 - 直接修改生产环境配置文件最后是验证边界。建议所有智能体生成的代码都必须在独立分支中测试,不能直接合入主干。
如果你是在真实项目中按这个思路操作,下面是一个实用的 git 流程:
# 创建独立工作分支 git checkout -b feat/agent-task-001 # 在智能体开始前创建快照 git add -A git commit -m "snapshot before agent task" # 运行智能体,完成任务 # 审查智能体的修改 git diff HEAD~1 --stat不要图省事就让智能体直接在主干分支上运行修改。一旦发生 SWE-Touch 里描述的那种“覆盖用户改动”的问题,独立分支加快照 commit 能让你快速回滚,不用手动恢复代码。
8.2 如何设计提示词以增强协作稳定性
基于 SWE-Touch 反映的问题,这里给出一个更完整的提示词模板,适合在“用户会中途介入”的协同开发场景下使用。
你是一个代码库修改助手。在执行任务过程中,用户可能随时修改代码文件。 请严格遵守以下规则: 1. 信息来源优先级别: - 用户手动新增的代码 > 用户通过自然语言提出的新要求 > 你已有的计划 > 其他参考资料 2. 每轮行动前,必须读取目标文件最新内容,并检查是否存在与上次读取不一致的地方。 3. 如果发现不一致: - 停止当前行动。 - 分析不一致的内容,判断是用户改动还是偶发变化。 - 在回复中明确说明你检测到了哪些变化,以及你的应对方案。 4. 如果用户改动了函数签名、常量定义、配置文件: - 先梳理所有依赖这些定义的位置。 - 再决定是否需要批量修改。 - 不要只改被调用处的代码。 5. 你的修改必须遵守最小变更原则: - 只修改与任务直接相关的代码。 - 不重构用户代码风格。 - 不移动用户已写好的函数位置。 - 不删除用户代码里的“无用”内容,除非任务明确要求。 6. 每个文件修改完成后,输出该文件的修改摘要,包括: - 修改位置。 - 修改原因。 - 保留了哪些用户原有内容。这段提示词的关键在于第 3 条和第 5 条。第 3 条让智能体在面对变化时优先暂停和识别,第 5 条限制了它的“修改冲动”,避免在解决问题的同时引入无关变更。
8.3 团队协作中的角色分工
在实际工程团队中,建议把编程智能体定位成一个“需要监督的初级工程师”,而不是“全自动编程机器人”。
具体分工建议如下:
- 技术负责人负责拆分任务并明确验收标准。
- 开发者在智能体执行任务前做好环境准备和快照。
- 智能体负责执行代码修改和初步测试。
- 开发者负责审查智能体的 diff,特别是“用户改动区域是否被覆盖”。
这套分工的核心思想是:利用智能体提升编码速度,但不放弃人工审查这个关键环节。SWE-Touch 的价值正在于提醒我们,在交互场景中,智能体的判断力仍然有限,人工审查不是流程负担,而是质量保障。
8.4 版本管理与回滚策略
在引入智能体协作开发后,版本管理的颗粒度要更细。建议:
- 每次任务开始前创建一个轻量标签。
- 智能体的修改按文件维度审查,不要整体合并。
- 如果智能体在修改 A 文件时引入了对 B 文件的无关变更,应该单独剔除。
# 查看智能体修改了哪些文件 git diff HEAD --name-only # 单独还原某个文件的修改 git checkout HEAD -- path/to/file对于重要项目,还可以利用 IDE 的本地历史功能,每十分钟自动保存一次工作区快照,这样即使 git 没有提交,也能通过 IDE 的历史记录找回被智能体覆盖的代码。
9. 总结与后续学习方向
SWE-Touch 这篇工作真正有价值的地方,不是又给了一个新的分数排名榜,而是把编程智能体评测的视角从“无人值守的自动修复”拉回到了“人机协作的真实开发”。
它让我们意识到,当前编程智能体的瓶颈,也许已经从代码生成能力转移到了交互协同能力。一个能在静态任务上考满分的智能体,在用户中途改代码的常态场景下,完全可能表现得像个“优秀的破坏者”。
如果你正在做编程智能体的选型,建议不要只看基准测试分数,而是重点考察这几个方面:
- 智能体是否能感知代码库状态变化。
- 智能体是否提供明确的文件读取和修改日志。
- 智能体是否支持在任务中途暂停并重新规划。
- 智能体的修改是否遵循最小变更原则。
- 智能体是否能区分“用户改动”和“自身改动”。
这些能力目前还没有一个统一评测标准,但 SWE-Touch 已经在朝这个方向探索。后续值得关注的几个方向包括:更细粒度的用户交互类型建模、多轮对话中的状态跟踪评测、以及“用户意图变更”场景下的智能体重规划能力评测。
对于普通开发者来说,现阶段最实用的做法是:在引入任何编程智能体之前,先建立好快照、分支、审查这套基础工程保护机制,再把智能体放到真实任务里测试少量交互场景,尤其要测试你中途修改代码时的表现。
这才是拿到 SWE-Touch 这类评测结果后,真正应该落实到项目里的行动。