当前位置: 首页 > news >正文

Agent验证技能开发实战:从创建到维护的完整指南

最近我在折腾 pstack 的验证技能,核心解决一件事:Agent 用自然语言生成操作指令之后,怎么知道它真的把应用改对了。以前很多 Agent 只能说“我已完成”,但页面到底是不是按预期变化、接口有没有返回正确、数据有没有落库,它自己并不确定。pstack 新增的创建与维护验证技能,就是把“验收应用”这件事拆成可被 Agent 调用的技能:从打开页面、点击、输入、截图,到断言、汇总报告,全部按固定流程执行。这个方向最适合正在做 AI Agent 开发、应用 QA,以及想用 Agent 跑回归测试的人。这篇不会讲太深奥的 Agent 理论,更多是我实际创建和调验证技能时踩过的点。

1. 验证技能在 Agent 里的定位:先搞清它是工具还是流程

1.1 Agent 跑通不等于验证通过

很多团队会告诉 Agent“去新增一个用户”,Agent 也确实执行完了:打开后台、点新建、填表单、提交,最后还回了一句“已完成”。如果你只看这一步,会觉得 Agent 很能干。但真正的问题在后面:新增用户真的出现在列表里了吗?用户名和填写的表单一致吗?账号能正常登录吗?这些都不该靠 Agent 本身的“感觉”判断,而要靠一个可重复的验证流程。

这个差异就是验证技能存在的原因。它把“验证”从 Agent 的随机行为里剥离出来,变成一个固定的执行单元。Agent 只负责理解任务、调用技能、解释结果,而技能内部用确定性的步骤完成检查和断言。

我之前踩过一种典型状况:Agent 说创建成功,实际是接口返回 200,但页面上因为权限校验,用户列表根本没有刷新出来。如果只依赖 Agent 自身判断,这个问题会被漏掉。加一层验证技能后,操作完立刻检查列表里是否有目标用户名,问题当场暴露。

1.2 验证技能与普通 MCP 工具的差别

“Agent Skill 和 MCP 有什么区别”这个问题最近经常被问到。简单说,MCP 更像给 Agent 一根“可调用的管子”,通过标准接口暴露某个工具能力;而 Skill 通常包含更完整的执行上下文:目标、步骤、提示词、默认参数、错误处理策略。

验证应用这件事尤其适合做成 Skill,而不是裸 MCP 工具。因为验证不是单次动作,而是“打开页面→等待元素→填写表单→提交→等待跳转→断言结果→截图”这样的流程。如果每一步都拆成独立 MCP 工具交给 Agent 临时拼装,很容易漏掉等待条件和断言步骤,结果就是操作都成功但验证并不过关。

pstack 里做验证技能时,我会把整个验证链路写在一个技能定义里。这样 Agent 调用时只需要说“验证一下登录流程”,技能内部自动执行完整链路,而不是让 Agent 现场决定先调哪个工具。

1.3 把验证分成“行为操作”和“结果断言”两部分

验证技能设计时最核心的一点,是把“用户怎么操作”和“结果怎么判断”分开。

行为操作包括:打开 URL、输入账号密码、点击登录按钮、等待页面跳转、填写表单、提交。这部分解决的是“像真实用户一样”的行为路径。

结果断言包括:当前 URL 是否包含 /dashboard、页面上是否出现“欢迎回来”、列表里是否存在目标用户名、接口返回的 code 是否为 0、数据库或接口查询结果是否符合预期。这部分解决的是“这个应用真的符合预期吗”。

如果只写行为操作,那就是一个自动化脚本,不叫验证;如果只写断言,那又没法让 Agent 真正去操作应用。两个部分合在一起,Agent 才能既执行又验收。

2. 创建首个验证技能前,先把环境、对象和验收标准列清楚

2.1 环境条件:本地浏览器、测试应用、账号和数据隔离

创建验证技能之前,不要急着写配置。先确认环境。

我一般先列一个最小清单:

  • pstack 服务可用,Agent 能正常调用技能。
  • 验证环境里有可访问的浏览器驱动或自动化运行时。
  • 测试应用有独立地址、测试账号和测试数据。
  • 网络策略允许 Agent 执行容器访问目标应用。
  • 有日志和截图输出目录,权限要放开。

这里最容易忽略的是网络策略。Agent 运行在一个容器或远程执行环境里时,本地机器能访问的localhost它不一定能访问。我第一次配置验证技能时,总是报“页面打不开”,排查半天发现是容器里访问不到宿主机上的测试应用地址。

