做了一个月 LangGraph Agent 后,我们为什么用两周切到了 Skill? - 葡萄城技术团队

文章目录

做了一个月 LangGraph Agent 后,我们为什么用两周切到了 Skill? - 葡萄城技术团队

相关消息称,在前端组件测试的完整流程中,最耗时的环节往往并不是“执行测试”本身。 科技新闻。

早期流程缺少完整的自动检测闭环,生成结果仍需人工逐项检查。对测试工程而言,最核心的验收劳动并未消除:页面“能打开”,不代表它已是可交付的合格测试页面。

这正是迁移中最耗时的部分:不是简单替换模板语法,而是识别框架生命周期、绑定语义和组件实例边界。在这次迁移中,Skill 将高频排错路径固化下来,降低了团队重新查找资料和试错的次数;这一案例用于说明工作方式,不代表其他框架或组件组合都能获得同等收益。

做了背景与起因

一个典型的框架差异是组件实例的可用时机。Vue 页面中依赖 ref 和挂载后回调的初始化逻辑,不能机械地替换为 Angular 的类字段;若在视图子节点尚未就绪时读取组件实例,页面虽能渲染、按钮也可显示,但实例配置和测试接口未必真正就绪。特性验收会将“组件已初始化”和“交互后实例状态变化”拆成独立断言;失败后,再将初始化逻辑迁移到正确的生命周期或组件就绪回调,并重新执行整页验收清单。

复杂组件生成效果不佳,本质上是因为模型的可选解空间过大,容易偏离工程规范。我们将易被遗漏的经验写成清晰、可执行的规则:测试数据必须确定,依赖来源必须受控,全局事件必须限定作用域,关键的非可视状态必须具备可读取的测试接口。

统计范围为一个季度内完成的 30 个前端组件测试页面任务。我们将涉及多组件协作、API 组合、嵌套编辑或跨框架适配的任务归为“复杂场景”。下文的“首轮通过”按任务统计,指首轮产出在未修改代码的情况下,通过该任务规定的运行检查、工程规范、核心组件交互/API 组合及验证检查。

做了事件经过

即便后来没有继续以 LangGraph 作为默认入口,这段探索仍留下两条值得保留的工程经验:为关键状态定义清晰的输入/输出契约,以及为工具调用划定受限边界。后续的 Skill 设计并未抛弃这些原则,而是将其纳入更轻量的任务封装。

这正是 AI 代码生成容易失效的场景:它很容易生成一个“看起来像 Demo 的页面”,却难以直接产出一个“能接入工程体系、能稳定回归、能自动断言”的合格测试页面。

这次尝试带来的经验是:工具“能调用”不等于它“理解被测对象”。当被测产品超出通用 DOM 模型时,应为其补充领域适配层。这里为 SpreadJS 构建的是独立的 Canvas 领域探针;其他内部组件或业务层前端测试也可以按同样方式扩展,而不必等待通用浏览器工具覆盖所有语义。

做了各方回应

为了让 Agent 理解组件 API,我们加入了向量检索。但组件资料来源并不统一,网页与离线文档的同步、切分和更新都需要维护;不同的切片算法和检索逻辑也可能得到不同结果。检索只能提高资料的可获得性,无法将这些分散经验自动转化为工程约束。

对于高复杂度任务,验证清单会在生成代码前确定并固化;对于低、中复杂度任务,则只验证核心路径。这样可以避免让同一个生成过程临时发明实现、临时修改测试,再宣布自己通过。

这样一来,知识不再只是 RAG 返回的一段背景文本,而会成为生成前的强约束事实依据;团队也减少了为代码生成单独维护复杂向量知识库链路的投入。

做了影响分析

仍需强调两个限制:第一,LangGraph 阶段的验证自动化覆盖并不完整,早期结果包含人工核对;Skill 阶段则将更多核对项转为可执行断言。第二,30 个真实需求并非成对的同源样本,模型版本、知识和模板资产的成熟度、组件版本及任务结构变化都可能共同影响结果。

RAG 面临的问题并不止于资料维护。即使检索到了正确内容,也无法保证生成阶段会将其视为必须遵守的事实。

但它也暴露了后来的难题:将 apiFacts、constraints 写入状态,并不意味着生成节点一定会将其视为不可违背的前提。如果“生成代码”节点未被要求以这些事实和约束为输入,并产出可检查的执行证据,那么即使在图上增加检索或反思节点,也无法自动让代码变得更正确。

