Cindy 用浏览器登录态跑完整流程,先分清哪些动作要人接手

文章导读
Cindy 复用浏览器登录态跑流程,需要先回答的问题通常是「Cindy 能不能跑完」,但真正要先定下来的是「这条流程里有几个动作一旦发生就收不回来」。判断边界建议先看动作是否可逆,不要先看步骤多少或页面复杂度。可行的顺序是:把任务里会碰到的动作逐条列出来,按只读、写入、不可逆三档打标,把不可逆动作改成需要人确认的停点,最后用一条低风险任务验证停点确实拦得住动作。在跑测确认之前,这条流程建议仍按半自
📋 目录
  1. A 把一个任务里会碰到的动作逐条列出来
  2. B 按只读、写入、不可逆三档给动作打标
  3. C 把不可逆动作改成需要人确认的停点
  4. D 跑一条低风险任务验证停点是否真的生效
A A

Cindy 复用浏览器登录态跑流程,需要先回答的问题通常是「Cindy 能不能跑完」,但真正要先定下来的是「这条流程里有几个动作一旦发生就收不回来」。判断边界建议先看动作是否可逆,不要先看步骤多少或页面复杂度。可行的顺序是:把任务里会碰到的动作逐条列出来,按只读、写入、不可逆三档打标,把不可逆动作改成需要人确认的停点,最后用一条低风险任务验证停点确实拦得住动作。在跑测确认之前,这条流程建议仍按半自动处理,由人在关键一步接手。

适用场景是 Agent 带浏览器登录态跑后台或业务系统流程。操作动作是先列动作清单,再按可逆性分只读、写入、不可逆三档,不可逆档统一改成人工停点。验证方式是用一条低风险任务完整跑一遍,看停点处写请求是否真的没发出、任务状态是否停在待确认。风险边界是:读取类页面可以放手,写入类需要留痕或可回滚,提交、发布、付款、删除、授权这类动作必须人工确认后才继续。

把一个任务里会碰到的动作逐条列出来

动作清单建议按四列写全:步骤、页面地址、目标控件、触发前后的条件。写得含糊的地方通常就是容易出问题的地方,尤其是流程中途弹出的二次确认框:不少系统的发布按钮点下去之后还会再弹一层确认,Agent 如果把这层弹窗当成普通对话框自动点掉,停点就等于没有。

下面是一条内容后台发布流程的清单示例,页面路径按实际系统替换,控件描述写成能被脚本稳定定位的形式,不要只写「保存按钮」。

步骤页面地址控件 / 动作触发前条件触发后可见变化
1 打开文章列表GET /admin/articles无,直接访问登录态有效列表表格渲染完成
2 新建草稿点击后跳 /admin/articles/new新建按钮列表已加载URL 变化,出现编辑表单
3 填写标题与正文/admin/articles/new标题输入框、正文编辑器表单为空输入框有值,草稿未落库
4 保存草稿POST 保存接口保存草稿按钮标题非空出现「已保存」提示,列表多一条草稿
5 预览/admin/articles/{id}/preview预览链接草稿已存在打开预览页,内容只对自己可见
6 发布POST 发布接口发布按钮 + 二次确认弹窗文章状态为草稿状态变为已发布,对外可见

清单落到执行侧可以用一份步骤配置承载,把风险标签写在步骤上,方便后面统一拦截:

task: publish_article
steps:
  - id: open_list
    url: https://<host>/admin/articles
    action: goto
    expect: css=table.article-list
    risk: read_only
  - id: save_draft
    action: click
    target: css=button[data-action=save-draft]
    expect: text=已保存
    risk: write
  - id: publish
    action: click
    target: css=button[data-action=publish]
    expect: text=已发布
    risk: irreversible
    gate: human_confirm

按只读、写入、不可逆三档给动作打标

