Agent SDK
工具权限与人工审批
设置权限模式,处理宿主回调,并区分单次允许、持久规则和隔离。
三个不同的配置层
WithTools 选择向模型提供的内置工具集合;WithAllowedTools 与 WithDisallowedTools 表达权限规则;WithPermissionHandler 处理运行时交给宿主的权限请求。规则、运行时模式和回调一起决定执行路径,不能把回调当作每次工具调用都会经过的审计入口。
初次接入可只提供 Read、Glob、Grep,确认流程后再开放写入。已经批准的工具可能直接执行;若要记录每次工具事件,应使用 Hooks。
选择权限模式
| 模式 | 使用目的 |
|---|---|
ModeDefault | 按运行时规则处理,未决请求交给审批路径 |
ModeAcceptEdits | 接受文件编辑;其他操作仍按规则处理 |
ModePlan | 规划任务;不是操作系统只读沙箱 |
ModeDontAsk | 按预设规则处理,不依赖交互式提问 |
ModeAuto | 对未决操作使用运行时自动审核,需要能力和模式确认 |
ModeBypassPermissions | 跳过运行时权限检查,只用于已有明确隔离和授权的环境 |
不要把无人值守服务配置成需要人工审批、却没有审批界面的状态。运行期切换到 bypass 还需要启动时允许 WithAllowDangerouslySkipPermissions(true);不要把它作为解决超时的通用办法。
安装宿主权限处理器
下面的片段展示保守的无界面策略:显式需要人的请求和未预先批准的操作都拒绝。它可以用于接入验证;要允许操作,应接入自己的审批界面,并把用户决定返回给该次请求。
options = options.WithPermissionMode(permission.ModeDefault).
WithPermissionHandler(func(ctx context.Context, request permission.Request) (permission.Decision, error) {
if err := ctx.Err(); err != nil { return permission.Decision{}, err }
if request.RequiresHuman {
return permission.Deny("当前入口没有人工确认界面,请在可审批的会话中重试。", false), nil
}
return permission.Deny("该操作尚未获得批准。", false), nil
})
展示审批时至少包含工具名称、参数、请求理由和影响对象。使用 ToolUseID 关联请求;若 AgentID 有值,还要标出发起请求的 Agent。不要仅凭模型生成的描述隐藏实际命令或目标路径。
返回单次允许或拒绝
permission.Allow(updatedInput, updates) 返回允许决策。仅允许本次时,传入 nil 的规则更新列表;确实需要修改参数时才提供 UpdatedInput。UpdatedPermissions 会改变规则状态,不能顺手把一次确认升级成持久允许。
permission.Deny(message, interrupt) 的说明会用于解释为什么未执行。interrupt=false 允许运行时根据拒绝结果选择其他办法,true 表达中断意图。不要把拒绝伪装成执行成功。
RequiresHuman 表示该请求不能由自动审核替代用户确认。用户页面关闭、等待超时或请求被取消时,不要默认允许。权限等待和运行回合需要各自的超时策略。
自动审核的边界
nxs 的 auto 模式需要 auto_review_v1 协商;Claude Code 使用原生权限模式确认。Bridge 不运行审核模型。即使 Supports 返回 true,设置模式仍可能因账号、模型或策略不可用而失败。
调用 session.Control().SetPermissionMode(ctx, permission.ModeAuto) 后必须处理错误,不要在界面上先显示“已开启”。
权限与沙箱
审批回答的是“这次操作是否获得授权”;沙箱限制的是“进程能触及哪些系统资源”。Go 自定义工具在宿主进程中执行,需要自行校验当前用户和数据归属,不能假设它继承运行时沙箱。详见部署与隔离。