首页 / OpenHarness 源码课 / OH03: Permission Model

OH03: Permission Model OpenHarness · 对标 S03

S03 同题:在 Agent 能调工具的前提下,用策略 + 可选人工确认划安全边界。

OpenHarness 把判定收拢在 PermissionChecker.evaluate,配置在 PermissionSettings;交互确认通过 permission_prompt 注入(TUI 默认 ui/permission_dialog.ask_permission)。

权限链路:工具请求 → 策略判定 → 确认或放行 → 执行。

🎯 问题(与 S03 一致)

模型可能发起删文件、跑 Shell 等高风险调用;Harness 要在自动化可控之间折中:哪些默认放行、哪些必须问用户、哪些硬拒绝。

🔍 配置:PermissionSettings

定义于 config/settings.pymode(见下)、allowed_tools / denied_tools 名单、path_rules(glob,可 deny 某类路径)、denied_commands(glob,匹配 Bash 等命令串)。课内 S03 的多种 PermissionMode 在 OH 里目前收敛为三个枚举值,这是产品范围差异,不是「少实现一半」的简单对比。

🔍 模式:PermissionMode

  • DEFAULT:只读工具直接 allowed变异工具返回 allowed=Falserequires_confirmation=True,等待 permission_prompt
  • PLAN:阻断变异工具(规划态不写盘),与课内 plan 叙事接近。
  • FULL_AUTO:策略通过后一律放行,类似高风险的「全自动」——仍受 deny 名单与 path/command 规则约束(见 evaluate 顺序)。

🔍 判定:PermissionChecker.evaluate

关键参数:tool_nameis_read_only(来自 OH02BaseTool.is_read_only)、file_pathcommand(由 query._resolve_permission_file_path / _extract_permission_command 从原始 input 与 Pydantic 模型两侧抽取,避免路径规则对不上字段名)。

分支顺序(先读代码再记)denied_toolsallowed_toolspath_rules deny → denied_commandsFULL_AUTO → 只读放行 → PLAN 挡变异 → 默认模式「变异需确认」。

Python
# permissions/checker.py — PermissionDecision 与 evaluate 核心语义(节选)

@dataclass(frozen=True)
class PermissionDecision:
    allowed: bool
    requires_confirmation: bool = False
    reason: str = ""

# DEFAULT + 非只读 → 需确认
return PermissionDecision(
    allowed=False,
    requires_confirmation=True,
    reason="Mutating tools require user confirmation in default mode",
)

🔗 接入循环:query._execute_tool_call

evaluatenot decision.allowed:若 requires_confirmation 且提供了 permission_prompt,则异步询问;用户拒绝则返回错误型 ToolResultBlock;用户同意则不再次调用 evaluate,直接进入 tool.execute。若无 prompt 且需确认、或直接硬拒绝,则返回带 reason 的错误块。读源码时注意 if/else 嵌套,避免误解为「确认后重算策略」。

💬 TUI:ask_permission

ui/permission_dialog.pyprompt_toolkit 打一行 [y/N],是最小可行确认;与 Claude Code 富交互相比,教学上更利于看清「prompt 是可插拔依赖」。

⚖️ 与课内叙事对照

维度 课内 S03 OpenHarness
模式数量 多种(acceptEdits、bypass…) 当前 3 种枚举 + 名单 / glob 规则
确认 UI 产品级终端 / IDE 可注入 permission_prompt,默认简单 y/N
只读快捷放行 课内概念 显式 is_read_only 分支
路径级策略 课内常合并讲 path_rules + fnmatch

🤔 思考题

  1. 为何 allowed_tools 要在 path_rules 之前检查?若某路径被 deny 但工具在白名单,结果会怎样?
  2. permission_promptNone 时,默认模式下变异工具是「静默拒绝」还是抛错?对应哪段分支?
  3. FULL_AUTO 仍可能拒绝的情况有哪些?

📎 延伸阅读

OH01–12 目录 · OH02 · OH04 · S03 · D03 · S10 Hooks(与 PreToolUse 顺序)