Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f3c41bd
refactor: reorganize permission decision policies
kermanx May 25, 2026
44be735
feat: rework permission decision policies
kermanx May 25, 2026
4c2573a
Merge branch 'main' into codex/permission-decision-policies
kermanx May 25, 2026
1f0679b
fix: align permission policies with execution metadata
kermanx May 25, 2026
bd79f2a
fix: preserve glob permission rule matching
kermanx May 25, 2026
0ba9a37
fix: keep plan review before session approvals
kermanx May 25, 2026
71f0b19
fix: restore plan review outcome telemetry
kermanx May 25, 2026
d970ead
fix: prefer ask rules over allow rules
kermanx May 25, 2026
4cb74ff
Merge branch 'main' into codex/permission-decision-policies
kermanx May 25, 2026
0b667f7
fix: avoid unnecessary git marker probes
kermanx May 25, 2026
67c3d32
Merge branch 'codex/permission-decision-policies' of https://github.c…
kermanx May 25, 2026
0c94bfa
Merge origin/main into codex/permission-decision-policies
kermanx May 25, 2026
a244148
feat: rework permission decision policies
kermanx May 25, 2026
9ad3a9b
refactor: simplify v1.1 record migration
kermanx May 25, 2026
9472a48
update
kermanx May 26, 2026
b730803
Merge branch 'main' into codex/permission-decision-policies
kermanx May 26, 2026
8641479
fix
kermanx May 26, 2026
287ad87
Merge branch 'codex/permission-decision-policies' of https://github.c…
kermanx May 26, 2026
a15a0e9
Merge branch 'main' into codex/permission-decision-policies
kermanx May 26, 2026
1c10e6c
fix
kermanx May 26, 2026
98d5e79
Merge branch 'codex/permission-decision-policies' of https://github.c…
kermanx May 26, 2026
f086bca
fix
kermanx May 26, 2026
2a99ad6
fix
kermanx May 26, 2026
8e1c0d1
fix
kermanx May 26, 2026
321e629
fix
kermanx May 26, 2026
667a124
fix
kermanx May 26, 2026
fff5ede
fix
kermanx May 26, 2026
9e9d713
fix
kermanx May 26, 2026
ac06e62
fix
kermanx May 26, 2026
29f4cd5
fix
kermanx May 26, 2026
b0befb4
Merge remote-tracking branch 'origin/main' into codex/permission-deci…
kermanx May 26, 2026
f075072
fix
kermanx May 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/modern-permission-policies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@moonshot-ai/agent-core": minor
"@moonshot-ai/kimi-code": minor
---

Rework tool permission decisions around resolved execution metadata, with exact-argument session approvals and centralized permission telemetry.
125 changes: 125 additions & 0 deletions PERMISSION_DECISION_MODEL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Tool Permission Decision Model

本文记录 tool call permission 判断模型:一个已经通过前置校验、可以被执行的 tool call 如何被分类为 `approve` / `deny` / `ask`。本文不覆盖工具是否存在、是否启用、参数 schema 是否合法、ask 交互过程、以及工具执行时报错。

**设计目标:**

- Permission policy 模块化、单队列。每个 H2 对应一个 `PermissionPolicy`,按文档顺序执行,首个命中的 policy 给出最终 decision。
- Permission 层不硬编码每个 tool 的参数结构或 UI 文本。

**Execution contract:**