我们为 PureJS、Angular、React、Vue 等技术栈分别准备了基础模板。模板负责统一目录结构、初始化骨架和共同约束;模型只需处理本次需求特有的组件组合、数据和交互逻辑。

LangGraph 的检查点与恢复能力也需要被正确理解:配置持久化存储(checkpointer)后,它可以保存流程状态,便于调试、回溯和恢复;但解压、安装依赖、启动服务等外部副作用,仍需由业务代码设计为幂等、可检测或可清理。恢复状态并不能自动消除外部世界中已经发生的操作。

LangGraph 仍适合跨系统协调、复杂审批、长时运行和动态任务路由;Skill 则更适合将稳定的领域知识和验收流程封装为可重复执行的能力。两者也可以组合:由编排层处理真正复杂的跨系统流程,由 Skill 负责具体领域任务。关键不在于一开始搭出所有能力,而在于先判断瓶颈究竟在流程,还是在领域知识与验收。

组件产品的通用性会进一步放大这项作业的复杂度。以 Wijmo 等企业级前端组件库为例,即使只是“验证表格编辑功能”,也可能需要覆盖嵌套编辑器、筛选、排序、冻结等 API 组合,处理事件边界和真实用户场景中的交互顺序,并兼顾 PureJS、Angular、React、Vue 等框架差异。组件越通用,功能与 API 的组合空间越大,测试页面的构建成本也越高。

为解决这个问题,我们先用一个多月搭建了基于 LangGraph 的自定义 Agent,希望实现端到端流程的完全可控;随后又用约两周,将组件测试页面生成与验证这条核心生产链路切换到 Skill 方案。

关键不在于“资料很多”,而在于将查询输出转化为结构化事实。例如,一个生成任务在编码前至少要明确:目标框架、组件版本、需要使用的属性/事件、已验证的样例模式、不可改动的工程入口,以及必须暴露的测试状态。资料查询阶段只负责确认这些事实,不直接产出代码;代码生成阶段则必须以这些事实为依据完成实现。

MCP 解决的是工具与 Agent 的连接方式,并不会自动补齐领域语义。本文中的断言由 Playwright 测试脚本执行;Playwright MCP 只是让 Agent 调用浏览器操作的可选传输层,不能与 Playwright Test 的断言运行时混为一谈。以 Playwright MCP 服务为例,它适合页面导航、点击、输入和 DOM 查询,但其默认抽象以浏览器和 DOM 为中心。面对 SpreadJS 等以 Canvas 渲染为主的组件,单元格、选区和工作表状态未必能从 DOM 中可靠推导;仅靠通用点击和 DOM 结构,也很难完成具备业务语义的编辑与验证。

当时,团队决定自建一套可控的 Agent 流程。我们希望每一步都能接入相应的资料和工具,并能根据结果分支、重试或进入失败处理流程。因此,我们选择了 LangGraph:它可以将模型、工具和业务逻辑拆分为独立节点,再用状态和条件边描述流程如何继续、结束或回退。

我们将流程固定为一条可检查的闭环:

在随后的一个季度内,我们完成了 30 个任务,并观察到:复杂场景的首轮通过率从约 60% 提升至 92%,典型页面的交付周期从约 4 小时缩短至约 30 分钟。

这次实践的价值不只在于换了一套方案。无论使用哪种组件库、Agent 或 Skill,下面几条都可作为通用经验。

自动修复最多尝试 3 轮。这个数字是防止无意义循环的安全上限,而非通用的最优参数;若达到上限后任务仍失败,系统会保留失败项、已尝试的修复方案和未覆盖范围,交由人工接管。

Skill 不等于把长提示词简单保存成文件。针对组件测试页面生成这一场景,我们将前一阶段反复出现的知识和约束沉淀为四类工程资产,并额外增加了一个横切的工具适配层。每类资产都直接对应 LangGraph 阶段的一个痛点。

因此,测试页面并非普通的功能 Demo。Demo 只需展示功能可用;测试页面则必须做到:结果可重复、状态可观察、行为可断言。它既要符合组件 API 的标准使用方式,也要适配现有测试工程的依赖管理、目录结构与自动化测试规范。

