工具系统:注册、可见性、截断与权限收口
模型能调用的工具,不是“仓库里有实现就等于可见”。Agent Forge 把每个工具收成统一契约:入参校验、执行、输出截断;再经注册表过滤、插件改写定义、会话权限收口后,才进入本轮 streamText 的工具表。过长的工具输出用截断保护上下文,与会话级 compaction 互补。
每个工具经定义/包装后具备:
- 入参校验(schema / zod 解析)
- 原执行逻辑
- 输出截断(除非元数据已标明截断过)
执行上下文携带会话与消息标识、当前角色、中止信号、权限询问入口,以及回写 tool Part 元数据的通道。
flowchart TD B[内置工具显式列表] --> All[候选全集] C[配置目录 tool 脚本] --> All P[插件注册的 tool] --> All All --> Reg[registry 过滤]内置工具是显式列表,不是扫描整个工具源码树自动注册。自定义来自项目配置目录下的工具脚本,以及插件注入。候选可以多,真正送给模型的是过滤后的子集。
flowchart LR All[候选] --> L1[按模型 / 提供方 / 开关] L1 --> L2[plugin tool.definition] L2 --> L3[resolveTools + permission] L3 --> LLM[送给模型]第一层按模型与提供方能力裁剪(例如某些搜索工具仅在特定配置下启用;部分模型走 patch 编辑,其它走 edit/write)。第二层允许插件改写描述与参数 schema。第三层按角色、会话与单次输入的工具覆盖,结合权限规则(allow / deny / ask)再滤。
第三层的收口规则:
- 权限名与工具名对应;写入、补丁等编辑类工具在配置里统一映射到同一条
edit权限。 - 仅当规则 pattern 为
*且动作是deny时,整个工具从本轮工具表移除;带具体 pattern 的 deny 只在该次调用命中时拒绝。 ask不隐藏工具,执行前发出询问,决定后再继续。- 单次请求传入的工具布尔开关折算成 allow / deny 后并入这一层。
mutating 路径还可进入人工门禁与审计;未命中规则时按上图执行。权限配置合并见配置与权限覆盖。
工具返回字符串过长时:按统一上限截断正文,标记已截断,并把完整输出落到文件路径供事后查看。目的是防止单次 tool 结果撑爆上下文窗口。截断是即时闸门;compaction 是跨轮折叠。二者一起用。
阈值与角色差异
Section titled “阈值与角色差异”阈值由统一策略给出,角色影响的是截断之后给模型什么续读指引:
| 环节 | 规则 |
|---|---|
| 统一上限 | 行数与字节双重判断,默认 2000 行 / 50 KB;超限保留一段预览,并标注截掉的量与单位 |
| 完整输出 | 写入截断缓存目录,结果里附路径;除非角色显式禁止,该目录对该角色可读 |
| 续读指引 | 角色仍能派子任务时,提示交给 explore 子代理检索完整文件,避免主上下文被灌满;角色被禁用子任务时,提示改用检索或带偏移量分段读取 |
| 工具体自有上限 | 读取类工具单行超过 2000 字符会截断该行;目录列举与检索类工具默认只回前 100 条 |
工具若已自行处理过截断并在结果元数据里标记,统一包装不会重复截断。
bash跑出几万行日志:回填正文只保留前 2000 行(或 50 KB 以内)的预览,完整文件落到截断目录。主角色可用子任务时,指引是让 explore 子代理去检索该文件;被禁用子任务时,指引改成用检索工具或分段读取。read打开一行压缩过的 JSON:该行按 2000 字符截断,模型需要具体字段时改用检索定位。- 检索命中过多:只回前 100 条并提示已截断,模型需要更全结果时应收窄路径或模式,而不是加大条数上限。
| 现象 | 优先核对 |
|---|---|
| 模型看不到某工具 | 注册表规则、插件改写、resolveTools、permission deny |
| 参数校验失败 | 工具 schema 与模型生成参数是否一致 |
| 上下文仍暴涨 | 截断是否生效;是否还需 compaction |
| 工具执行被询问卡住 | 权限 ask 流是否经 SSE 送达并完成决定 |
相关阅读: