别把 tool.completed 当成业务成功:AI 工具权限审计的四层事件链

tool.completed 不等于业务动作已完成。本文用一个需要确认的写工具说明事件、权限和业务回执的最小接线。

在 AI 助手里,tool.completed 不是"业务动作已完成"的同义词。要让一次创建工单、提交采购申请或发送通知可追溯,应用需要把四种事件串起来:工具提议、权限决定、工具生命周期和业务系统回执。下面用一个需要用户确认的写工具说明最小接线边界。

先定义审计链的四个锚点

  1. tool.proposed:记录工具名、toolCallId 和经过筛选的参数摘要,回答模型准备做什么。
  2. tool.permission.decided:记录 allow、deny 或 ask,以及 decisionSource;它回答为什么放行或拒绝。
  3. tool.started、tool.completed、tool.failed:记录是否真正进入 handler、耗时和错误类型。
  4. 业务回执:由 handler 调用的业务服务返回 businessRequestId、状态和查询入口,回答外部系统到底发生了什么。

第一到第三项来自运行链,第四项必须由业务服务提供。不要用模型最后一句话代替第四项。

让权限决定进入自己的审计出口

下面是接线示意,省略模型客户端、真实业务服务和 UI;它展示责任边界,不是复制即上线的完整教程:

ts 复制代码
const createTicket = defineTool({
  name: 'create_ticket',
  description: '创建当前用户有权提交的工单',
  readOnly: false,
  parameters: {
    title: { type: 'string' },
    priority: { type: 'string' }
  },
  handler: async (args) => ticketService.create({
    tenantId: auth.tenantId,
    userId: auth.userId,
    idempotencyKey: requestContext.idempotencyKey,
    ...args
  })
});

const session = await createSession({
  client,
  tools: { custom: [createTicket] },
  permission: {
    rules: { ask: ['create_ticket'] },
    askUser: async (call) => ui.confirm(call.name)
  },
  onDecision: (record) => audit.write({
    ...record,
    userId: auth.userId,
    tenantId: auth.tenantId
  })
});

这里的 onDecision 只接住权限决定;它不能替代业务回执。审计表还应在 handler 开始、结束或失败时补运行状态,并在业务服务返回后写入 businessRequestId 和权威状态。参数是否完整落盘由应用按敏感级别决定,不能把令牌、客户资料或完整请求体无条件写进审计日志。

权限决定的三种结果不能混成一个布尔值

allow 表示这次调用通过权限判断,deny 表示被拒绝,ask 表示需要确认或进入询问面。没有接入 askUser 时,涉及确认的调用可能按 fail-closed 被拒绝;应用应把这个结果显示为"需要确认/策略拒绝",而不是空数据。decisionSource 能帮助排查是用户、规则、模式、策略还是钩子做出的决定;matchedRule 若存在,也可以用于管理者复盘。

createSessionView 适合把这些会话事件投影成工具卡、确认提示和错误状态,但它不替应用保存审计数据库。页面要同时显示工具状态和业务状态:工具完成后仍要查询业务请求号,才能决定显示"已受理""处理中"还是"结果未知"。

超时后先查回执,再决定重试

业务写工具至少需要一个稳定请求号。调用超时可分成三类:尚未提交、已受理但未返回、已经有明确结果。应用先按请求号查询业务系统;只有确认未受理且业务接口允许重试时,才重新提交。SDK 的会话事件可以帮助你标记运行阶段,去重和补偿仍属于业务服务。

什么时候采用这条链

它适合 Node.js 或 Electron 应用中同时存在多轮任务、需要用户确认的工具和可查询的业务回执。Tansr 可以组织工具、权限和会话事件,把决定通过 onDecision 暴露给应用;应用仍负责身份、租户、幂等、审计存储和数据脱敏。一次固定查询或已经具备完整审计链的运行框架,不需要为了增加一条事件而迁移。

最小验收包括:允许、拒绝、等待确认各跑一次;确认工具开始和完成事件可见;超时后能按业务请求号查到最终状态;审计记录不会泄露参数中的敏感字段。完成这些检查后,再决定是否扩大写工具范围。

接口依据见 Tansr 的PermissionOptions、PermissionRules、会话与事件流和createSession。

示意代码省略真实模型和业务服务;上线前必须在自己的 Node.js 或 Electron 宿主中验证。

相关推荐
陆柒1452 小时前
跟着 Webpack 配置学习前端工程化
前端
用户6353300254792 小时前
Day 1|HTML5:一个商城首页的骨架,从 DOCTYPE 到语义化
前端
平凡的阿泽3 小时前
我用 Trae 实现了AI辩论赛
前端
对空六课3 小时前
指标口径生效时间的版本查询实现
大数据·服务器·前端·算法·数据分析
对空六课3 小时前
RFM分层边界变化的回溯计算
大数据·服务器·前端·数据库·人工智能·算法·数据分析
IT_陈寒3 小时前
Vite打包的诡异行为,让我差点提交了个错误版本
前端·人工智能·后端
鹏多多3 小时前
前端是如何死去的?| 完整时间线
前端·javascript·程序员
coding漫漫长路3 小时前
海报挪进Worker画,canvas字体又变回默认了
前端
看浪的路人3 小时前
第2讲:ReAct 模式从零实现——不用框架,手写一个 Agent 内核
前端·react.js·前端框架