测试账号也要提前准备。验证登录、创建用户、修改配置这类流程时,如果只能用生产账号或管理员账号,风险很大。最好准备一套测试专用账号,并且每次验证后能清理测试数据,避免多个 Agent 任务之间互相影响。

2.2 验证对象拆解:页面、接口、流程、权限、数据一致性

验证技能不能笼统地说“验证这个应用”。要把验证对象拆到可断言的颗粒度。

页面层:元素是否可见、文本是否正确、跳转 URL 是否符合预期、按钮是否可点击。

接口层:请求返回状态码、业务 code、响应字段、耗时。

流程层:登录是否进入首页、新建后是否出现成功提示、审核流程能否走通、报错时是否有合理提示。

权限层:普通用户看不见管理入口、未登录访问受保护页面是否跳转登录、越权操作是否被拒绝。

数据一致性:界面显示的数据和接口返回是否一致,操作完成后数据库或列表是否更新。

一个验证技能不必覆盖所有层,但设计时要想清楚这次验证要覆盖哪几层。比如验证“登录”时,至少覆盖页面层和接口层;验证“新建用户”时,至少要覆盖页面跳转、接口返回、列表数据更新三层。

2.3 把“像真实用户一样”翻译成可判断断言

“像真实用户一样”听起来很抽象。落到验证技能里,其实就是回答几个具体问题:

  • 用户打开应用时能看到什么?是登录页面还是首页。
  • 用户登录后进入哪个页面?跳转地址是什么。
  • 用户点新建按钮后,表单是否出现,光标是否进入第一个输入框。
  • 提交成功后,页面有没有成功提示,列表有没有新数据。
  • 如果输入的手机号已存在,页面会不会给出明确错误文案。

这些都可以写成断言。不用关心这个断言“像不像人”,只要它来自真实用户的使用路径,并且结果可判断,就是有效验证。

我建验证技能时,会先手工走一遍流程,把每一步在浏览器里看到的实际状态记下来。比如“登录成功后 URL 从 /login 变成 /dashboard”“新建用户成功后出现 toast:创建成功”。然后把这些状态翻译成技能里的断言条件。这样比凭空设计更可靠。

3. 用 pstack 创建验证技能的实操流程

3.1 技能目录与基本结构

pstack 里一个验证技能通常由三部分组成:技能说明、执行脚本、配置文件。具体目录名可以根据你安装的版本调整,但思路通用。

我习惯用这样的结构:

skills/ verify_login_flow/ skill.yaml verify.py README.md assets/

skill.yaml 负责描述这个技能是干什么的、Agent 在什么场景下应该调用它、参数怎么传、超时时间是多少。verify.py 负责真正执行浏览器自动化操作和断言。assets 放截图或报告。

skill.yaml 里一般包含 name、description、version、parameters、timeout 这些字段。description 尤其重要,因为 Agent 是否想起用这个技能,主要靠 description 判断。写得太窄,Agent 该用的时候不会用;写得太宽,不该用的时候反而乱用。

示例配置:

# 示例配置,字段名以你实际安装的 pstack 版本为准 name: verify_login_flow description: 验证登录流程。当用户希望检查登录功能是否正常、登录页面是否可用时调用。 version: 0.1.0 parameters: - name: base_url description: 测试环境访问地址 required: true - name: username description: 测试账号 required: true - name: password description: 测试密码 required: true timeout: 60

description 里我建议写清楚“验证”两个字,同时写清楚适用场景。比如“当用户希望检查登录功能是否正常时调用”,这比“执行登录”更贴合验证技能定位。

3.2 先写最小验证用例:打开页面、点击、断言

第一次创建验证技能,不要想着一步到位写复杂业务流。先写一个最小用例,把链路跑通。

以“验证登录流程”为例,最小用例是:

  1. 打开登录页面。
  2. 输入测试账号和密码。
  3. 点击登录按钮。
  4. 等待页面跳转或元素出现。
  5. 断言 URL 是否进入 /dashboard。
  6. 截图保存。
  7. 返回验证报告。

对应脚本核心部分可以是:

# 示例伪代码,实际写法取决于 pstack 封装的浏览器 API from pstack import PlaywrightSkill, assertion class VerifyLoginFlow(PlaywrightSkill): async def run(self, context): page = await context.new_page() await page.goto(self.params.base_url + "/login") await page.fill("input[name=username]", self.params.username) await page.fill("input[name=password]", self.params.password) await page.click("button[type=submit]") await page.wait_for_url("**/dashboard", timeout=10000) assertion.assert_contains( page.url, "/dashboard", "登录成功后应跳转到 dashboard" ) await page.screenshot(path="assets/login_success.png") return { "status": "pass", "message": "登录流程验证通过", "screenshot": "assets/login_success.png" }

