指出给Agent派活时"修checkout"过于模糊,应给出Bug的修订版本、暴露问题的fixture、预期行为等可验证的契约。
"Fix checkout" 足以开启一段对话。但对于一个编码 Agent 而言,这是一个糟糕的任务单元。
Agent 可以检查代码库、发现可疑之处、写出一个看似合理的补丁,然后报告成功。但审查者仍然无法共同回答两个基本问题:到底哪里坏了?什么样的可观测行为现在应该有所不同?
随着实现成本下降,这个鸿沟变得更加重要。一个编码任务应该从已知的前置状态开始,以声明的后置状态结束。补丁只是系统在这两者之间移动的一次尝试。
任务是一种状态转换,不是一句话
模糊的提示通常包含意图:
修复会话过期时的结账超时。
但它不包含任务契约。哪个版本有 bug?哪个 fixture 暴露了它?请求是挂起了、返回了错误的状态码,还是丢弃了购物车?什么行为必须保持不变?哪个命令用来评估结果?
没有这些细节,Agent 就不得不在实现修复的同时自己发明部分验收测试。这是一个糟糕的委托边界。同一个系统在选择"完成"的含义,并宣布自己已经到达了那里。
一个可审查的任务有两个可观测状态:
起始状态在任何修改之前可以被重建。
目标状态在修改之后可以在不信任 Agent 总结的情况下被评估。
Agent 可以在两个状态之间选择实现方式,而任务作者拥有周围的契约。
这种框架也让人类摆脱了低价值的监督工作。如果你已经定义了可接受的行为、约束和证据,你就不需要叙述每一个代码变更。
从失败开始
CLI-Gym 是失败优先任务构建的一个有用例子。它的项目文档描述了一个流程:从健康的仓库环境开始,引入受控的失败,然后将那些状态转化为可复现的命令行任务。README 报告了来自 29 个仓库的 1655 个任务。
这些数字是项目方提供的,并不证明基准质量或生产可靠性。这里的任务设计比标题数字更有用。
受控失败给了 Agent 和审查者相同的起点。它可以被重置。它可以在补丁之前被观察。它可以在之后再次被检查。如果失败因为与补丁无关的原因消失了,那也会变得可见。
对比一下把 Agent 扔进一个活跃的分支然后说"构建很奇怪,请修复它"。Agent 可能会发现一个真正的问题。它也可能会修复一个偶发症状、更新一个不稳定的快照,或者改了足够多的代码,以至于没有人能说出哪个行为才是重要的。
失败优先不意味着每个任务都需要一个已经失败的测试。功能工作往往从没有测试开始。在这种情况下,定义一个可观测的前置状态和一个具体的验收示例。一个缺失的端点、不支持的交互,或者一个目前没有产生结果的 fixture,仍然可以锚定这个转换。
把契约放在一个制品中
聊天适合探索。作为编码任务的唯一记录,它太弱了。
持久化的设置将意图、范围、检查和证据保存在存活于会话之外的制品中。任务文件可以在执行前被审查。计划可以与允许的范围进行比较。测试输出和最终 diff 可以附加在同一个工作单元上。
这将审查从"完成消息听起来令人信服吗?"变成了对比:
运行是否从声明的基线状态开始?
原始的复现步骤现在是否达到了目标行为?
diff 是否保持在声明的边界内?
哪些命名检查运行了,哪些没有运行?
任务变得模糊时 Agent 是否停止了?
把一段自信的完成描述当作上下文,然后对照制品来验证它。
契约也应该尽可能保持实现中立。"在 refreshSession() 周围添加重试"可能是一个合理的计划,但它已经在规定补丁了。"过期的会话在配置的timeout内返回类型化的认证错误并保留购物车"给 Agent 留下了在选择变更之前检查代码的空间。
六字段任务卡
你不需要一个大型规范系统来获得这个好处。一个紧凑的任务卡对于许多仓库变更来说已经足够了。
以下示例是假设的。命令和 fixture 名称代表你实际使用的任何东西。
Revision: <commit SHA>
Fixture: expired-session.json
Environment assumption: the local test services start with the documented setup command
Initial state: the cart contains one item and the session token is expired
Run pnpm test checkout -- --grep "expired session"
Current result: the checkout request waits until the test timeout
Save the pre-change failure output with the task
Checkout returns the repository's existing typed authentication error before the configured timeout
The cart remains intact so the user can authenticate and try again
Do not change the session lifetime
Do not add a dependency
Preserve checkout behavior for valid sessions
Keep unrelated formatting and refactors out of the diff
Re-run the exact reproduction command
Run the existing checkout test group
Run the repository's type check
Inspect the final diff against the boundaries above
Hand the task back unresolved if:
the failure does not reproduce from the declared base
the fixture or local setup is broken
the expected result conflicts with the current API contract
a required service or credential is unavailable
the fix needs a wider product or architecture decision
省略 Stop 部分会让 Agent 没有定义的方式返回一个未解决的任务。只有成功标准的 Agent 会继续搜索补丁。明确的停止条件让它可以在扩大变更或猜测产品意图之前返回一个有用的失败报告。
通过的检查是有边界的证据
命名检查使转换可审查。它们不对整个系统提供认证。
一个绿色的针对性测试说明了该测试中编码的行为。它不能证明架构是健康的、变更是否安全,或者每个产品期望是否已被捕获。可复现的失败缩小了围绕命名行为的不确定性,同时将架构和产品问题留给审查。
最终的 diff 仍然需要审查。将代码与声明的目标和非目标进行比较,然后决定是否需要更广泛的测试或专家审查。认证路径中的一个两行修复可能比一个隔离内部工具中的更大变更更值得仔细审视。
任务卡有助于使这种判断变得清晰。它显示了检查应该证明什么,以及它们的权威在哪里。
让未解决的运行算作有效结果
来源笔记中的 Hacker News 和 Reddit 帖子是轶事性的,但一些参与者倾向于小而可审计的循环:检查、更改、运行真正的检查、审查 diff,并为下一步保留足够的状态。工具偏好各不相同,而每个无人值守的运行仍然需要一个清晰的交接。
报告"无法从指定的版本复现"的运行产生了有用的信息。发现矛盾的验收检查或缺失服务的运行也是如此。这些结果保护仓库免受猜测的补丁,并给任务作者一个具体的问题去解决。
把每次运行都当作补丁或失败来对待会产生隐藏不确定性的压力。把合理的停止作为契约的一部分使得工作流更加诚实。Agent 可以说明它检查了什么、转换在哪里中断了、以及缺少什么决定或依赖。
这比一个没有人同意用它定义成功的检查的绿色输出要好得多。
在要求补丁之前先定义转换
回到"fix checkout"。有了基础版本、fixture、复现命令、行为目标、边界、检查和停止条件,任务在 Agent 写一行代码之前就可以被审查。
Agent 可能会发现预期的修复很小。它可能会发现任务描述不足。当前置状态和后置状态是明确的时,两种结果都更容易处理。
一个更强的模型可以提出更好的实现。它无法恢复团队从未写下的成功条件。
Your AI Agents Ship Code Faster Than You Can Review It
The AI Coding Agent Workflow That Actually Works After 1,000 Hours
Ask HN: What coding agents are you using?
Coding agents workflow