验证也不只是检查页面能否加载,而要检查三个层次:动作是否发生、状态是否变化、最终行为是否符合预期。筛选输入框可以输入文字,不代表筛选功能已经实现;程序化断言还需检查筛选后的记录数和数据状态是否确实发生变化。

以一个典型的表格测试页为例,原始需求应拆分为下面的特性契约,而非直接将一段自然语言交给模型:

这暴露了一个常见误区:“有 RAG”不等于“代码生成时拥有可靠知识”。 如果资料未被组织成明确的规则、模板或输入契约,检索结果仍只是上下文中的一段普通文本。更具体地说,若生成节点无需列出所依据的 API 事实,后续也没有断言检查这些事实是否被正确使用,那么检索链路只能提高“模型看见资料”的概率,无法保证“模型按资料实现”。

自定义 Agent 的灵活性背后,是大量需要自行负责的部分:状态字段、节点职责、路由逻辑、工具权限、错误分支、知识库更新、模型行为变化、日志和回归测试。每增加一项规则或功能,都可能牵动流程、状态和提示词中的多个位置。

“独立”不等于一定要换一套模型,而是要保证被测实现代码无法反向改写验收依据。为使这一边界可执行,P0 特性及其断言需要在生成代码前由需求方或经评审的固定模板确认,并存入受版本保护的只读资产;修复环只允许改动页面实现和明确允许修改的生成文件。每轮修复后,执行器都会先校验验收资产的哈希或 diff 白名单,再重跑完整的 P0/P1 基线。模型可以提出功能实现的候选方案,却不能既定义 P0 的期望值,又在失败后自行改写它。

这个例子说明,一份合格的 AI 测试页任务至少应具备“自然语言需求 -> 特性契约 -> 实现 -> 独立断言 -> 根因修复 -> 全量回归”这条可追踪的完整链路。

这里需要澄清:LangGraph 与 Skill 并不是同一抽象层的直接替代品。LangGraph 是自定义 Agent 的流程编排层,主要负责状态、路由、工具调用和失败分支;Skill 则是面向领域任务的能力封装方案,将任务说明、知识、规则、模板、脚本和评测组织为可复用能力,由宿主 Agent 执行。

无论是验证新功能、完成版本回归,还是复现真实用户场景,自动化测试开始前都必须先构建一个完整的组件测试页面。它的作用是将抽象的组件能力还原为可运行的真实场景:准备测试数据、组合相关组件、配置 API 参数、实现交互逻辑,并将关键状态暴露给自动化断言。测试页面准备不足,测试脚本便缺少稳定、可靠的验证对象。

这一个多月里,我们完成的并非一份简单配置,而是一套需要长期维护的运行时系统。对于动态、跨系统的任务,这种投入可能值得;但面对当前高频、规则密集的组件测试页面生成任务,它逐渐显现出过度设计的特征:流程很灵活,代码生成的准确性和验证难题却没有被优先解决,迭代速度也被维护成本拖慢。

部分 Canvas 组件也会提供 ARIA、DOM 代理或公开 API;问题不在于“Canvas 必然不可测”,而在于不能仅凭通用 DOM 可靠推导全部领域状态。

在 Playwright Skill 中,我们将 Playwright 的浏览器操控能力与领域探针一并封装:在受控的页面上下文中执行专门的查询/编辑脚本,并将成效以结构化数据返回给断言步骤。

对前端组件测试而言,最终衡量的不是 Agent 是否拿到了运行地址,而是测试页面能否接入工程、需求是否真正实现、断言是否真实执行,以及失败是否被完整保留。这也是我们用两周切到 Skill 的原因:它更直接地解决了当时最昂贵的问题。

探针只能调用组件公开 API 或显式暴露的测试接口,不能读取或修改私有实现。需要验证真实用户输入路径时,仍优先使用鼠标、键盘等真实浏览器交互;探针用于准备可重复的前置状态,或作为状态判定依据(oracle)检验交互后的业务结果。这样既不会将 Canvas 测试退化为“直接改内部状态”,也避免仅凭像素或 DOM 猜测业务状态。

一次典型失败可能是:页面可以正常打开,行冻结按钮也能被点击,但 F3 的实际值仍为 0。根因不应被笼统描述为“按钮不工作”后就让模型盲改,而要落到可验证的具体类别,例如初始化发生在目标框架的组件实例就绪之前,或按钮只更新了局部变量而未更新真实的表格实例。修复完成后,系统会重新运行 F1–F5 的全量断言,而非只重跑 F3,从而及时发现修复是否意外破坏了初始冻结或样式逻辑。

