当“正确”并非确定性时验证 agentic 行为
Validating agentic behavior when “correct” isn’t deterministic
GitHub Blog 文章提出用于 Copilot Coding Agent/Computer Use 的独立 Trust Layer。方法用 2–10 条成功 trace 构建 PTA,经视觉指标、SSIM 与 multimodal LLM 做 Semantic Merging,再用 dominator analysis 提取关键状态,并以 topological subsequence matching 验证新执行;VS Code extension 评估中 Dominator Tree 准确率、Precision、Recall、F1 均为 100%,高于 CUA 自评。
现代软件测试建立在一个脆弱的假设之上:正确行为是可重复的。对于确定性代码,这个假设大体成立。但对于像 Github Copilot Coding Agent(又称 Agent Mode)这样的自主 agent,尤其是在我们探索集成式“Computer Use”前沿时,这个假设几乎立刻失效。随着 agent 从简单的代码建议扩展到与 UI、浏览器和 IDE 等真实环境交互,正确性会呈现多路径特征。加载页面可能出现,也可能不出现;时序会发生变化;多种有效的动作序列都可能导向同一个结果。除非我们的 GitHub Actions workflow 足够稳健,能够考虑这种可变性,否则很常见的情况是:agent 成功完成了任务,但测试仍然失败——这是会阻断生产流程的“false negative”。本文将探讨如何摆脱脆弱的逐步脚本,转向用于 agentic validation(agentic 验证)的独立“Trust Layer”。我们将展示一个模型,它关注关键结果而不是僵硬路径,从而提供一种可解释、轻量、并可用于真实 CI pipeline 的行为验证方式。agent 驱动验证的挑战 设想你负责一个 GitHub Actions pipeline,它依赖 Copilot Agent Mode 来验证真实世界的 workflow。这个 agent 可能会利用 Computer Use,在容器化云环境中进行导航,以完成 workflow 验证。周二,构建是绿色的。周三,测试失败了——尽管没有任何代码变更。发生的情况是:hosted runner 上一次轻微的网络延迟让加载页面多停留了几秒。agent 等待、适应,并正确完成了任务。但你的 CI pipeline 仍然将这次运行标记为失败——不是因为任务失败了,而是因为执行路径不再匹配录制脚本或断言时序。agent 没有失败。失败的是验证。这暴露出 agent 驱动测试中反复出现的三个痛点,它们共同造成了“trust gap”:False negatives:任务成功了,但 test runner 无法容忍变化。脆弱的基础设施:测试因时序、渲染或环境噪声而失败,而这些因素与正确性无关。合规陷阱:结果可能是正确的,但由于 agent 行为偏离自动化测试预期,系统仍标记为回归。我们正处于一个过渡期:像 Github Copilot Coding Agent 这样的 agentic system 正在加速开发,但传统验证方式仍然僵硬。在确定性软件中,正确性可以简单地理解为某个特定输入匹配某个已知输出。但对于 agent,中间过程有意设计为非确定性。随着 agent 越来越多地部署到生产环境,正确性不再是遵循一组预先规定的步骤,而是“可靠地达成关键结果”。要让这些系统规模化,我们需要一种验证框架,能够区分“偶然噪声”(例如加载页面)和“关键失败”(例如未能保存数据)。正确性的关注点从“这件事发生了吗?”转向“要让成功成立,哪些事情必须发生?”为什么现有测试方法在自主 agent 面前会失效 传统测试工具在执行路径固定时运行良好。当行为出现分支时,它们就会开始失效——并不是因为这些工具工程质量差,而是因为它们假设序列是稳定的。当我们将这些方法应用到 Copilot Coding Agent,包括它在容器化环境中导航的场景时,四类常见范式的局限会变得很明显:基于断言的测试:要求人为、耗时地为每个检查编写规格,并且无法覆盖有效的替代执行路径。Record-and-replay 工具:对环境噪声高度敏感;轻微的渲染差异或时序变化经常触发错误失败。Visual regression testing:孤立地比较截图,而不理解更广泛的执行流程或语义含义。ML oracle:这些“black box”需要数千个训练样本,并且在将某个行为标记为不正确时无法提供可解释性。尽管这些方法的实现不同,但它们共享一个结构性假设:正确性由是否遵循某个特定的可观察状态序列来定义。对于 agentic system,这个假设会失效。要让开发者真正信任这些系统,包括 Github Copilot,我们必须超越线性脚本检查,开始验证结构化行为。重新定义正确性:关键行为与可选行为 要摆脱脆弱测试并构建 Trust Layer,我们必须从根本上改变对“正确”的定义。在 agentic system 中,正确执行不必看起来完全相同。它们确实需要共享一个共同的逻辑结构。概念转变 想象一个启用了 Computer Use 的 Github Copilot Coding Agent,在容器化云环境中的 VS Code 里执行搜索。一次运行中,加载页面出现了几秒;另一次运行中,UI 立即加载完成(如下所示)。场景:打开 VS Code 传统测试会把它们视为两个不同结果。但对开发者来说,加载页面只是偶然因素;它并不改变任务是否成功。我们可以将 agent 行为分为三类:关键状态:成功真实成立时必须出现的里程碑,例如到达“Search Results”页面。可选变化:由环境差异导致的偶然状态,例如 loading spinner 或装饰性 UI 变化。收敛路径:不同的步骤序列(例如使用快捷键与使用菜单)最终重新汇合到同一个结果。加载页面可能出现,也可能不出现。但搜索结果必须出现。只有后者决定正确性。从直觉到理论:Dominator analysis “必须具备”和“偶然”行为之间的区别,源自编译器理论中的 dominator relationship。在 control-flow graph 中,如果从起点到节点 B 的每条路径都必须经过节点 A,那么节点 A “dominates” 节点 B。通过将 dominator analysis 应用于 agent 执行 trace,我们可以自动识别:哪些状态是必需的 哪些状态是可选的 不同路径在哪里收敛 这使我们能够提取一个最小且可解释的正确性定义。将执行建模为图,而不是脚本 为了捕捉 agentic 行为的复杂性,我们必须不再把执行视为线性的一维脚本。相反,我们的框架使用一种称为 Prefix Tree Acceptor(PTA)的图结构来建模行为。从线性 trace 到结构化图 在这个模型中,一次执行不是一串命令,而是一个有向图,其中:节点表示可观察状态,例如 UI agent 的截图,或开发 agent 的代码快照。边表示转换,捕捉在状态之间移动所采取的动作(点击、键击或 API 调用)。为什么图很重要 将执行视为图,可以表示分支和收敛——这些概念在线性脚本中无法捕捉。分支用于刻画非确定性环境变化,例如加载页面是否出现。收敛用于识别不同路径在哪里重新汇合,表明 agent 已经成功应对某个变化,并回到主要任务流。通过将表示方式从步骤序列转为结构化行为模型,我们不再因为 agent 走了不同路径而惩罚它,而是开始验证它是否遵循了逻辑上合理的路径。我们的解决方式:一种面向正确性的结构化方法 为了让 agent 从实验性 demo 走向生产级基础设施,我们的团队开发了一种新的验证算法,不再依赖僵硬脚本,而是通过示例学习。为了测试这一点,我们聚焦于一个复杂的非确定性环境:AI agent 通过“Computer Use”导航 Visual Studio Code。只需观察 2–10 次成功会话,我们的算法就能自动构建一个“ground truth”模型,用于区分 agent 的有效变化和实际失败。workflow:从 trace 到“master”图 捕获(PTA Construction):我们收集了 2–10 条成功执行 trace,并将其转换为 Prefix Tree Acceptor(PTA),即有向图,其中节点表示可观察 UI 状态,边表示动作。泛化(Semantic Merging):我们的算法将这些 trace 合并为一个统一图。它使用三层等价检测框架——结合快速视觉指标与 LLM 语义分析——来判断两个状态是否在逻辑上等价,例如忽略时间戳变化,同时标记缺失的 UI 控件。提取骨架(Dominator Analysis):我们对合并后的图应用 dominator analysis,以识别“关键状态”,即每次成功运行都必须经过的里程碑,同时自动过滤 loading spinner 等“可选”状态。对于开发者而言,这种方法特别有价值,因为它不需要人工编写规格,也不需要大规模模型训练。由于生成的模型是实际执行状态构成的图,其决策完全可解释。当验证失败时,我们的算法会通过明确指出缺失了哪个关键状态,给出清晰的失败原因。判断两个状态何时“相同” 状态等价是 agent 验证中最难的问题。例如,我们如何知道两张不同截图是否表示同一个逻辑 UI 状态?我们通过一个三层等价检测框架解决这个问题,它从快速视觉指标逐步深入到语义理解:视觉指标:我们使用快速 perceptual hash 和 structural similarity(SSIM)立即捕捉近乎相同的状态。通过 LLM 进行语义分析:当视觉指标存在歧义时,我们使用 multimodal LLM 来判断差异是否具有语义意义。例如,LLM 知道应忽略时间戳变化或不同的窗口装饰,但会标记不同的错误消息或缺失的 UI 控件。保守合并:只有当模型确信状态等价时,我们才合并状态;当执行路径确实发生分歧时,图会自然分支。这不是简单的逐像素比较,也不是让模型判断整个任务的“LLM hand-waving”。通过防御性、节制地使用 LLM 来解决特定歧义,我们的框架既足够稳健,能够处理 UI 噪声,又足够精确,能够检测真实回归。用 dominator analysis 提取真正重要的内容 一旦各种执行 trace 被合并为统一图,我们的算法就会应用 dominator analysis 来隔离任务的核心骨架。通过支配关系定义“关键”:在图论中,如果从起点到 State B 的每条可能路径都必须经过 State A,那么 State A dominates State B。在我们的模型中,如果某个状态是任务成功完成的 dominator,我们就将其定义为关键状态。过滤过程:通过计算这些数学关系,算法会自动区分“必须具备”的里程碑与“偶然”噪声。在我们的 VS Code 实验中,“Search Dialog”状态被识别为关键里程碑,因为它是一个数学意义上的 dominator——不先触发搜索,就不可能到达结果。相反,“Loading”页面不支配任何内容;由于更快的运行会绕过它,算法会将其标记为可选变化,而不是成功所需条件。这确保“Trust Layer”框架只在关键步骤缺失时提醒你,而不是在环境波动时报警。场景:打开 VS Code 通过将这些关键节点提取为 dominator subtree,我们创建了一个“ground truth”模型,表示最小且可解释的正确性定义。这会将验证焦点从 agent 采取的具体步骤,转向它必须命中的关键检查点。在实践中验证新的执行 有了作为 ground truth 的 dominator tree,验证一条新的、未见过的执行就变成了结构比较过程,而不是寻找完美匹配。这样,只要 Agent Mode 命中“必须具备”的里程碑,它就可以按自己的方式导航环境,或调整其集成的 Computer Use 路径。当新的执行 trace 到来时,我们的验证算法会提取其状态序列,并使用 topological subsequence matching 将其与 dominator tree 进行比对。逻辑:我们不要求新的 trace 与参考完全一致;我们只要求关键状态以正确的相对顺序出现。处理额外状态:如果参考序列是 A → B → C,而 agent 生成 A → X → B → Y → C,测试仍然通过,因为额外状态(X、Y)会被视为偶然噪声。检测失败:只有在关键状态被跳过,或状态没有按所需逻辑顺序出现时,才会触发失败。评分与可解释性 我们的框架提供的不只是二元的通过/失败结果;它还提供 coverage metric 和清晰解释:Coverage:计算为匹配到的关键状态数占参考模型中总状态数的百分比。失败原因:如果 trace 失败,我们的算法会准确指出缺失的状态(例如,“Failed: State ‘Search Results’ never reached after ‘Search Dialog’”)。这种细节水平将验证从“black box”转变为开发者实际可用于调试 agent 及其环境的诊断工具。我们从评估中学到了什么 为证明这种面向 Trust Layer 的结构化方法有效,我们进行了一个受控实验,将我们的 Dominator Tree 方法与 agent 的自我评估(即 Computer-Use Agent,或 CUA,报告自己的成功情况)进行比较,场景是一个真实的 Copilot Agent 自定义 VS Code extension 测试套件。准确率差距 在用于区分成功执行与因产品 bug 或 agent 错误而失败执行的测试中,结果非常明确:Metric CUA Self-Assessment PTA (Dominator Tree) Accuracy 82.2% 100% (+17.8) Precision 83.3% 100% (+16.7) Recall 60.0% 100% (+40.0) F1-Score 69.8% 100% (+30.2) 虽然 agent(CUA)经常将失败误报为成功,通常是因为超时或误解了自身状态,但 Dominator Tree 通过关注关键里程碑是否实际到达,实现了完美区分。识别“not a bug”场景 对开发者而言,最重要的影响是减少“false alarm”。当测试失败时,你需要高信号反馈,以判断产品代码是否损坏,还是 agent 只是因环境噪声而跌倒。“Self-Verification”差距:在我们的评估中,agent 的内部自我评估(CUA)完全无法识别“Not a Bug”场景(0% F1-score)。这表明,在非确定性环境中,agent 目前还不能可靠地给自己的作业打分。结构化优势:通过在 dominator model 中使用状态和动作等价,我们的独立 Trust Layer 在正确识别失败是 agent 执行错误而非产品回归方面达到了 52.2% F1-score。结论 结构化验证大幅优于自报成功。通过将“source of truth”从 agent 的内部逻辑转移到一个学习得到的外部结构,我们可以显著减少在 CI pipeline 中因 flaky test 结果和 false positive 而浪费的人工审查时间。它今天如何融入开发者 workflow 要让这个 Trust Layer 框架有效,它必须超越研究原型,直接集成到开发者每天使用的系统中。通过将正确性视为学习得到的结构,而不是僵硬脚本,我们可以显著提高 GitHub 生态中生产级自动化的可靠性。集成点 这种方法旨在增强软件开发生命周期中的几个关键环节:GitHub Actions Pipelines:通过减少环境噪声(例如短暂加载页面)导致的 false negative,这种方法为自动化构建提供“更高信号”,避免不必要的 pipeline 阻塞。Regression testing:开发者可以使用稳定版本中的少量已验证 trace 来创建“ground truth”模型,用于自动验证未来更新。Agent evaluation:团队不必依赖 agent 报告自己的成功,而可以使用结构化验证来衡量 agent 实际命中关键里程碑的频率。UI automation:该框架允许对复杂桌面和 Web app 进行更稳健的自动化,即使 UI 元素或路径在版本之间发生轻微变化也能适应。这个框架的最终目标,是让 agent 从“实验性 demo”走向“生产基础设施”。通过提供推理能力——即失败时能够明确指向缺失的关键状态——我们为开发者提供了他们在 workflow 中信任自主系统所需的透明度。下一步 尽管结构化验证代表了重要进展,但我们当前的框架在走向完全成熟的过程中仍有一些边界。当前限制包括:需要成功 trace:算法“通过示例学习”,这意味着它需要 2–10 条成功执行 trace 来构建 ground truth 模型。目前它还不能仅从失败日志中学习或定义正确性。LLM 依赖:我们的语义等价检查目前依赖 multimodal LLM 访问。虽然这使其具备忽略时间戳或窗口装饰的“智能”,但也在验证层引入了外部 API 依赖和相关延迟。时间盲点:当前实现会验证事件顺序,但还无法标记某个特定状态(例如 loading spinner)是否持续过久。未来工作包括:时间约束与负向约束:未来工作将聚焦于捕捉时序要求(例如“loading 必须在五秒内完成”),并从负例中学习,以明确阻断已知失败路径。层次化与多模态抽象:框架将演进为把低层截图聚类为高层概念(例如“Launch Sequence”),同时集成 DOM 结构、accessibility tree 和网络流量等非视觉信号。Online learning:我们计划实现实时模型细化。当我们的算法验证新的成功运行时,它会重新计算 dominator,从而持续改进对真正“关键”内容的理解。为什么现在这件事很重要 随着 AI agent 从实验性 demo 走向核心基础设施,验证也必须随之演进,从脆弱脚本转向有韧性的系统。我们不需要用 black-box model 去评判其他 black-box model。我们需要开发者可以检查、推理并信任的结构性保证。通过结合经典编译器理论(即 dominator analysis)与 multimodal AI,我们已经证明,只需少量示例,就可以学习到一个可解释、稳健的成功定义。这个 Trust Layer 框架提供了:高效学习:从通过示例中自动推导 ground truth。运行稳健性:安全处理非确定性行为与环境噪声。完全透明:提供可解释结果和开发者可采取行动的清晰推理。展望未来,聚焦这些实用且可解释的路径,将是确保 GitHub Copilot Coding Agent 不仅强大,而且能够成为开发者 workflow 中可信组件的关键。随着 Computer Use 在整体 AI-native 开发生命周期中的采用不断增加,这一点尤其重要。通过将“source of truth”从 agent 的内部逻辑转移到学习得到的外部结构,我们提供了让自主 agent 成为现代基础设施中可行的生产级工具所需的保证。我们迈向可验证自主性的旅程才刚刚开始。若想深入了解我们基于 Dominator Analysis 的框架,可以阅读完整论文。文章 Validating agentic behavior when “correct” isn’t deterministic 最先发表于 The GitHub Blog。