- 文件安全边界由 `execution.accesses` 表达,policy 基于它判断 cwd 外、敏感文件、git control path 等规则
- 用户配置规则的括号参数由 `execution.matchesRule(ruleArgs)` 解释
- `matchesRule` 接收 `ToolName(...)` 括号内的原始字符串,不由通用 rule parser 拆分逗号或解释字段语义
- `matchesRule` 必须是同步纯函数,只基于 `resolveExecution(args)` 已经解析好的信息判断,不做 IO
- `Approve for session` 的可记忆对象由 `execution.approvalRule` 表达,值是完整的 permission rule 字符串,例如 `Bash(git status)` / `Read(/repo/a.txt)`
- `approvalRule` 由 tool 根据自己的语义生成;permission policy 不从 raw args 推导命令、路径、搜索表达式、agent type、skill identity 等字段
- 内置 tool 提供 `matchesRule` 时沿用 permission DSL 的旧匹配语义:空 pattern 命中,leading `!` 表示取反;路径 subject 使用 path glob 语义,普通字符串 subject 使用 glob 语义
- 如果 execution 没有提供 `matchesRule`,带括号参数的规则不命中;需要参数级别匹配时,tool 必须实现 `matchesRule`
- approval UI 使用 `execution.display` / `execution.description`;需要状态型审批 UI 的 tool(例如 `ExitPlanMode` 的 plan 内容与选项)也必须由自己的 `resolveExecution` 返回展示信息;`PermissionPolicy` 不返回、不拼接、不改写 UI 展示文本

**Telemetry contract:**

- `PermissionPolicy` 不直接打 permission 相关 telemetry;单队列执行器在 policy 命中和 approval 完成时统一打点。`exit-plan-mode-review-ask` 例外:它在自己的 `resolveApproval` 回调中记录 `plan_resolved` 事件,用于追踪 plan review 的最终用户决策
- `PermissionPolicy` 可以返回开放结构的 `reason` object;`reason` 只放额外的非敏感 primitive 摘要,没有额外信息时省略
- Policy 命中时记录 `permission_policy_decision`
- `policy_name`: 命中的 policy name,例如 `cwd-outside-file-access-ask`
- `decision`: `approve` / `deny` / `ask`
- `tool_name`, `permission_mode`
- 如果 policy 返回 `reason`,展开记录其中的非敏感摘要,例如 file access operation、是否 cwd 外、是否敏感路径、是否 git control path
- 用户完成 ask 时记录 `permission_approval_result`
- `policy_name`: 发起 ask 的 policy name
- `result`: `approved` / `approved_for_session` / `rejected` / `cancelled` / `error`
- `tool_name`, `permission_mode`
- 可记录 `has_feedback`、`approval_surface`、`duration_ms`、`session_cache_written`
- `reason` 和 telemetry 都不记录 raw tool args、raw path、raw command、用户配置 rule 原文、approval UI 文本
- 用户配置规则命中时只记录非敏感匹配摘要,例如 `rule_decision`、`has_rule_args`、`match_strategy`,其中 `match_strategy` 可为 `tool_name_only` / `matches_rule`

## pre-tool-call-hook: PreToolCall Hook Decision

- Hook 返回 `block` -> `deny`
- Hook 返回 `allow` 或无结果 -> 继续后续判断

## auto-mode-ask-user-question-deny: Auto Mode AskUserQuestion Deny

- `permissionMode=auto` 且 tool 是 `AskUserQuestion` -> `deny`

## plan-mode-guard-deny: Plan Mode Guard Deny

- plan mode active 且当前没有 plan file path 时调用 `Write`/`Edit` -> `deny`
- plan mode active 且 `Write`/`Edit` 目标不是当前 plan file -> `deny`
- plan mode active 且 tool 是 `TaskStop` -> `deny`

## user-configured-deny: User Configured Deny Rules

- 用户配置 `deny` rule 命中 -> `deny`
- 本阶段只处理用户配置 `deny` rule;`ask` / `allow` rule 在后续各自 policy 中按文档顺序判断
- 用户规则按配置顺序扫描,命中第一条本阶段对应 decision 的 rule 即返回
- `ToolName` 无括号参数时只匹配 tool name
- `ToolName(ruleArgs)` 先匹配 tool name;tool name 命中后调用 `execution.matchesRule(ruleArgs)`,返回 `true` 才算命中
- `mcp__server__tool` / `mcp__server__*` 仍通过 tool name 匹配 MCP tool name
- `*(ruleArgs)` 可作为全工具匹配模式;tool name 命中所有工具,括号参数仍按 `matchesRule` 解释
- 路径、命令、搜索表达式、agent type、skill identity 等参数语义由对应 tool 的 `resolveExecution` / `matchesRule` 定义,不在 policy 中硬编码