打标用三个问题就够:这次动作会不会改变服务端状态;改了能不能撤回;影响会不会外溢到外部可见、涉及金额或涉及权限。三问都是否,归只读;改变状态但能改回来,归写入;改变状态且撤不回,或者一发生就对外可见,归不可逆。

  • 只读:翻页、筛选、打开详情、生成预览、导出到自己手里。确认方式是自动执行,保留页面快照或接口响应摘要;一旦跳到登录页、权限不足页,就停下等人处理登录态。
  • 写入:保存草稿、改备注、改状态字段、上传附件。确认方式是自动执行但必须留痕:操作前后各取一次关键字段(列表行数、目标字段值),失败重试设上限,重试仍失败就停。
  • 不可逆:发布、提交审核、付款、删除、授权、发送通知给外部。确认方式是硬停点,Cindy 只能准备到触发前一步,点击由人完成或由人明确放行。

对照例子最容易被混淆:读取订单列表并发起导出,属于只读,导出文件落在本地,不改变对方系统状态;提交一张表单、把订单备注从 A 改成 B,属于写入,改完还能再改回去;点发布、点确认付款、点删除按钮,属于不可逆。同一个 POST 请求既可能是保存草稿也可能是发布,所以风险标签建议写在步骤配置里,不要只靠 URL 正则批量匹配。

risk_rules:
  read_only:
    methods: [GET, HEAD]
    patterns: ["*/list", "*/detail", "*/preview"]
  write:
    methods: [POST, PUT, PATCH]
    patterns: ["*/draft", "*/save", "*/update"]
  irreversible:
    methods: [POST, DELETE]
    patterns: ["*/publish", "*/submit", "*/pay", "*/delete", "*/grant"]
    fallback: block

把不可逆动作改成需要人确认的停点

停点放在不可逆动作的最后一次点击之前,不是点击之后。Cindy 到这一步只做三件事:整理待确认信息(目标对象、即将执行的动作、会影响什么、当前页面 URL 和关键字段)、把任务状态置为待确认、停止推进。没有人确认,Cindy 不点那个按钮。

Cindy 用浏览器登录态跑完整流程,先分清哪些动作要人接手

确认之后如何继续:确认信号要和 task_id 绑定,恢复时只执行停点之后的动作,不重放前面的步骤,否则会出现重复保存、多条草稿的情况。确认方式建议由人在页面上真实点一次,或者在确认渠道回一条带任务 ID 的指令;不建议让 Cindy 从「继续」这类自由文本里自己推断是否已获授权。

长时间没人确认时的处理:设超时,默认挂起而不是自动放行。超时后保留登录态、不主动关闭浏览器会话,写一条 pending_human 记录,任务由人接管继续或直接作废。

gate:
  step_id: publish
  mode: block
  timeout: 15m
  on_timeout: hold      # hold 挂起 / abort 中止,不建议 auto_pass
  require: explicit_confirm

给 Cindy 的约束可以直接写进任务提示词,重点是禁止绕路:

执行到 risk=irreversible 的步骤时,先停止点击并输出:
1) 即将执行的动作和目标对象
2) 该动作会改变什么、能否撤回
3) 当前页面 URL 和关键字段值
然后等待确认。未收到确认前,不要重试,不要换其他入口或换一个按钮完成同一个动作。

跑一条低风险任务验证停点是否真的生效

验证要选一条结果可清理的任务,例如针对一篇测试文章或测试订单走完整流程,不要拿真实对外内容做首次跑测。观察点集中在页面行为上:停点处的页面是否停在原 URL、有没有出现成功提示、列表里的状态有没有变化、浏览器网络记录里有没有发出 POST 或 DELETE 请求。

预期表现是:页面不跳转、无成功提示、目标对象状态不变、写请求没有发出、任务状态停在待确认;超时后也没有任何一步被自动补上。日志里应能看到一条明确的 gate 记录,例如:

ts=<time> task_id=<id> step=publish risk=irreversible gate=blocked
  url_before=/admin/articles/123
  url_after=/admin/articles/123
  write_request=none
  status=pending_human

不符合预期时,重点记录这几项,便于定位是分级错了还是停点位置错了:task_id、step_id、risk 标签及其来源(配置还是规则匹配)、gate 决策与决策时间、触发前后 URL、是否发出 POST/DELETE 及其目标路径、页面提示文本、重试次数、对应日志行。典型失效有两种:日志里出现 write_request=POST 而 url_after 没变,说明点击已经发生只是页面没刷新;或者二次确认弹窗被自动点掉,停点看似存在实际没拦。这两种情况都要回到动作清单,把停点往前提一步,然后重跑同一条低风险任务确认拦住为止。