TP
TaskPilots

面向生产环境的智能体平台。

预约演示
4 条产品线,一套运行底座
智能体系统 1775235316 3m45s

工具注册表和权限边界,别放在提示词里硬写

围绕可靠多智能体工作流构建的研究与运营笔记。

TP

TaskPilots 编辑部

AI 系统研究

更新日期

1775235316

工具注册表和权限边界,别放在提示词里硬写

围绕可靠多智能体工作流构建的研究与运营笔记。

很多团队在单体 Agent 早期都会走到同一个阶段:工具还不算太多,于是大家把“有哪些工具、什么时候能用、哪些参数不能传、哪些情况要停下来”一股脑写进系统提示词,觉得这样最省事。问题是,这种做法只在演示阶段勉强可用。一旦工具开始增多、权限开始分角色、会话开始跨轮次、执行开始带真实副作用,提示词就会从说明书变成临时配置中心,而模型也会被迫同时承担工具发现、权限判断、状态恢复和失败回退四种本不该全靠语言完成的工作。

OpenAI Agents SDK 关于运行 Agent 的文档、LangGraph 对持久化与状态恢复的设计,以及 Anthropic 对工具调用的说明,都指向同一个结论:工具注册表、权限边界和会话状态应该放在运行时系统里,由控制器、适配层和状态层管理,而不是塞进一段越来越长的提示文本里。对 TaskPilots 这样的独立运行 Agent 平台来说,这不仅影响模型表现,更直接决定单体 Agent 能否在接入真实工具后继续保持可控、可恢复和可审计。

为什么这个问题重要

提示词不该兼任工具目录和权限中心

把工具注册表写进提示词,表面上是在给模型“更多上下文”,本质上却是在用最脆弱的一层承载最关键的系统配置。模型当然可以读取工具说明并做出选择,但它并不适合成为工具清单的唯一事实来源。只要提示词版本落后一步、工具签名更新一次、权限边界变一轮,模型就可能在错误的工具定义上继续推理,进而产生错误调用、错误重试或错误恢复。

  • 工具是否存在,不应靠模型记住一段文本。
  • 工具是否可用,不应靠模型自己理解权限边界。
  • 工具调用是否成功,也不应靠模型猜测上一次执行发生了什么。

单体 Agent 上生产后,问题会先从状态层爆出来

很多团队以为这是“提示工程优化”问题,真正上线后才发现最先出事的通常不是文案质量,而是运行状态。一次工具超时后,模型不知道上一步是否已经写入成功;一次会话中断后,模型只能根据上下文猜测该不该重试;一次权限变更后,提示词里仍然保留旧工具列表,结果模型反复请求一个实际上已经不可见的接口。LangGraph 的持久化设计之所以重要,就是因为生产系统里的恢复不能依赖模型回忆,而要依赖结构化状态快照和明确的执行边界。

适用场景

哪些团队最容易被这个问题卡住

最容易遇到这个问题的,是那些还没上多 Agent,但单体 Agent 已经开始调用多个工具、维护会话状态,并承担真实业务动作的团队。典型场景包括客服助手调用 CRM 与发信接口、运营助手跨轮次处理工单、内部 Copilot 调用权限系统或知识库、以及任何需要在一次会话里经历检索、判断、执行、回写和失败恢复的流程。这些团队往往不会先被模型回答质量卡住,而会先被“工具到底能不能用、为什么这次重试出错、为什么状态断了”这类运行时问题拖住。

哪些阶段可以先不做太重

如果当前系统仍然只做单轮问答、没有真实写入、工具数量极少、失败后直接让用户重来一次也没有业务代价,那么当然还可以暂时把部分说明留在提示词里。但只要开始出现跨轮次状态、可重试执行、角色差异化权限,或者工具调用会产生真实副作用,就不应继续把提示词当作运行时配置库。换句话说,问题不在于工具多不多,而在于系统是否已经开始承担真实执行责任。

推荐系统结构

把工具注册表做成运行时事实源

更稳的结构,是让工具注册表独立于提示词存在,由运行时根据当前 Agent、当前会话和当前任务上下文动态下发。模型看到的不是一份手写在提示里的万能清单,而是当前步骤真正可用的工具集合、参数契约和错误语义。OpenAI Agents SDK 在运行 Agent 的设计里强调控制器和工具调用流程,就是因为工具应该由运行时注入,而不是让提示文本长期携带系统级配置。

这层注册表至少应管理四件事:工具标识、输入输出契约、可见性范围和版本。工具新增、下线或签名变更时,应该先改注册表,再由运行时自动反映到模型可见上下文里。这样模型始终面对的是一份最新、最小、与当前任务匹配的工具集,而不是一份混杂了历史遗留说明的长提示。

把权限边界和会话状态下沉到控制层

工具能不能被调用,不应只由模型“看起来应该调用”来决定,而应由控制层结合角色、会话、任务阶段和状态快照共同判断。某个工具即使存在,也可能只在特定阶段、特定用户、特定风险等级下可见。与其让模型在提示词里阅读一大段“如果是 A 就不要调 X,如果是 B 就可以调 Y”,不如让运行时直接只暴露当前允许的工具,并把状态快照一并交给控制器管理。

