让助手操作电脑之前,先明确哪些动作可以直接执行、哪些必须确认、哪些禁止。
windows-bot-memory/action-layer
这篇不是 computer-use 教程,只记录为本地助手设计权限时的一些判断。
很多本地助手做到一半,都会走到同一个诱惑面前:既然模型能理解用户意图,为什么不直接让它操作电脑?
可以让它操作电脑,但前提是动作不能从一条临时命令开始。
codex-windows-bot 的动作层后来选择了一条更慢但更稳的路:所有能力先进入 action registry,再按风险分级,再决定是否需要确认,最后只调用固定 handler。通用 shell 不进入这张表。
动作注册表不是命令菜单
动作注册表看起来像一份功能清单:
{ "id": "projects.brief", "category": "projects", "risk": "R0_READ", "enabled": true, "confirm": false, "handler": "projects_brief", "args_schema": { "project": "string", "mode": "string" }, "max_output_chars": 10000, "redact_args": ["project"]}但它不该被当成“命令菜单”。它更像一份动作说明:这个动作叫什么、属于哪类、能不能启用、是否要确认、参数长什么样、输出最多多长、哪些参数不能进审计明文。
它要解决的是:每个动作先登记清楚,再进入执行。用户说“帮我看看项目状态”,模型不能临时编一个命令;它只能选择注册过的动作,比如生成项目 brief、列出固定检查、读取允许的入口文件。
风险等级要比功能名称更早出现
动作层里应先看 risk,再看 handler。
风险可以分成五层:
R0_READ 只读本地状态R1_LOCAL_LOW 低风险本地副作用R2_LOCAL_STATE 本地状态改变,需要确认R3_EXTERNAL 外部发送、上传、日历、权限等,需要确认R4_FORBIDDEN 通用 shell、宽泛删除、敏感信息提取等,拒绝这样讨论一个能力时,会先问它会碰到什么。截图当然有用,但它会捕获当前屏幕,所以应归到需要确认的一类:固定目录保存,只返回尺寸和文件名。再比如上传文件是常见需求,但它跨出了本机范围,就应该落到外部动作层,不应混在本地修改步骤里。
风险等级把“能做什么”改成了“在什么约束下能做”。
R0 先读,R2/R3 再确认
本地助手最适合先开放只读观察,控制类动作可以晚一点。
- 读取健康状态。
- 列出能力目录。
- 生成项目 handoff。
- 查看插件开关。
- 列出近期审计摘要。
- 读取本地页面快照。
- 查看窗口是否存在标题。
- 列出本地截图元数据。
这些动作仍然要限流、脱敏、审计,但它们不改变机器状态,也不向外发送内容。
一旦动作会改本地状态,就应该进入确认门。比如重启本地私聊机器人、删除过期成果、打开已知应用、清理任务文件,都不应由一句自然语言直接执行。
一旦动作会触达外部系统,就更要和本地步骤拆开。创建日历、发送提醒、上传结果文件,这些动作需要独立确认。不能因为前一步“生成文件”已经被确认,就顺手把文件发出去。
确认门要和动作执行分离
确认不能只靠一句“确定吗”。
更稳的做法是:先生成一个待确认请求,记录动作 id、风险等级、参数摘要、过期时间和确认码摘要;确认时只允许用这个请求 id 继续执行。
这样至少有三个好处:
- 用户确认的是一个已冻结的计划,而不是重新解析一遍自然语言。
- 确认码过期后,旧请求不能被再次利用。
- 审计里能看到“计划”和“执行”是两个阶段。
这也能避免一个常见漏洞:模型在确认后重新理解用户输入,把原本只读的任务变成写入或外部发送。
文件、项目、应用、桌面要走不同窄门
“操作电脑”听起来是一个能力,实际应该拆成几类窄门。
文件动作只负责本地助手根内的普通文本读取。项目动作必须通过注册项目 id,只能读相对路径,只能运行枚举好的检查。应用动作只看静态 app registry 和聚合运行状态,启动应用要另走确认。桌面动作只读窗口的安全摘要,不返回进程号、命令行、原始标题、截图或控件树。
这几个门不能互相借权限。
知道某个应用存在,不代表能读它的安装目录。知道某个项目存在,不代表能运行它的任意脚本。能看到当前窗口存在标题,也不代表能把标题明文发回聊天。
把门拆开,系统会少一点“全能感”,但风险范围清楚得多。
输出也要限流和脱敏
很多安全设计只盯输入,其实输出更容易泄漏。
动作层里每个动作都应该有输出长度上限。返回健康状态时,别带完整路径、进程命令行、配置文件位置、运行参数、消息原文或账号标识。返回审计时,只给摘要、计数、动作 id 和风险,不给原始参数正文。
这会牺牲一些调试便利,但对聊天入口很必要。维护者要看原始日志,可以回到本机高信任环境;远程聊天只应该拿到被裁剪过的事实。
一个简单判断是:如果这段输出被截图转发出去,会不会暴露本机结构、账号线索、私有消息或凭据类内容。会的话,它就不该从动作层原样出来。
health 和 selftest 是发布检查门
动作注册表写完不代表安全。
长期能兜住这套系统的,是 health 和 selftest。每新增一个动作,都应该至少验证三类事情:
- 正常路径能返回预期摘要。
- 禁止路径要明确拒绝,别悄悄换成别的行为。
- 聊天输出里没有本地路径、进程细节、私有标识、凭据类内容或原始消息。
这类检查听起来繁琐,但它能防止“今天为了方便临时加一个参数”慢慢把窄门拓宽。
尤其是本地助手一旦接入聊天入口,安全范围就不能只靠开发者记着,新增动作时这些检查都得跑一遍。
现在的判断
本地助手接管电脑前,应先做动作分级,再考虑 UI 控制或通用命令。
一个可长期维护的动作层至少要回答这些问题:
- 这个动作是否在注册表里。
- 它属于只读、本地副作用、本地状态改变、外部动作,还是禁止项。
- 它是否需要确认。
- 它的参数能不能被 schema 限住。
- 它是否只调用固定 handler。
- 它的输出能不能被裁剪和脱敏。
- 它有没有 health 或 selftest 覆盖。
当这些问题都答得清楚,助手才适合逐步增加能力。
真正容易出问题的地方,是把一次本机操作包装成普通聊天回复。更稳妥的做法是让每个动作先登记清楚,需要确认的就停下来等确认,不该做的直接拒绝。
继续读