这份契约带来两个直接好处:问题可以沿状态链路追踪,失败不再只剩一段模糊的自然语言描述;文件操作、构建和测试等确定性步骤也可以封装为受限工具,无须让模型临场猜测执行命令。

团队估算的纯人工工期至少为 5 个工作日;在 Skill 辅助下,实际用 2 个工作日完成。

除单个页面生成外,我们还完成过一项跨框架迁移:将一个覆盖 50+ 组件的测试页面从 Vue 迁移至 Angular。这并非简单的语法替换;迁移过程中需要同时处理两种框架在组件组织、数据绑定和生命周期上的差异,并逐一排查组件 API、页面结构和测试行为带来的错误。

这些约束不属于“提示词优化”,而是工程职责分层:Skill 负责领域能力,宿主负责工具权限、上下文隔离、重试和报告。没有这层边界,任何看似方便的自主构建或浏览器控制,都会重新带来维护和安全风险。

图结构本身并不难,难在让每个节点对同一任务形成一致理解。这类 Agent 的状态可以抽象为:

失败不是流程终点,而是下一轮修复的输入。我们会将失败归为生态/依赖、框架生命周期、API 语义、测试接口或业务交互等类别,再将失败断言、实际状态和错误日志带回相应的实现环节。每次修复都应更贴近原始需求、保持代码质量并解决根因;不得通过删除功能、修改预期结果或绕过异常制造“通过”的假象。

最初选择 LangGraph 并非一时冲动。我们需要处理的是一条完整的端到端链路:理解自然语言需求、查询组件资料、生成测试页面、准备并运行工程、分析错误,甚至将外部问题的最小复现 Demo 转换为回归测试页面。

规则当然不能神奇地保证结果正确,却能有效缩小模型自由发挥的范围。面对组件嵌套、事件联动和数据状态等复杂场景,AI 无须每次重新猜测项目约定,而是在固定边界内实现需求特有的差异部分。

一个 Canvas 组件的领域探针可以提供类似下面的契约:

第一阶段,我们将“企业级”理解为尽可能多地自建编排能力;完成这轮探索后才更清楚地看到,当前核心任务的约束大多稳定且重复。随着通用编码 Agent 和工具链已能承担通用执行动作,业务团队不必再为每个领域任务重建一层运行时。于是,注意力从“让流程无所不能”转向“让领域约束可验证”。

最终,我们将组件测试页面生成与验证这条核心生产链路切换至 Skill。这里的“切换”并不表示 LangGraph 在所有场景都不再需要,而是指日常高频的页面生成与验证不再以自建 Agent 图作为默认入口。

我们将数百个组件和 API 条目、架构说明,以及经过生产验证的使用模式,整理成可按需读取的结构化参考资料。生成代码前,系统会先核验 API 签名、语义、多框架差异和使用边界,明确关键前提。

复盘后,我们不再优先追求“能处理一切的通用 Agent”,而是先解决“如何稳定生成符合组件测试规范的页面”这一核心难题。

一条好的规则,最好同时说明“为什么”和“如何验”。例如,“数据必须确定”不能只写成禁止随机数,还要使验证能够重放同一组数据;“状态可读”也不等同于随意读取组件私有字段,而应约定使用公开 API 或显式暴露的测试接口。只有这样,规则才是可执行的约束,而非空泛的愿望清单。

需要先说明边界:这并非将同一批任务在两种方案上重复运行的严格 A/B 实验。两个阶段的模型、文档、样例和验证能力都在持续演进,因此下文数据反映的是生产链路整体演进后的阶段性结果,不能将全部增益简单归因于 Skill 本身。即便如此,这次演进仍回答了一个具体的工程问题:面对规则密集的组件测试任务,应该先自建复杂的 Agent 运行时,还是先将领域知识和验收标准沉淀为可执行能力?

当然,我们也可以为这类能力单独开发自定义 MCP 服务。但在这个聚焦的测试工作流中,我们选择让领域适配器随 Playwright Skill 一起版本化,而非维护一个独立服务。这并未消除探针的契约、权限和兼容性成本,只是降低了当前单一工作流的接口协调成本;如果同一能力需要被多个 Agent 或应用复用,自定义 MCP 服务反而可能是更合适的边界。

