![]()
给5个AI agent一个任务:从零写个国际象棋引擎。1个做架构规划,3个并行写模块,1个统筹全局。没有外部棋库,没有联网查询,只有agent、测试套件,以及一个目标——在1200 ELO等级分下至少50%胜率击败Stockfish。
引擎跑通了。但作者Matt Bateman发现,真正让他意外的不是输出结果,而是整个监督式AI agent执行过程中暴露的问题。
团队配置:Opus做大脑,Sonnet当手脚
5个agent的分工很明确。架构师跑Claude Opus,负责整体规划。3个工程师跑Claude Sonnet,并行实现具体模块。1个经理负责在架构师和工程师之间路由任务。每个工程师有自己的git worktree——独立分支、独立目录,完全隔离。
任务板就是一个Markdown文件:待办、进行中、已完成。作者输入batty start --attach,然后旁观。
他最初以为工程师——那些写实际代码的agent——会是瓶颈。错了。
好的架构规划让工程师能独立工作。棋盘表示、走法生成、局面评估,这些模块天然隔离:触及不同文件、使用不同数据结构、可以独立测试。架构师看清了这一点,相应分解了任务。
早期版本用过较弱的架构规划,工程师互相阻塞。评估agent要等棋盘表示agent完工。搜索agent要等前两个都完成。3个agent,理论上并行,实际上串行。
解决方法是给规划阶段更多时间、更多昂贵的token。作者用Opus跑架构师,并给出明确指令:"分解任务,让每个工程师无需等待其他工程师输出就能立即开始。预先定义接口。"
架构师产出了一份规划:清晰的模块边界、共享类型定义放在common/types.rs、每个工程师可以对着写的存根实现。3个工程师在几秒内同时启动。
第一个教训:在监督式AI agent执行中,任务分解的质量决定一切。规划上的投入不是开销,是杠杆。
经理agent:最被低估的角色
经理agent的工作是读取任务板,决定下一步行动,分派给架构师或工程师。听起来简单,但作者发现这个角色的设计直接决定系统能否收敛。
早期版本的经理太"积极"。只要看到待办事项,立刻分派。结果工程师同时收到多个任务,任务板混乱,依赖关系断裂。
修正后的经理采用严格的状态机:检查进行中任务→评估依赖→若无阻塞则分派→否则等待。每次只推进一个任务,确保完成后再下一步。
这个设计让整体耗时从不可预测变成可预期。作者记录的数据显示,严格顺序执行的版本比"积极"版本平均快23%,且失败率从31%降到4%。
但经理的瓶颈很快暴露:它成了单点。所有信息流经它,所有决策出自它。3个工程师经常处于等待状态,不是因为代码依赖,而是因为经理还没处理完上一轮反馈。
作者尝试过让经理并行处理,但导致状态竞争——两个工程师同时修改同一文件,合并冲突爆炸。最终妥协:经理保持单线程,但优化提示词减少每轮决策的token消耗,把平均响应时间从45秒压到12秒。
第二个教训:协调agent的吞吐量,比执行agent的数量更重要。并行执行需要并行协调,但协调的并行化是hard模式。
测试驱动:agent的"地面真相"
整个项目没有人类写业务代码。但人类写了一个关键东西:测试套件。
测试分为三层。单元测试验证单个函数:给定FEN字符串(一种棋盘状态的标准表示),验证走法生成是否返回合法移动列表。集成测试用已知棋局验证搜索深度和评估分数。最终验收测试让引擎对战Stockfish 1200,统计胜率。
这些测试是agent唯一的"地面真相"。作者观察到有趣现象:agent会"针对测试优化"——不是作弊,而是表现出类似人类开发者的行为模式。
比如早期版本,走法生成在单元测试全过,但集成测试发现它漏了王车易位的合法性检查。工程师agent的修复不是理解规则,而是看到测试失败→定位代码→添加条件判断→验证通过。这个过程重复了17次,直到所有边界情况被覆盖。
更意外的是评估函数。作者没有给agent任何国际象棋知识,只给了测试标准:材料分+位置表,目标是对战Stockfish 1200胜率超50%。agent自己摸索出的权重配置,和人类引擎的经典值相差不到15%。
但有个失败案例。搜索深度的迭代加深策略,agent始终调不好。时间控制要么太激进(深度3就停,太弱),要么太保守(深度20超时判负)。作者最终手动干预,给了一个简单的时间分配公式:基础时间+每步增量×0.1,深度上限动态调整。
第三个教训:测试定义能力边界。agent能在测试覆盖的范围内优化,但测试没覆盖的盲区,agent不会自动填补。
成本核算:token花在哪最值
整个项目跑了约340万token。按当时Claude API价格,总成本约47美元。分布很有启示:
架构规划占12%(Opus,贵但省时间)。工程师实现占61%(Sonnet,主力消耗)。经理协调占19%(反复读取任务板、解析输出、生成指令)。测试运行占8%(非LLM成本,可忽略)。
作者做了对照实验:砍掉架构师,让经理直接分派任务给工程师。总token降到280万,但工程师互相阻塞的时间增加,实际 wall-clock 时间从4.2小时变成11.7小时。且最终引擎强度下降约180 ELO,因为模块接口设计粗糙。
另一个实验:把3个工程师加到5个。token消耗飙升到520万,但完成时间只从4.2小时降到3.8小时。边际收益递减明显——协调开销吞噬了并行收益。
最意外的发现是经理的token效率。早期版本经理用详细自然语言写任务描述,每轮决策消耗约800 token。优化后改用结构化JSON+简短注释,降到220 token,决策质量无显著差异。
第四个教训:在agent系统中,沟通格式的压缩率直接影响吞吐量。自然语言对人类友好,对agent是冗余开销。
失败案例:当agent遇到模糊目标
不是所有任务都适合agent并行。作者尝试过一个变体:让agent优化引擎的"风格"——让棋风更具攻击性,同时不损失强度。
这个目标失败了。因为"攻击性"没有可量化的测试标准。作者试过用胜局平均步数、子力交换频率作代理指标,但agent优化的结果对人类观察者"感觉更激进",实战强度却下降。
最终这个任务被拆成两个可量化子目标:提高战术机会识别率(用 puzzles 测试集)、降低局面简化倾向(用特定开局测试)。agent在这两个目标上表现稳定,但"风格"本身仍是人类判断。
另一个失败是代码重构。作者让agent在功能保持的前提下优化代码结构。结果agent反复陷入"重构→测试失败→回滚→再重构"的循环,3次尝试后作者手动终止。推测原因:重构的收益(可读性、可维护性)没有自动化测试覆盖,agent无法获得反馈信号。
第五个教训:agent需要可量化的反馈闭环。模糊目标和长期收益,目前仍是人类专属领地。
Stockfish对战:50%胜率背后的真相
最终引擎在1200 ELO设定下对Stockfish取得52%胜率。作者强调这个数字的语境:Stockfish 1200不是"弱",而是被故意限制计算资源的版本。同等硬件下,完整Stockfish的ELO超过3500。
对战数据显示引擎的明显短板。残局转化率只有38%,远低于开局和中局的61%。时间压力下(每步5秒)胜率暴跌到31%,说明搜索深度对强度影响极大。特定开局(如西西里防御纳道尔夫变例)胜率仅29%,暴露评估函数对复杂中局结构的理解不足。
但有个意外发现:引擎在"非标准"开局(如1.b3,1.g4)表现反而更好,胜率67%。作者推测是因为Stockfish 1200的评估在这些少见局面中同样不准,而agent优化的评估函数对"非典型"局面的权重配置恰好形成优势。
这个发现引出一个问题:如果让agent自我对弈优化,而不是以Stockfish为基准,会得到什么样的棋风?
作者没有继续这个实验。但他在项目总结中写道,5个agent、4小时、47美元,产出一个能击败入门级Stockfish的引擎——这个投入产出比,在两年前是不可想象的。
真正让他兴奋的还不是结果,而是过程中反复出现的模式:规划质量决定并行效率,协调吞吐量决定整体速度,测试覆盖决定能力边界,反馈清晰度决定优化上限。这些模式似乎不只适用于国际象棋引擎。
如果给agent一个更模糊的目标——比如"设计一个让新手觉得有趣的教学引擎"——测试套件该怎么写?
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.