## auto-mode-approve: Auto Mode Approve

- `permissionMode=auto` -> `approve`
- 任何在 auto mode 下也必须阻止的规则都必须表达为 deny,并放在本 policy 之前

## user-configured-ask: User Configured Ask Rules

- 用户配置 `ask` rule 命中 -> `ask`

## exit-plan-mode-review-ask: ExitPlanMode Review Ask

- `ExitPlanMode` 且 plan mode active 且 plan 内容非空且 `permissionMode!=auto` -> `ask`
- 本 policy 必须在 Session Approval Memorized History 之前执行;plan review 的审批对象包含当前 plan 内容,普通 session history rule 不能表达“这份新 plan 已经被 review”

## user-configured-allow: User Configured Allow Rules

- 用户配置 `allow` rule 命中 -> `approve`
- 使用与 User Configured Deny Rules 相同的 rule 匹配方式

## session-approval-history: Session Approval Memorized History

- `Approve for session` 记住的是本次 `execution.approvalRule`
- 后续请求用 `approvalRule` 生成的 `session-runtime` rule 走与用户配置 rule 相同的 parser / matcher;命中 -> `approve`
- `session-runtime` rule 只在本 session replay / parent-child 继承中生效,不作为用户配置 rule 参与 `user-configured-*` policies
- `execution.approvalRule` 是必选字段;tool 必须明确给出 session approval 的记忆边界
- v1.1 -> v1.2 wire migration 会把缺少 `sessionApprovalRule` 的 legacy session approval record 按旧 action label 尽力补成 rule;runtime 不再做 legacy record 兼容

## plan-mode-tool-approve: Plan Mode Tool Approve

- `EnterPlanMode` -> `approve`
- plan mode active 且 `Write` / `Edit` 目标是当前 plan file -> `approve`
- `ExitPlanMode` 不在 plan mode active 状态 -> `approve`
- `ExitPlanMode` 在 plan mode active 但没有有效 plan 内容 -> `approve`

## sensitive-file-access-ask: Sensitive File Access Ask

- `execution.accesses` 中存在敏感文件 `.env` / SSH private key / credentials path -> `ask`

## git-control-path-access-ask: Git Control Path Access Ask

- `execution.accesses` 中存在 `.git` 控制目录或 git control dir path -> `ask`

## cwd-outside-file-access-ask: CWD Outside File Access Ask

- `execution.accesses` 中存在 `read` / `write` / `readwrite` / `search` file access,且目标 path 在 cwd 外 -> `ask`

## yolo-mode-approve: YOLO Mode Approve

- `permissionMode=yolo` -> `approve`

## default-tool-approve: Default Tool Approve

- 默认 `Read` / `Grep` / `Glob` / `ReadMediaFile` / `SetTodoList` / `TodoList` / `TaskList` / `TaskOutput` / `WebSearch` / `FetchURL` / `Agent` / `AskUserQuestion` / `Skill` -> `approve`

## git-cwd-write-approve: Git CWD Write Approve

- tool name 为 `Write` / `Edit`,且 `execution.accesses` 中的写目标在 POSIX git cwd 内、目标在 cwd 内 -> `approve`

## fallback-ask: Fallback