这里有一个关键点:点击登录按钮之后,不要立刻断言。要等页面跳转完成或者目标元素出现,否则断言可能执行太快,导致误报失败。

等待条件优先用wait_for_urlwait_for_selector,而不是固定 sleep。固定 sleep 在快机器上浪费时间,在慢机器上又不够稳定。

3.3 接入应用访问地址和测试账号

技能方案里最好不要把测试账号和密码写死在脚本里。不同的环境、不同的账号,验证结果会完全不同。

我更建议把这类信息做成参数,在调用技能时传入。这样同一个技能可以复用到多个环境,也方便隔离测试数据。

调用示例:

pstack run verify_login_flow \ --param base_url=https://demo.example.com \ --param username=test_user_01 \ --param password=******

如果你的 pstack 没有命令行运行方式,也可以在 Agent 对话里让模型根据上下文自动填充参数。不过自动填充的风险是模型可能猜错地址,所以至少 base_url 要提前配置好。

账号和密码这类敏感信息,建议走环境变量或密钥管理,不要在 skill.yaml 里明文出现。验证技能本质上也是一个程序,密钥泄露问题同样存在。

3.4 注册技能并让 Agent 调用

创建完技能之后,需要让 pstack 能发现它。一般需要把技能目录放到 pstack 配置的技能加载路径里,或者在管理界面点击“扫描技能”/“重新加载”。

加载成功后,可以做一个快速测试:打开 Agent 对话,直接输入“请验证一下登录流程,使用我提供的测试账号”。理想情况是 Agent 能自动匹配到这个验证技能,并执行完整流程。

如果 Agent 没有匹配到,先检查技能的 description 和名称是否和用户表达相关。比如用户说“检查登录页能不能用”,技能描述里如果只有“验证登录流程”而没有提到“检查”“登录页”,匹配度可能不高。

第一次调用成功后再进入复杂场景,不要一上来就让 Agent 验证一个完整的“新增用户→分配权限→模拟登录→数据清理”流程。复杂流程排查起来会非常麻烦。

4. 验证技能维护:日志、重试、用例更新和版本控制

4.1 从单条用例到多场景用例集

单个验证用例跑通之后,很快会遇到新需求:登录验证完了,还要验证新增用户、修改密码、导出数据。这时候不要为每个场景都新建一个完全独立的技能,而是考虑维护多场景用例集。

我一般会把同属于一个应用的验证用例放在同一个技能目录下,每个用例是一个独立脚本或独立函数。比如:

skills/ verify_management_console/ skill.yaml cases/ test_login.py test_create_user.py test_update_password.py test_export_data.py common/ selectors.py

这样 Agent 可以调用整个技能指定跑某个用例,也可以一次跑全部回归用例。

用例之间要尽量互相独立。比如 test_create_user 不能依赖 test_login 已经执行成功,因为验证技能可能只被调用其中一个用例。每个用例最好自己完成前置登录、业务操作、断言和清理。

4.2 失败重试不能无脑重复,要看失败类型

验证技能在 Agent 工作流里常见的一个问题是:失败了,Agent 又盲目重试,结果还是失败。浪费时间,还可能污染测试数据。

我自己的处理方式是先分类失败类型。

第一类:环境类失败。比如应用没启动、网络超时、页面加载太慢。这类可以重试,通常重试一两次就能恢复。

第二类:定位类失败。比如选择器找不到、按钮文案变化、页面改成异步加载。这类重试没有意义,应该直接输出失败原因,提示维护技能里的选择器。

第三类:业务类失败。比如提交后接口返回报错、数据没有写入、权限校验未通过。这类可能是应用有 bug,更不该让 Agent 反复重试,而是要把结果留给人去确认。

可以在技能里加一个简单的失败分类字段,把错误类型带回给 Agent。这样 Agent 在判断是否重试时就有了依据。

4.3 维护周期与日志规范

验证技能不是建完就结束了。应用页面结构一变,技能里的选择器、断言、流程就可能失效。所以维护是关键步骤。

维护周期要跟着应用迭代走。前端发布后,至少跑一遍核心验证技能;后端接口变更后,检查接口断言是否还成立;测试账号变更时,同步更新参数配置。

日志必须规范。我每次执行验证技能都会记录以下信息:

  • 执行时间、技能版本、目标环境。
  • 输入参数(脱敏后)。
  • 每个关键步骤的开始和结束时间。
  • 页面截图、接口响应摘要。
  • 每个断言的预期结果、实际结果。
  • 失败时的错误类型和堆栈。

