先把工具调用看成跨边界事务
研究代理先读取网页再写入知识库,看似只有两个动作,实际已经跨过模型进程、工具网关、存储服务三条故障边界。模型发出写入意图并不代表服务端收到,请求返回超时也不代表存储没有提交。若调用协议只有名称、参数和一段自然语言说明,调度器只能把未知结果误判为失败,再次生成写入请求,于是同一材料得到两个不同记录标识。生产契约首先要表达的是可观察状态,而不是让模型猜测远端发生了什么。
可以把一次调用拆成已接受、执行中、已提交、已拒绝和结果未知五类状态。前三类必须附带稳定操作键,提交态还应返回资源标识、结果摘要和服务端时间;拒绝态提供机器可判定的错误类;未知态只说明连接证据不足,不授权立即重做。读取与纯计算通常可以安全重试,扣费、发送、删除和创建记录则属于有副作用事务,需要查询状态、补偿动作或人工接管。这样的分类直接决定超时后的控制流。
契约同时约束形状与业务不变量
结构化参数先消除语法歧义:必填字段、长度、枚举、格式和禁止的附加字段都应由服务端解析器验证。但类型正确并不等于操作合理,例如知识库编号存在却属于另一个租户,正文长度合法却超过账户配额,计划时间格式正确却早于当前允许窗口。因此还要为工具列出资源所有权、额度、状态转换和字段关系等业务不变量,并明确这些判断只能在可信执行端完成。模型侧校验只能改善体验,不能承担授权。
返回值也要有稳定模式。建议把业务结果与执行元数据分开:结果部分只含调用者获准读取的字段,元数据含操作键、契约版本、状态和摘要。不要把数据库异常、内部枚举全集或完整请求正文直接塞进错误信息,因为这些内容会进入下一轮提示并扩散。对可修正参数给出精确字段路径,对权限、配额和资源不存在采用不泄露细节的统一错误,再由调度层决定是否询问用户。
幂等键必须绑定真正的业务意图
随机请求编号只能追踪一次传输,不能识别两次传输是否代表同一写入。幂等键应由任务标识、工具契约版本、规范化目标和业务意图摘要共同生成,并在首次执行前由服务端以唯一约束登记。正文中的无意义空白、字段顺序和等价时间表示需要先规范化,否则重试仍会得到新键;相反,也不能只用正文哈希,因为向不同知识库写入相同内容是两个合法动作。键的作用域与保留期限必须写进契约。
服务端接到已存在的键时,不再次触发副作用,而是返回原操作的当前状态和相同结果凭证。如果同一键携带不同参数,应明确报冲突,不能默默采用第一次或最后一次请求。对于持续数小时的外部作业,登记记录需保存到超过客户端最大重试窗口;对于不可撤销支付,还应结合上游提供的幂等机制。这样即使网络在提交后断开,代理也能通过查询接口确认事实。
授权在执行瞬间重新计算
代理在规划阶段看见某个资源,不意味着执行时仍有权限。工具服务要从认证上下文取得调用者和租户,按规范化资源标识重新查询所有权、角色、资源状态与配额,不能相信模型传来的用户编号或权限布尔值。批量操作还要逐项或按受控查询范围授权,避免一个合法父级编号夹带越界子项。授权结论应绑定本次操作键,并记录采用的策略版本,便于事后解释拒绝原因。
资源标识尤其容易形成旁路:大小写、编码、别名、软删除记录和跨租户可猜测编号都可能让预检查与实际查询指向不同对象。安全实现先解析为内部规范标识,再用同一标识完成授权和写入,二者应处于一致事务或具备乐观版本条件。若资源在检查后被转移或冻结,提交必须因版本不符而停止,不能沿用几秒前的许可。
超时之后先求证再决定动作
客户端超时表示等待预算用尽,仅能证明没有及时取得响应。调度器收到未知状态后,应使用操作键调用只读状态端点;若显示执行中,则按退避策略继续观察;若显示已提交,校验结果摘要后进入下一步;若服务端确认从未接受,才允许重新投递同一键。状态端点本身要轻量、可重复且不引发新的作业,避免查询又成为副作用来源。
并非所有失败都适合重试。参数错误需要重新规划,权限拒绝应要求新的授权,配额不足应结束或等待明确窗口,依赖服务暂时不可用才适合有限退避。超过查询时限仍未知时,应冻结后续依赖写入并生成接管记录,其中包含操作键、目标摘要和最后证据。切忌让模型根据语气判断成功,也不要把“未收到错误”翻译成“已经完成”。
审计证据不等于复制敏感正文
审计链需要回答谁在何时依据什么契约请求了哪个受控目标、授权决定是什么、是否产生副作用以及最终状态。记录调用者内部标识、工具名、契约版本、操作键、目标的不可逆摘要、状态码和结果摘要通常已经足够。Cookie、访问令牌、网页全文、知识库正文与底层异常栈不应进入通用日志;确需排障的内容采样要单独授权、脱敏并自动过期。
工具输出进入模型上下文前也要按字段过滤。读取工具可返回引用片段和来源,而不是整份私密对象;写入工具只返回确认凭证,不回显秘密字段。审计日志与业务结果采用不同访问策略,导出行为同样被记录。若结果摘要由规范化响应计算,恢复流程便可比较查询结果与原始凭证,发现服务端状态被意外改写,同时不暴露具体正文。
用故障矩阵证明契约有效
验证从并发与断线开始:两个工作进程携带同一操作键同时提交,只能产生一条记录;服务端提交后立即切断连接,客户端查询应得到原资源标识;同一键更换目标或正文必须返回冲突。随后覆盖身份边界,包括伪造租户编号、已撤销角色、资源转移和批量混入越权项,所有请求都应在执行端拒绝,且失败不留下半成品。
第二组测试针对可观测性和恢复:让依赖分别在接受前、提交中和提交后超时,确认调度器选择重投、观察或继续的分支;扫描日志确保凭据与完整请求正文不存在;篡改模型输出声称成功,工作流仍只认可服务端凭证。最终以重复副作用数为零、未知状态可收敛、越权写入为零和人工接管信息完整作为门槛,才算把工具调用从一句指令变成可验证事务。
补偿动作不能伪装成数据库回滚
跨系统事务通常无法整体回滚。邮件已经送达、外部账单已经生成时,本地删除记录并不会抹去影响。契约应为可补偿动作声明对应工具、允许状态、期限和所需权限,例如撤回草稿而不是删除已发送事实。补偿本身是新的副作用,具有新的操作键、审计记录和失败状态。
设计工作流时先辨认哪些动作真正可逆,优先把不可逆提交推迟到证据齐全之后。可以先创建受限草稿、预览费用或验证目标,再经确认进入最终提交。若补偿失败,不继续递归生成补偿,而是冻结关联步骤并把远端凭证交给人工处理。
测试要让原动作成功而补偿依赖失败,确认系统如实保留部分完成状态;再重复发送补偿键,只产生一个撤回请求。用户界面应区分已回滚、已请求补偿和无法补偿,不用统一的“已恢复”隐藏外部世界仍存在的结果。
契约演进需要兼容与停用策略
工具参数、返回值或权限语义变化时提升契约版本,正在运行的任务继续引用启动时版本。服务端可以兼容读取旧请求,但不能把新必填授权字段默认为宽松值。无法安全兼容时明确停止旧版本,并让恢复器转人工或重新规划,不能在后台静默转换高风险意图。
停用前统计仍在使用旧版本的任务与客户端,提供迁移窗口和可重放夹具。描述文本、Schema、授权中间件和审计解析器应随同一版本发布,防止模型看到新说明却调用旧实现。注册中心校验内容摘要,发现主机缓存与服务器声明不一致便拒绝写操作。
兼容测试重放历史成功、拒绝和未知状态,确认相同操作键仍能查询原凭证;新旧客户端并发时唯一约束继续成立。版本切换之后观察冲突、拒绝和未知态比例,异常立即回退到上一完整契约,而不是只回退提示文案。
实现片段
const result = await tools.execute({ operationKey, actorId, input })
评论 · 0