LangGraph 的持久化思路很适合放在这里理解:恢复时不该让模型重新阅读整段历史后自行推断,而应让状态层明确告诉它上一步在哪、哪些动作已经提交、哪些动作只是计划、哪些结果需要校验。只有这样,重试才会是恢复,而不是重新碰运气。

把 TaskPilots 的运行时能力变成适配层

映射到 TaskPilots,可以把独立运行 Agent 的工具链、状态模型和运行时控制面理解成三层。第一层是注册表,维护工具定义、版本和最小权限暴露;第二层是执行适配层,负责把当前任务、会话和风险上下文映射成可见工具和调用策略;第三层是状态层,记录快照、执行结果和恢复点。像 按风险分级决定 Agent 的自治边界审计友好的人工接管,需要留下哪些证据 讨论的审批与证据要求,也应在这三层里落地,而不是再回头塞进提示词补丁。

风险与失效点

最常见的故障是无状态重试和假恢复

如果系统没有独立状态层,最常见的失败就会出现在重试与恢复上。一次工具超时后,模型不知道请求是否已经抵达下游,只能根据聊天上下文猜测要不要再调一次;一次页面刷新或工作线程重启后,模型虽然还看得到历史文本,却不知道上次执行停在了“已计划”还是“已提交”。这种情况下最危险的不是调用失败,而是系统误以为自己在恢复,实际上是在重放一段不确定的历史。

  • 无状态重试容易造成重复写入、重复发信或重复下单。
  • 只看文本历史恢复,容易把计划步骤误认为已执行步骤。
  • 工具失败未校验,容易让模型在错误结果上继续推理。

把权限写进提示词,会让边界逐渐漂移

另一个高频问题,是权限边界在提示词里慢慢膨胀。最开始只是给模型一份工具清单,后来又补一段“管理员才能调用某某接口”,再后来加上“如果用户着急也可以走快捷路径”。每次修改看起来都合理,长期看却会把权限规则散落到多个 prompt 版本、多个环境配置和多个角色模板里。最后没有人能明确回答一个问题:当前这个 Agent 此刻为什么能看到这组工具。只要这个问题回答不清,权限边界就已经开始漂移。

验证指标

上线前先验证工具暴露与状态恢复是否解耦

上线前不要只做“模型会不会调用工具”的 happy path 测试,更要验证工具暴露和状态恢复是否已经真正从提示词里解耦。建议至少做三类验证:第一类是注册表变更测试,确认工具版本或权限变更后不需要手改 prompt 也能立即生效;第二类是中断恢复测试,确认在超时、重启或重放后系统能根据状态快照恢复,而不是让模型重新推断;第三类是越权样本测试,确认当前不允许的工具根本不会出现在模型可见集合中。

上线后持续看成功率、失败率与状态一致性

生产阶段至少要长期跟踪四类指标。第一是执行成功率,观察运行时改造后实际完成链路是否更稳定。第二是工具失败率,尤其要区分工具本身失败、参数校验失败和权限拒绝失败。第三是恢复时间,也就是中断后恢复到可继续执行状态所需的时间。第四是状态一致性,确认计划、执行结果、快照和最终业务状态之间没有持续偏差。除此之外,最好再看一次“提示词变更触发的运行回归数”,如果这项仍然很高,就说明工具配置还没有真正从 prompt 中迁出。

  • 成功率提升但状态一致性不稳,说明系统可能只是更快地错下去。
  • 权限拒绝失败很多,说明工具暴露规则仍然和任务阶段脱节。
  • 恢复时间过长,说明快照粒度或恢复点设计还不够清楚。

下一步 / FAQ

下一步先把提示词里的工具说明清单拉出来

最务实的第一步,不是立刻重写整套运行时,而是先把当前提示词里所有工具相关内容单独抽出来,按“工具定义、权限规则、状态假设、失败处理”四类做一次拆分。只要这一步完成,团队通常就会立刻看到哪些内容其实应该进入注册表,哪些应该下沉到状态层,哪些应该交给执行适配层处理。先把职责拆开,再做运行时改造,推进会顺得多。

FAQ:工具少的时候也要做注册表吗

不一定要一开始就做得很重,但至少要有一个独立于 prompt 的事实源。哪怕只有两三个工具,只要它们会变、会分权限、会跨会话执行,就值得先从简单注册表做起。

FAQ:把工具信息放到运行时,会不会让模型更笨

通常不会,反而更稳。模型不是失去工具信息,而是得到一份更小、更准、与当前任务更匹配的工具集合。相比阅读一大段历史配置,模型更容易在清晰约束下做出正确选择。

FAQ:这是不是只有多 Agent 才需要考虑

不是。单体 Agent 只要开始接多个工具、跨会话执行并承担真实副作用,就已经需要把工具注册、权限边界和状态恢复当作运行时问题来处理,而不是继续依赖提示词硬扛。