没有日志的验证技能等于没验证。出问题时,你不知道是哪个步骤挂了,也不知道是环境问题还是应用问题,只能重新跑一遍,效率很低。

4.4 技能和 MCP 的边界:什么时候拆、什么时候合

维护过程中你会反复调整技能边界。这里给一个我自己用的判断标准:

如果验证流程里某个能力需要被多个不同技能复用,比如“读取短信验证码”“查询数据库用户状态”,那这个能力适合做成独立工具,通过 MCP 暴露。如果是一整套带有业务步骤和断言逻辑的流程,适合继续留在技能里,因为把步骤拆给 Agent 临时组合,会失去稳定性。

比如“登录验证”是一个技能,“查询用户状态”是一个通用工具。登录验证技能内部可以调用查询用户状态这个 MCP 工具,但不需要把它改成 MCP。这样技能负责编排,工具负责单点能力,边界最清晰。

另外注意:技能和 MCP 不是互斥的。好的 Agent 工程实践里,两者常常配合使用。Pstack 里新增和修改验证技能时,也可以把技能执行时需要的底层能力配置到对应的工具服务里。

5. 实际运行效果和判断标准

5.1 一次典型验证流程的过程

我以一个“后台管理系统新建用户”的验证技能为例,把实际运行过程拆一遍。

技能入口:用户提供 base_url 和测试账号。Agent 调用技能。步骤执行:

  1. 打开后台登录页。
  2. 用测试账号登录。
  3. 进入用户管理列表。
  4. 点击新建按钮。
  5. 填写用户名、手机号、角色。
  6. 点击提交。
  7. 等待成功提示。
  8. 在列表里搜索该用户名,确认出现。
  9. 调用接口查询该用户名是否存在。
  10. 截图并返回验证报告。

这个过程能做到“像真实用户”到什么程度,取决于等待条件和断言是否贴近真实。真实用户不会点击提交后 200 毫秒就判断成功,他会等一下看到提示,再到列表里确认。验证技能也要有同样的节奏。

5.2 结果判定:通过、失败、告警、跳过

验证结果不要只返回 pass 或 fail,我建议增加告警和跳过状态。

通过:所有断言符合预期,操作路径完整,截图正常保存。

失败:至少一个关键断言未通过,比如用户名没有出现在列表里,或者接口返回错误码。失败时技能应该提供现场证据,方便定位。

告警:功能主线通过,但存在非关键问题。比如页面加载时间超过预设值、控制台有警告信息、某个非关键元素延迟出现。告警不阻塞流程,但值得后续跟踪。

跳过:前置条件不满足。比如没有测试账号、目标功能未上线、找不到对应的测试环境地址。跳过时不能算通过,也不能算失败,要留下原因。

这套状态设计能让 Agent 在后续决策时更准确。否则明明该跳过,Agent 却把结果当作“验证通过”,那这个验证就是假验证。

5.3 资源占用和速度判断

验证技能要不要长期在后台跑,主要看资源占用和执行速度。

在常见环境下,单个 UI 验证流程耗时通常在十几秒到一分钟不等。涉及页面截图、接口查询和报告生成时,时间会更长。速度的判断标准不是“尽可能快”,而是“能不能在任务不超时的情况下稳定完成”。

资源方面重点关注浏览器实例数量、内存占用和并发数。不要一上来就开十个浏览器实例并行验证,很可能把测试环境搞崩。我一般先用单实例跑,确认稳定后,再压到 2 到 3 个并发,观察测试应用和 Agent 运行环境的负载。

如果技能用于定时回归,比如每天一次,反而没必要追求高并发。稳定大于速度。如果用于 Agent 对话中的即时验证,则要控制单次执行时间,尽量在 30 秒内给出结果,否则用户体验很差。

6. 常见问题与排查链路

6.1 Agent 调用验证技能时报错

先看现象,再看输入,再看环境,最后改技能。

现象层面:是技能没有被调用,还是被调用了但执行报错?如果 Agent 直接回复“我已完成”但没有执行验证技能,很可能是技能描述不清晰,Agent 没有把该任务识别为验证场景。这时调大 description 的关键词覆盖范围。

如果技能确实被调用了但执行报错,先看返回错误是超时、选择器失败、还是参数缺失。超时优先看网络和页面加载速度;选择器失败优先看页面结构;参数缺失优先看 Agent 传参是否正确。

6.2 验证结果误报:先看选择器和等待条件

验证结果不稳定,经常是以下原因之一。