在企业工程中,Skill 还需要在宿主 Agent 之外划定清晰的运行边界。生成和验证只能在目标劳动区内读写;环境检查、启动和测试应使用明确的脚本或命令白名单;工具输出应尽量结构化,避免将无关目录、凭据或配置带入上下文;任务结束后,无论成功或失败都要清理浏览器和临时进程。

在一个多月里,我们围绕这条链路搭建了一个自定义 Agent,主要能力包括:

我们的测试环境采用由 SystemJS 在运行时加载模块的无构建方案。通用大模型更熟悉 Vite、Webpack 等现代前端构建流程,生成的代码往往“符合通用前端开发习惯”,却无法直接适配现有工程体系。每次开发前,工程师都要重复同步组件知识、工程约束和测试规范,效率因此被进一步拖慢。

Skill 在其中承担的并非“一键转换”角色,而是将框架模板、组件知识、既有实现模式和验证步骤串成可重复执行的流程:先识别原页面的组件和功能点,再匹配目标框架的模板与实现方式,生成迁移结果,最后通过自动化断言发现并修复差异。

这组数字中,最值得关注的不是“生成速度”,而是工程师的人工复核投入由约 2 小时降至约 5 分钟。这意味着更多判断由可执行断言承担,并不等同于整套验证流程的机器执行耗时也只有 5 分钟。相应地,Skill 的维护成本并未消失,只是从维护图节点和运行时,转移为维护知识、规则、模板、断言和领域探针。

这并非“LangGraph 不如 Skill”的结论。真正的选型依据在于任务的不确定性来自哪里:如果不确定性主要来自跨系统流程和动态决策,编排层的投入值得;如果不确定性主要来自领域知识、工程约束和验收规则,优先将这些资产产品化通常更有效。

这使生成过程中的错误集中在真正需要针对性思考的功能实现上,而不再反复出现在文件结构、基础初始化等通用环节。模板也不应只是可复制的样板文件:它需要保留稳定的测试挂点、生命周期位置、依赖加载方式和清理逻辑,使生成结果从一开始就进入可验证的轨道。

问题的根源不在于缺少一个反思节点,而在于组件测试依赖大量隐性领域知识:什么样的数据才能保证结果可重复,哪些状态必须以可读方式对外暴露,哪些样例可以跨任务复用,以及不同框架下哪些工程结构绝不能改动。这些知识零散分布在提示词、检索结果和开发者经验中,模型每次生成代码时都可能遗漏其中一部分。

这里最重要的设计,不是“多跑几轮”,而是让验收标准独立于实现代码。需求会预先拆分为带优先级的特性清单:P0 是阻断交付的核心行为,P1 是高复杂度任务必须覆盖的关键路径,P2 是补充优化项。代码生成后,修复可以参考既定需求、断言成果和错误日志,但不得改写原始需求、期望值或验收脚本。未执行的验收项必须在报告中标记为“未覆盖”,不能计作通过;环境错误和超时同样属于“未完成验证”,而非任务成功。

Agent 可以完成构建和运行,并得到可访问的页面地址,但这只能说明环境链路已经走通。它无法证明筛选功能确实改变了数据状态、编辑操作确实写回了数据模型,或冻结和事件逻辑确实符合需求。

Skill 的正常运行离不开浏览器测试工具的支撑。实践中,我们评估了 Playwright 的两类接入方式:通过 Model Context Protocol(MCP)暴露通用工具能力,或在 Skill 中组织工具调用、探测脚本和领域断言。二者并不互斥,Skill 也可以调用 MCP;我们调整的是工具抽象边界,并非否定 MCP 协议本身。

从自建 LangGraph Agent 到 Skill,我们经历的不只是一次技术迭代,更是一次问题聚焦:从追求完全可控的通用流程,转向优先解决高频、稳定、规则密集的组件测试任务。

葡萄城产品 MCP 服务,引起了广泛关注。

声明:本文信息来源于相关渠道或网络,版权归原作者所有。如涉及版权问题请及时与本站联系删除。本文观点仅供参考,不代表本站立场。
天枢新闻网
天枢新闻网资深内容创作者,致力于为广大读者提供及时、准确、深度的新闻资讯与行业分析。
领域:科技 发布:2026-08-04