webwright — 本课题摘录
读了哪几篇: 01-agent-loop(中央 agent 循环)、04-completion-gate(完成门禁与自我校验)。
其余两篇(两种环境与代码即动作、模型后端)本轮没读。
这一家在本课题里的位置:它是"什么时候停"这一问里唯一一个说"模型说了不算"的。
它对本课题回答了什么
决定四:完成门禁 —— 把"做完了"变成一个可核对的磁盘事实
它先把问题点破:模型很爱"幻觉式完成"——没真正做完就宣称做完了。 后果是评测分数虚高、实际失败。
它的答案:模型想说"我做完了",必须先满足三件事,而且三件事都是磁盘上能查到的:
① 把任务拆成若干条「可独立验证的约束/筛选/动作」,写进一个计划文件
│
② 写一个最终脚本,真跑一遍,产出逐条对应的证据 + 动作日志
│
③ 跑一个「自我校验」裁判,写出结果文件,里面的判定必须是「通过」
│
▼
只有第 ③ 步的文件真的存在、且判为通过,循环才放行「完成」
(依据:前沿库 · Webwright · 完成门禁与自我校验 —— 模型想 done=true 必须先把任务拆成 critical points 写进 plan.md、跑 final_script 产出逐条截图与动作日志、再跑 self_reflection 裁判写出 predicted_label=1 的结果文件,门禁检查这个文件才放行)
"把完成变成一个磁盘事实"这句话是这一篇的核心。 其它家的收工判据都在内存里(模型不再调工具 / 调了完成工具 / 停止条件谓词为真),只有它把判据放到了循环之外、放到了一个别人也能查的地方。
裁判本身是两阶段的
阶段 1(并行,每条证据一次调用)
每条证据 ──► 让模型打一个分 + 写一段理由
(解析失败重试至多三次,仍失败记零分)
│
▼ 收集所有理由
阶段 2(一次聚合调用)
把「每条证据的理由编号列表」+「动作日志」+「全部证据」一起给模型
│
▼
回复必须以「状态:通过」或「状态:失败」结尾
│
▼
解析末尾那一行 ──► 通过 / 失败 / 解析不出来当失败
(依据:前沿库 · Webwright · 完成门禁与自我校验 —— self_reflection 是两阶段——阶段1并行地对每张截图让模型打 1-5 分并写理由(解析失败重试≤3、仍失败记0分),阶段2把所有理由+动作日志+全部截图一起聚合成一次调用,要求回复以 Status: success/failure 结尾)
三个可抄的实现细节:
| 细节 | 为什么 |
|---|---|
| 解析很宽容 | 先用正则抠两行,抠不到再退回当 JSON 解析;而且提示词明确要求"只返回这两行,别返回 JSON" |
| 只认最后一个"状态"行 | 模型可能在中间提到"状态",取最后一处;缺失或畸形一律当失败 |
| 证据自动发现 | 不显式传时自动找编号最大且有证据的那次运行,agent 不用手动列清单 |
(依据:前沿库 · Webwright · 完成门禁与自我校验 —— 裁判解析先正则抠 Score/Reasoning 两行抠不到再当 JSON 解析;最终裁决只 认最后一个 Status 行,缺失或畸形一律当 FAIL)
"缺失或畸形一律当失败"这个默认方向是对的。 判定"成没成"的地方,不确定就该判没成。 对比 fara 的"步数耗尽也标成完成"——同一个位置,一个默认失败,一个默认成功,后者出了问题。
决定四补充:退出的唯一信号是一条消息
循环里没有布尔标志、没有返回值判断——退出的唯一方式是往消息列表尾部塞一条"退出"角色的消息。 (依据:前沿库 · Webwright · 中央 agent 循环 —— DefaultAgent 的 while True 里,退出的唯一信号是消息列表最后一条的 role 等于 "exit",不是异常也不是返回值)
这跟 mini-swe-agent 一模一样(那边也是"最后一条消息是不是退出角色")。两家独立收敛,而且都配了"异常自带该追加什么消息"的机制。
这条设计的好处:"为什么停的"和"停了"用同一个数据结构表达。 退出消息里可以带原因、带最终答案,不需要另开一个字段。