TL;DR:omp 的 approval 系统用三种模式(always-ask/write/yolo)+ 三层工具分级(read/write/exec)+ 逐工具覆盖,让你按任务类型精细控制 agent 的自主权。默认 yolo 最省心,项目里建议用 write 加 bash: prompt 做安全兜底。
omp 的记忆系统解决了「agent 怎么记住经验」。但经验要落地,agent 就得动手:改文件、执行命令、删除旧代码。这就引出了所有 AI 编程工具的共同问题——agent 有多大自主权? 每改一个文件都弹确认框?你会疯。完全不确认?万一 rm -rf / 呢。
approval 系统就是在这两端之间找平衡。
问题的本质
假设你让 agent「把 config.ts 里所有硬编码端口改成环境变量」。这个任务涉及:
grep搜索端口号 —— 纯读取,零风险edit逐个替换 —— 改文件,出错了能 git resetbash跑npm run build验证 —— 执行命令,理论上能rm -rf /
agent 跟人不一样:它能一秒改 20 个文件,也能一秒删 20 个文件。你得有个机制精确控制每一步的自主权。
omp 的解法是三层结构:模式 × 分级 × 逐工具覆盖。先讲每一层,再讲怎么组合。
三种模式
配置项:tools.approvalMode,默认 yolo。
| 模式 | 自动通过 | 弹确认框 |
|---|---|---|
always-ask | read | write、exec |
write | read、write | exec |
yolo | read、write、exec | 无 |
always-ask——最保守。 读取操作自动放行,写文件和执行命令都要你点头。适合你不确定 agent 会做什么的场景,比如第一次让它碰核心代码。
write——最常用。 读和写都放行,只在执行命令时弹框。这是大多数项目的 sweet spot:agent 能自由读代码、改文件,但跑 bash 命令要你确认。改 50 个文件不用点 50 次,但要执行部署脚本时你会看到。
yolo——完全自主。 所有操作自动放行,包括执行命令。适合你完全信任 agent(或者看都不想看)的场景。这也是 omp 的默认模式——它假设你知道自己在做什么。
三种模式可以随时切换,不用重启 session:
# 在 session 里改,对当前 session 生效/settings set tools.approvalMode write
# 或启动时指定omp --approval-mode always-askomp --auto-approve # 等价于 approvalMode: yolo(注意:也是 yolo,不是 write!)omp --yolo # 等价于 approvalMode: yolo三层工具分级
每种工具都有一个 approval 声明,告诉系统它属于哪个风险等级:
| 等级 | 语义 | 典型工具 |
|---|---|---|
read | 只读数据,不改变任何状态 | read、grep、glob、lsp |
write | 改变工作区/会话状态,但不执行任意代码 | edit、write、todo |
exec | 执行代码、shell 命令、浏览器操作、spawn agent | bash、eval、browser、task |
没有声明 approval 的工具默认当 exec 处理——宁可多确认,不能漏掉。MCP 服务端的工具默认声明为 write。
在逐工具覆盖(per-tool 覆盖,即 tools.approval 配置,见下一节)中引用 MCP 工具时,命名格式为 mcp__<server>__<tool>(双下划线分隔),例如 mcp__filesystem__delete、mcp__github__create_pr。不知道工具名?在 session 里问 agent “list available tools” 或用 /tools 命令查看完整列表。
这意味着:你用 write 模式时,bash(exec 级)会弹框,但 edit(write 级)不会。想要更精细?用逐工具覆盖。
逐工具覆盖(per-tool)
逐工具覆盖就是在全局模式之外,给每个工具单独设规则。比如全局用 write(读写自动、exec 弹框),但对 bash 单独设 prompt,或者对某个 MCP 工具设 deny。配置项是 tools.approval,跟 tools.approvalMode 平级:
tools: approvalMode: write approval: bash: prompt # 执行命令必须确认 read: allow # 读取总是放行(在 always-ask 下也没事) edit: allow # 编辑总是放行 mcp__filesystem__delete: deny # 禁止某个 MCP 工具每项的值:
allow:总是放行deny:总是拒绝prompt:总是弹框确认
这个覆盖在所有模式下都生效。即使在 yolo 模式,设了 bash: prompt 也会弹框。
实际用法:全局设 write,对高频安全工具设 allow,对高危工具设 prompt 或 deny。
知道三种模式和逐工具覆盖后,理解到底谁说了算比记忆配置项更重要。源码中的 resolveApproval() 函数按这个顺序判断:
resolveApproval(tool, args, mode, userConfig) │ ├─ 1. 获取工具的 approval 声明(可能是函数,动态计算) │ └─ 没声明 → 默认 tier = "exec" │ ├─ 2. 如果是 yolo 模式? │ └─ YES → 有 user policy 就用它,没有就 "allow" │ ★ 即使工具标记了 override: true,yolo 也忽略 │ ├─ 3. 工具标记了 override: true(比如 bash 检测到 rm -rf /)? │ └─ YES → user policy = "deny" → 拒绝 │ → 其他情况 → 弹框(哪怕 mode 说放行) │ ├─ 4. 有 user policy(per-tool 覆盖)? │ └─ YES → 用它(allow/deny/prompt) │ └─ 5. 模式的 tier 上限 >= 工具的 tier? └─ YES → allow └─ NO → prompt这个顺序有几个反直觉的点:
- yolo 是第一优先级的,甚至跳过安全 override。 如果你配了
yolo+ 没设bash: prompt,agent 就能执行rm -rf /而不弹框。这是故意的——yolo的字面意思就是”你负全责”。 - override(安全护盾)在非 yolo 模式下优先级高于 per-tool 覆盖。 即使你设了
bash: allow,如果命令匹配 critical pattern,依然弹框。只有bash: deny能阻止。 - per-tool 覆盖在 yolo 下是唯一的约束力。 想在 yolo 下保护自己?设
bash: prompt——这是 yolo 下的最后一道防线。
动态 approval:不是所有工具都是静态等级
有意思的是,approval 声明可以是函数。bash 工具就用了这个机制——它不是固定 exec 等级,而是检查命令参数:
// bash.ts 源码逻辑approval: (args) => { const cmd = args.command; // 匹配 critical patterns → { tier: "exec", override: true, reason: "Critical pattern detected" } if (matchesCriticalPattern(cmd)) return { tier: "exec", override: true, reason: "..." }; // 普通命令 → "exec"(但不 override) return "exec";}lsp 工具更灵活——根据操作类型返回不同等级:diagnostics 返回 read,rename 返回 write。在 write 模式下两者都自动放行(write 级已自动通过);在 always-ask 模式下诊断自动通过,重命名需要确认(除非设了 lsp: allow)。
自定义工具或扩展也可以利用这个机制——一个工具可以在不同参数下表现为不同风险等级。
弹框长什么样?标准审批提示会显示工具名、风险等级和操作上下文——比如 bash 会显示完整命令,edit 会显示目标文件和修改范围。自定义工具可以通过 formatApprovalDetails(args) 钩子追加额外的提示行(比如文件路径、预计影响的代码量)。你看到的信息足够判断”这个操作我放不放心”。
安全护盾:bash 的 critical pattern 检测
bash 工具内置了 CRITICAL_BASH_PATTERNS 正则列表。匹配任一模式时,approval 返回 { tier: "exec", override: true },触发上一步解析顺序中的第 3 条——非 yolo 下强制弹框。源码中精确的检测范围:
| 类别 | 匹配的模式 |
|---|---|
| 递归删除 | rm -rf / / rm -fr /、sudo rm |
| 权限破坏 | chmod -R ... /、chown -R ... / |
| Fork bomb | :(){ :|:& };: |
| 磁盘/文件系统 | > /dev/sd*、mkfs、dd ... of=/dev/...、shred /dev/、cryptsetup |
| 系统配置 | > /etc/passwd / /etc/shadow / /etc/sudoers、tee ... /etc/... |
| 远程代码执行 | curl ... | bash、bash <(curl ...)、eval "$(curl ...)" |
| 主机控制 | shutdown、reboot、halt、poweroff、init 0、kill -9 1 |
| 网络 shell | nc -e ... |
如前所述(解析顺序第 2 步),yolo 模式下 override 不生效——这些命令直接执行。保护策略同上:设 bash: prompt。
(历史细节:2026 年 5 月的一个版本曾让 override 在 yolo 下也弹框,但很快回退了——大量用户抱怨 yolo 模式下被”误杀”。现在 yolo 就是字面意思的 yolo。)
怎么选模式:决策框架
没有”万能模式”,按任务类型选:
| 任务类型 | 推荐模式 | 理由 |
|---|---|---|
| 探索代码、问问题 | always-ask | 不需要改文件,安全最优先 |
| 日常开发、重构 | write + bash: prompt | 自动改文件,命令要确认 |
| 跑测试、格式化 | write + bash: allow | 测试命令安全且频繁 |
| 批量自动化脚本 | yolo | 你看了脚本逻辑,信任它跑 |
| 部署 | write + bash: prompt | 部署脚本要确认,别手滑 |
| 初学 omp | always-ask | 先看懂它在干什么 |
我的日常配置(这个博客项目):
tools: approvalMode: write approval: bash: prompt read: allow edit: allow write: allowread、edit、write 的 allow 在 write 模式下其实是冗余的——这些 tier 已经自动放行。写出来是为了切到 always-ask 时也能正常工作,也方便一眼看懂配置意图。
逻辑:agent 能自由读写文件(写博客文章、改组件、调样式),但跑 bash 命令必须我确认。日常开发 90% 的操作不需要我点确认,但 npm run build、rsync 部署等命令我能看到。
当我明确要批量操作时——比如重命名 10 个文件、统一改 frontmatter——我会临时切到 yolo:
/settings set tools.approvalMode yolo干完活切回来。会话不中断,零摩擦。
常见陷阱
1. 用 always-ask 做日常开发
改一行代码弹一次框,改 20 行弹 20 次。你会习惯性点”允许”,变成人肉 yolo——既没安全也没效率。write 模式才是日常开发的正确默认。
2. yolo 下忘设 per-tool 保护
全局 yolo + 没设 bash: prompt = agent 可以无确认执行任何命令。如果你不 100% 信任 agent(或者不 100% 信任自己给 agent 的指令),至少设 bash: prompt。
3. 以为 deny 能挡住一切
deny 只在 approval 层面生效。如果 agent 用别的方式绕过(比如通过子 agent、通过 MCP 工具),需要对应的 per-tool 覆盖也配上。不过 omp 的子 agent 会继承 per-tool 配置,所以 deny 配置会穿透。
4. 混淆 CLI 标志和配置文件模式
--auto-approve 和 --yolo 是等价的——都强制 yolo 模式。想用 write 模式?必须用 --approval-mode write。
常见的踩坑姿势:配了 tools.approvalMode: write,但启动时加了 --auto-approve,以为在 write 模式——实际已经是 yolo 了。CLI 标志优先级最高,会覆盖配置文件。
跟前面系统的协作
approval 模式跟你已经配好的 Rules、Skills、Memory 形成完整的安全网:
- Rules 管底线:「禁止
fontProviders.google()」——agent 甚至不会写出这行代码 - Skills 管流程:「部署前先 build 再 rsync」——agent 知道怎么做
- Memory 管经验:「上次部署忘检查 SSL 导致失败」——agent 避免重复踩坑
- Approval 管执行:「改文件可以,跑
bash要确认」——agent 改代码不打扰你,但危险操作你 hold 住
四条线各司其职:Rules 防错,Skills 提效,Memory 省心,Approval 兜底。
还有一个跨系统的交互值得注意——子 agent(task 工具 spawn)始终以 yolo 运行,per-tool 配置会穿透,审批边界在 parent agent 的 task 调用上。所以多 agent 协作时,你只需确认”要不要 spawn”,不需要盯着子 agent 每一步操作。
下一步
approval 系统解决了”agent 能不能做”的问题。到这里,omp 的核心机制——Session、Rules、TTSR、Skill、多 Agent、Memory、Approval——已经全部讲完了。
最后一篇,我们回到最初的问题:把这些机制放进真实开发流程,omp 跟 Cursor / Windsurf 比到底谁更好? 不是参数对比,是用这个博客项目 5 个月的实战数据说话。
本文是「omp 编程工具使用探讨」专栏第 8 篇。查看专栏目录浏览全部文章。文中的配置示例来自 omp 官方文档和本博客项目的实际使用。