- 以上全部未命中 -> `ask`
2 changes: 1 addition & 1 deletion docs/en/configuration/config-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ Rules are written as a `[[permission.rules]]` array of tables, where each rule c
| --- | --- | --- | --- |
| `decision` | `string` | Yes | Decision result; one of `allow`, `deny`, `ask` |
| `scope` | `string` | No | Rule scope; one of `turn-override`, `session-runtime`, `project`, `user`; defaults to `user` |
| `pattern` | `string` | Yes | Match pattern in the form `ToolName` or `ToolName(arg-pattern)`. `ToolName` must match the runtime tool name exactly — built-in tools are `Read`, `Write`, `Edit`, `Bash`, `Grep`, and so on (see [Built-in tools](../reference/tools.md)) |
| `pattern` | `string` | Yes | Match pattern in the form `ToolName` or `ToolName(arg-pattern)`. `ToolName` must match the runtime tool name exactly — built-in tools are `Read`, `Write`, `Edit`, `Bash`, `Grep`, and so on (see [Built-in tools](../reference/tools.md)). Argument patterns are interpreted only by tools with built-in argument matchers, such as `Bash`, file tools, and search tools; MCP tools and custom tools match by tool name only |
| `reason` | `string` | No | Rule description for debugging or auditing |

Example:
Expand Down
2 changes: 1 addition & 1 deletion docs/en/customization/mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Stdio entries in a project-level `.kimi-code/mcp.json` execute local commands wh

## Tool naming and permissions

MCP tools are exposed using the naming convention `mcp__<server>__<tool>`. Permission matching supports `*` and `**` wildcards, so `mcp__github__*` covers every tool from the `github` server.
MCP tools are exposed using the naming convention `mcp__<server>__<tool>`. Permission matching supports `*` and `**` wildcards in tool names, so `mcp__github__*` covers every tool from the `github` server. MCP tool arguments are not part of permission matching; allow or deny the exact MCP tool name, or use a tool-name wildcard.

Calls that do not match any rule trigger an approval request. Choosing "Approve for this session" in the approval prompt auto-approves subsequent matching calls.

Expand Down
2 changes: 1 addition & 1 deletion docs/zh/configuration/config-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ api_key = "sk-xxx"
| --- | --- | --- | --- |
| `decision` | `string` | 是 | 决策结果,可选 `allow`、`deny`、`ask` |
| `scope` | `string` | 否 | 规则作用域,可选 `turn-override`、`session-runtime`、`project`、`user`;默认 `user` |
| `pattern` | `string` | 是 | 匹配模式,格式为 `ToolName` 或 `ToolName(arg-pattern)`。`ToolName` 必须与运行时真实工具名一致——内置工具是 `Read`、`Write`、`Edit`、`Bash`、`Grep` 等(详见 [内置工具](../reference/tools.md)) |
| `pattern` | `string` | 是 | 匹配模式,格式为 `ToolName` 或 `ToolName(arg-pattern)`。`ToolName` 必须与运行时真实工具名一致——内置工具是 `Read`、`Write`、`Edit`、`Bash`、`Grep` 等(详见 [内置工具](../reference/tools.md))。参数模式只由带内置参数 matcher 的工具解释,例如 `Bash`、文件工具和搜索工具;MCP 工具和自定义工具只按工具名匹配 |
| `reason` | `string` | 否 | 规则说明,供调试或审计使用 |

示例:
Expand Down
2 changes: 1 addition & 1 deletion docs/zh/customization/mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ MCP server 配置写在 `mcp.json` 中,分为两层:

## 工具命名与权限

MCP 工具按 `mcp__<server>__<tool>` 命名。权限匹配支持 `*` 和 `**` 通配,例如 `mcp__github__*` 命中该 server 下所有工具。
MCP 工具按 `mcp__<server>__<tool>` 命名。权限匹配支持工具名中的 `*` 和 `**` 通配,例如 `mcp__github__*` 命中该 server 下所有工具。MCP 工具参数不会参与权限匹配;请放行或拒绝精确的 MCP 工具名,或使用工具名通配

未命中权限规则的调用会触发审批请求;在审批弹窗中选择 "Approve for this session" 后,后续同类调用将自动放行。

Expand Down
142 changes: 0 additions & 142 deletions packages/agent-core/src/agent/permission/action-label.ts

This file was deleted.

59 changes: 0 additions & 59 deletions packages/agent-core/src/agent/permission/check-rules.ts

This file was deleted.

Loading
Loading