选择器不稳定。很多前端组件会生成动态 id,比如id="user-23232"。这类选择器不能用于断言,否则下一次执行很可能找不到元素。优先使用稳定的属性或文本定位。

等待条件不合适。固定写死 sleep 3 秒是硬伤。页面慢时 3 秒不够,页面快时又白白等待。改成等待某个元素出现、等待 URL 变化、等待接口返回。

同页面有多个相同元素。比如页面上有多个“确定”按钮,定位时要用更具体的上下文,比如指定某个弹窗范围内的确定按钮。

排查顺序是:先看截图,确认执行到哪一步;再看日志,确认等待条件是否生效;最后打开页面手工看元素,确认选择器仍然存在。

6.3 验证技能卡在某个步骤

卡住通常不是技能逻辑写错了,而是外部因素变化。

优先检查目标应用是否可访问。常见情况:应用服务重启后地址变了、测试环境过载、页面出现验证码。

第二检查 Agent 运行环境。容器里没有浏览器依赖、磁盘写满、截图目录权限不足,都会导致卡在等待阶段。

第三检查并发冲突。多个验证任务使用同一个测试账号,一个把另一个的会话踢下线,就可能导致操作到一半页面跳回登录页。排查时看一下有没有其他任务在同时运行。

6.4 安全合规操作

验证技能也是程序,执行时要注意数据安全。不要在技能文件里留真实密码、生产密钥、身份证号、手机号。测试环境要用脱敏数据。

涉及删除、修改数据的验证流程,尽量用测试专用数据,并且增加二次确认。比如技能里可以做一个 require_confirm 开关,默认关闭,只让 Agent 在明确需要时传入 true。

如果应用启用了验证码或风控,不要想着绕过。正确做法是在测试环境关闭验证码,或者使用专门的测试通道。安全红线不能碰,验证技能也一样。

最后我个人的建议是:验证技能真正落地时,最该盯住的不是它能覆盖多少页面,而是单个验证流程是否稳定、断言是否贴近真实用户、失败时能不能快速定位。先把一条登录链路跑稳,再逐步扩到复杂业务流,比一次性铺开大量用例更稳妥。

http://www.cnnetsun.cn/news/4332672.html

相关文章:

  • GAN生成虚拟人脸:从原理到训练调优的完整指南
  • Python接口自动化测试实战:从零搭建pytest框架
  • 端到端图神经网络社交关系推荐系统系统|PyTorch+ResNet+OpenCV完整源码+训练与部署教程
  • Spring Boot相册管理系统实战:从环境搭建到文件上传与分页
  • 四年级零基础孩子学C++,多久能考GESP六级
  • 检索增强生成全链路解析:从文档加载到评估的大模型知识库工程实践
  • PyTorch手写数字识别项目实战:从数据加载到模型部署的完整指南
  • 搜狐畅游校招Java笔试题解析:游戏开发工程师考点与实战
  • Java面试短期突击:从八股文到场景题的最小复习闭环
  • 基于Scrapy的Python爬虫架构设计与反爬应对策略
  • 呼叫中心IVR智能语音导航架构:自动分流、业务分层与通话提效技术解析
  • 计算机网络安全知识点
  • 外文翻译不用愁[特殊字符]零机翻感!论文英文翻译神器太绝了
  • JavaWeb仿小米商城项目实战:从Servlet到订单事务全流程解析
  • Claude + Obsidian 2.0:打造会读会写的 AI 第二大脑知识库
  • Qt平滑手写笔迹绘制:从事件采集到贝塞尔曲线拟合
  • 2026答辩季AI工具实测:大模型、通用AI PPT工具、毕业垂直工具,差距到底在哪?
  • 基于深度学习的阿尔茨海默病早期诊断辅助系统设计与实现
  • 用Accept标头让AI代理直接获取Markdown:内容协商实用指南
  • Simulink仿真结果曲线:从可视化到汽车动力性能结论的完整解析
  • RAG三层检索策略全解析:从查询理解到融合重排
  • 车载单圈视频数据工程:从GPS遥测到Python与ffmpeg分析
  • 基于MATLAB的SAR成像仿真与舰船检测工程实践
  • 怎么理解专业化分工与协作的原则
  • 最适合人工智能开发的编程语言优缺点对比
  • Codex API成本深度解析:重度使用一个月花多少钱?
  • 数学证明验证工具链:公式OCR、SymPy与大模型推理实战
  • 兰城装饰和艺家空间设计对比,兰溪装修怎么选?
  • 基于多目标粒子群算法的微电网优化调度Matlab实现详解
  • SpringBoot维修工单系统实战:从ZIP到上线全流程解析