首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >从工具调用到工具生成:能力缺口驱动的 LLM Agent 自主工具构建机制与工程实践

从工具调用到工具生成:能力缺口驱动的 LLM Agent 自主工具构建机制与工程实践

原创
作者头像
OneCode
修改于 2026-11-05 11:29:13
修改于 2026-11-05 11:29:13
1370
举报
文章被收录于专栏:ooderAgentooderAgent

OODER 技术博客 · Agent Engineering

从工具调用到工具生成:能力缺口驱动的 LLM Agent 自主工具构建机制与工程实践

——OODER Agent / SuperAgent 架构升级的技术原理分析

2026-11-05 · 深度技术原理分析 · 约 9000 字

摘要:当 Agent 从“会调用预置工具”走向“能为自己制造工具”,系统设计的重心就从 API 编排转移到能力治理。本文以 OODER Agent / SuperAgent 的架构升级为背景,讨论 Agent 自主造工具的真实需求、理论脉络、关键难点与工程实现,并给出一条可验证、可审批、可审计、可回滚的声明式工具构建路径。文中的截图均来自真实工具面或真实会话,而非示意图。 关键词:LLM Agent;工具制造;能力缺口;声明式工具;自进化;SuperAgent;A2A

一、背景:为什么 Agent 必须学会“造工具”

1.1 从固定工具面到 SuperAgent Runtime

过去一年,Agent 工程的主线从“单轮问答 + 固定函数列表”逐步转向“多轮任务执行 + 多执行体协作”。OODER 的这次升级,核心变化可以概括为三层:

  1. 执行层:从单机 Chat Scene 走向 SuperAgent Runtime。入口请求先经过 Router / Thread 绑定,再按执行体能力做 A2A 派发;执行体返回回执后,系统统一收敛终态、落库并回传前端。
  2. 工具层:从场景硬编码工具列表,走向 Tool Catalog + tools_load 按需装载。工具面不再由某个场景一次性写死,而是由能力注册表、技能中心和动态注册器共同供给。
  3. 环境层:从“只有对话”走向“对话 + 沙箱 + 技能中心 + 多节点”。Agent 可以在沙箱里读源码、编译、运行测试,也可以把能力声明上行到技能中心,供其它节点消费。

这套架构解决的是“已有能力如何被调度”的问题,但没有自动解决另一个更底层的问题:当能力根本不存在时,Agent 应该怎么办?

1.2 固定工具面的三重瓶颈

OODER 的工具面并不小。下图来自真实的“工具目录”页面:272 个工具、48 个分类。但同一个页面上,写工具(可执行外部副作用的工具)数量为 0,危险级别工具为 3。

图 1:真实工具目录——272 个工具、48 个分类、0 个写工具
图 1:真实工具目录——272 个工具、48 个分类、0 个写工具

图 1:真实工具目录截图(OODER 管理控制台)。工具数量并不等于能力覆盖:大量工具集中在读、检索、编排和设计域,真正能触达业务系统的写工具仍然稀缺。

这张图揭示了三个结构性瓶颈:

  • 长尾接口无法穷举:企业内部的 ERP、OA、财务、钉钉、邮件、报表、天气、地图……每个系统都有自己的 /api/。平台不可能为每个租户、每个版本、每个边缘接口预置一个 Java 工具。
  • 业务语义变化快于发版节奏:今天要“把资金驾驶舱渲染成图片并推送钉钉”,明天要“查某城市天气并写入客户拜访记录”。如果每次都要改代码、编译、发版,Agent 的可用性会被工程流程吞掉。
  • 模型会“假装完成”:当工具面没有对应能力时,模型常见的失败模式不是报错,而是用自然语言“解释自己做不到”,或者更糟——编造一个不存在的工具名。用户拿到的是“已处理”的幻觉,平台拿不到结构化需求。

1.3 真实需求:能力缺口不是异常,而是常态

在一次真实会话里,用户要求“把集团资金管理驾驶舱生成图片,用钉钉发给张海艳”。当时工具面既没有图片导出,也没有媒体上传,模型只能回答“我没有这个能力”。这个回答在语义上没有错,但在产品上是失败的:

  • 用户的需求是真实的;
  • 系统的能力缺口是真实的;
  • 平台却没有拿到“缺什么、为什么缺、期望参数是什么”的结构化信号。

这类事件反复出现后,团队把它定义为能力缺口(capability gap):Agent 在完成任务时,发现“当前工具面无法覆盖目标动作”的状态。能力缺口不是系统异常,而是 Agent 与环境之间的正常摩擦;关键在于,系统能否把摩擦转化为可运营的需求,并进一步转化为可用的工具。

这就是“自主造工具”的迫切性:它不是让模型随意写代码,而是让 Agent 在受控边界内,把“缺失的动作”表达成一份可校验、可审批、可执行的工具声明。

二、理论脉络:从工具调用到工具制造

“Agent 造工具”并不是一个新奇概念。过去三年,研究社区已经从不同角度逼近这个问题。

研究方向

代表工作

核心思想

对本实践的启示

自监督工具调用

Toolformer

让模型自己学习“何时调用、调用什么、传什么参数”

工具调用决策应由模型自主完成,而不是靠外部硬编码

大规模 API 调用

ToolLLM、Gorilla

用检索增强和指令微调,让模型掌握成千上万个 API

工具目录、检索和 schema 是基础设施,不是附属品

工具制造者/使用者分离

LATM(LLMs As Tool Makers)

一个模型造工具,另一个模型用工具

生成与使用应解耦,生成侧需要独立的质量门禁

抽象工具创建

CREATOR

把“抽象工具创建”和“具体决策执行”分开

工具声明应描述契约,执行时才绑定具体参数

开放式技能获取

Voyager

自动课程 + 技能库 + 自验证,持续积累可复用技能

工具需要可复用、可验证、可淘汰,而不是一次性脚本

从代码仓库生成工具

ToolMaker

从论文/代码仓库自动生成 LLM 可用工具,并闭环自纠正

“生成 → 自测 → 纠错”必须成为同一条链路

程序性记忆

Agent Workflow Memory

从历史轨迹归纳可复用工作流

一次成功经验应沉淀为可检索的程序性资产

自进化 Agent

Self-Evolving Agents 系列综述

从模型、记忆、工具、架构四个维度持续演化

工具是自进化的核心维度,但必须与治理同步演化

这些工作共同指向一个结论:工具不再只是“外部函数的列表”,而是 Agent 可以学习、创建、验证和积累的知识对象。

但学术工作与工程落地之间仍有一段距离。LATM/CREATOR 关注“能不能造出来”,Voyager 关注“能不能在开放环境里持续积累”,ToolMaker 关注“能不能从代码仓库自动生成”。而企业级 Agent 还要回答四个工程问题:

  1. 造出来的工具,风险谁说了算?
  2. 造出来的工具,谁批准它进入生产工具面?
  3. 造出来的工具,如何与多租户、多节点、多场景共存?
  4. 造出来的工具,如何证明它真的被执行过、并且可以回滚?

本文的实践定位是:不追求“模型自由写代码”,而是把工具制造收敛为一份可治理的声明(declaration)。模型负责“表达意图与契约”,平台负责“校验、授权、注册、执行与审计”。这与 CREATOR 的“抽象工具创建 / 具体执行分离”一脉相承,但把“审批与租户”纳入了工具对象本身。

三、问题定义与总体框架

3.1 能力缺口的定义

设 Agent 当前工具面为 \(T\),用户任务需要的动作集合为 \(A\)。若存在 \(a \in A\),使得 \(T\) 中没有任何工具能在当前会话的权限、租户和网络边界内完成 \(a\),则称系统存在能力缺口:

\[ Gap = \{ a \in A \mid \nexists t \in T,\ allowed(t, a, tenant, risk) \} \]

能力缺口有三个特征:

  • 任务相关:同一个工具面,对不同任务可能足够,也可能不足;
  • 权限相关:工具存在但当前用户/租户无权调用,也算缺口;
  • 可结构化:缺口至少应包含“需要的动作、缺失的能力类型、期望参数、替代方案、影响”。

3.2 五段闭环

OODER 把“造工具”拆成五段,而不是一次“让模型写个函数”:

  1. 发现:tool_gap_report 把缺口结构化上报;
  2. 生成:tool_register(dryRun=true) 生成声明并校验;
  3. 授权:服务端推导风险,WRITE/DANGER 进入 PENDING,管理员审批;
  4. 执行:热注册进 ToolEngine,tools_load 后调用;
  5. 审计:记录 actor、参数指纹、响应状态、定义指纹,并回写缺口状态。

图 2:五段闭环。真正困难的不在“生成”,而在生成之后的校验、授权、执行和审计。

3.3 三层架构

把这条链路放进 OODER SuperAgent 的整体架构,可以看到三个层次:

  • 能力层:Tool Catalog、能力注册表、技能中心、tools_load;
  • 制造层:缺口上报、声明生成、dryRun 校验、自测、热注册;
  • 治理层:风险推导、审批、owner、租户命名空间、URL 白名单、密钥、配额、审计。

图 3:制造层不是独立服务,而是嵌在 SuperAgent 的工具面与执行面之间;治理层横向贯穿。

四、关键难点与设计取舍

4.1 难点一:风险不可自证

最直接的做法,是让模型在声明里自己填 risk: READ | WRITE | DANGER。但我们在审计中确认,这种做法不可接受:

  • 模型可以把 DELETE 声明成 READ;
  • 模型可以把 POST 声明成 READ;
  • 模型可以把审批中的工具用 tool_test “试跑”,绕过审批;
  • 模型可以把已有工具重定义成 READ,从而接管别人的工具。

因此,风险必须由服务端推导,声明只能升高、不能降低:

HTTP 方法/目标

服务端推导风险

GET / HEAD

READ

POST / PUT / PATCH

WRITE

DELETE

DANGER

命中 /api/studio、/api/chat、/api/org、/actuator 等敏感前缀

至少 DANGER

这条规则把“模型自报风险”从安全边界降级为“提示信息”。审批、能力授权、执行确认都以服务端推导结果为准。

4.2 难点二:自治与审批的平衡

如果每个工具都要人工审批,Agent 就失去了“自主”的意义;如果完全不审批,工具面就会变成模型可以随意扩张的攻击面。OODER 的折中是:

  • READ 工具:登录用户可直接生效,但必须经过 dryRun + confirm;
  • WRITE / DANGER 工具:落盘即 PENDING,不注册、不可调用;管理员审批后才 ACTIVE;
  • 同名修订:即使新版本是 READ,也必须重新审批,防止“降级接管”;
  • 可选四眼原则:开启后创建人不能审批自己的声明。

这套规则的关键不是“审批”,而是审批对象是一份带内容指纹的声明,而不是一句自然语言描述。

4.3 难点三:运行时注册与命名空间

动态工具要进入 tools_load,就必须进入 ToolEngine 的注册表。但注册表是全局的:

  • 两个租户都叫 weather_query,会不会互相覆盖?
  • 一个租户的工具,会不会出现在另一个租户的 tools_index?
  • 已有全局工具叫 demo_tool,租户工具还能不能叫 demo_tool?

OODER 的解法是把“工具身份”拆成三个名字:

名字

用途

示例

基 id

业务语义、声明文件、人读

demo_tool

qualified id

审批、删除、后台运营

tenant-a:demo_tool

runtimeName

ToolEngine 注册键、tools_load、LLM 调用

t-tenant-a-demo_tool

基 id 只允许 [a-z0-9_],不含 -;运行时名以 t- 开头。这样租户工具的运行时名不可能与全局/存量工具重名。文件键也使用运行时名,因此两个租户的同名声明落在不同文件。执行时再校验 def.tenantId 与当前会话租户一致。

图 4:qualified id、runtimeName、fileKey 三层映射,保证“同名不同租户”可共存且可审计。

4.4 难点四:安全边界

声明式工具本质上是“让模型指定一个 HTTP 请求”。如果不加约束,它就是一个 SSRF 入口。OODER 在注册期和执行期做双重校验:

  • URL 规范化:拒绝 ..、//、反斜杠、%2e、%2f、%5c 等路径穿越/编码变体;
  • 主机限制:默认仅回环地址;放开外部时仍拒绝云元数据地址;
  • 端口白名单:默认 80,443,5332,8000-8999,9000-9999;
  • 敏感前缀黑名单:/api/studio/、/api/chat/、/api/org/、/api/v1/auth/、/actuator;
  • 密钥命名空间:只允许 ${secret:ooder.tool.secret.*},缺失即失败,不再静默替换为空串;
  • 响应上限:流式读取,默认 64KB,JSON 也按字节截断;
  • 配额/限流:单用户声明数量、参数数量、注册频率、审计/缺口文件大小都有上限。

这些约束的目标不是“让工具更难用”,而是让“模型犯错”变成“可诊断的失败”,而不是“不可见的越权”。

4.5 难点五:可观测与可回滚

工具造出来之后,最危险的场景不是“调用失败”,而是“调用成功但没人知道它做了什么”。OODER 的审计记录包含:

  • actor:谁创建/审批/调用;
  • conversationId:哪个会话;
  • paramsHash:参数指纹,不落明文;
  • contentHash:声明定义指纹,审批后若文件被改动,执行直接拒绝;
  • httpStatus、elapsedMs、truncated、risk、tenantId。

当审计文件或缺口文件超过阈值时,系统自动归档,避免无限增长。工具修订时先下线旧版本,防止“文件里是新 risk、内存里是旧实现”的授权错配。

4.6 难点六:场景覆盖

OODER 有多个场景(通用对话、意图分发、BPM、RAD、页面调试、技能中心等),其中不少场景覆写了 getAvailableTools 和 buildSystemPrompt。如果只在基类里补平台工具包,覆写场景就会拿不到 tool_register / tool_gap_report。

工程上的解法不是逐个场景加代码,而是:

  • 所有内核调用点统一走 effectiveTools(context);
  • appendPlatformToolPacks 在最后统一补平台工具包;
  • appendPlatformProtocols 在提示词末尾按标记幂等追加协议;
  • 这样既不破坏场景自定义工具面,也保证平台级能力“全场景兜底”。

五、实战:OODER 的实现路径

5.1 总体链路

一次“造工具”的真实链路如下:

代码语言:javascript
复制
用户提出目标
  → 模型检索工具面(tools_index / tools_find / tools_load)
  → 发现缺口:tool_gap_report(intent, neededAction, missing, alternatives)
  → 平台落库 + SSE 缺口卡(gapId)
  → 模型生成声明:tool_register(definition, dryRun=true)
  → 校验 URL / schema / 密钥引用 / 风险
  → tool_register(definition, dryRun=false, confirm=true)
  → 服务端推导 risk:READ 直接 ACTIVE;WRITE/DANGER → PENDING
  → 管理员审批:tool_register_approve(qualifiedId)
  → ToolEngine 热注册
  → tools_load(names=[runtimeName])
  → 真实 HTTP 调用 → 审计 → 回写缺口 resolved

在真实会话里,工具调用的密度远比“单次函数调用”高。下图来自一次资金流水分析任务:同一轮里连续出现 20 多次工具调用,涵盖工具装载、流水查询、实例列表、图表渲染等,单次耗时从 1ms 到 119ms。

图 5:真实会话中的工具链——20+ 次工具调用与耗时
图 5:真实会话中的工具链——20+ 次工具调用与耗时

图 5:真实工具链截图。工具面不足时,模型会在“检索—重试—再检索”中消耗轮次;这正是能力缺口需要被结构化的原因。

5.2 能力缺口上报

tool_gap_report 不是“报错日志”,而是一份需求契约:

代码语言:javascript
复制
{
  "intent": "把资金驾驶舱生成图片并用钉钉发给张海艳",
  "neededAction": "渲染 PNG + 上传媒体 + 发送工作通知",
  "missing": [
    {"kind": "media", "name": "dashboard_image_render", "reason": "无图片导出工具"},
    {"kind": "tool", "name": "dingtalk_send_image", "reason": "无媒体上传能力"}
  ],
  "alternatives": [
    {"tool": "render_chart", "label": "先渲染图表", "note": "不能直接生成 PNG"}
  ],
  "impact": "无法按时发送日报",
  "evidence": "工具返回 SKILL_NOT_WIRED"
}

平台把这个对象落库为 gaps.jsonl,并通过 SSE 推送 capability_gap 事件,前端渲染缺口卡。缺口卡的价值在于:用户能立刻看到“缺什么”,研发能按 gapId 追到“用户原话 + 需要的动作 + 期望参数”。

图 6:真实会话中的工具卡与任务步骤
图 6:真实会话中的工具卡与任务步骤

图 6:真实会话截图(浅色界面)。工具卡展示工具名、执行状态与任务步骤;当工具不存在时,同一位置会变为“能力缺口卡”。

5.3 声明式工具合成

一份最小的工具声明如下:

代码语言:javascript
复制
{
  "id": "weather_query",
  "displayName": "天气查询",
  "description": "查询指定城市当前天气",
  "method": "GET",
  "url": "http://127.0.0.1:9004/api/weather/current",
  "query": {"city": "{city}"},
  "risk": "READ",
  "params": [
    {"name": "city", "type": "string", "required": true, "description": "城市名"}
  ]
}

模型第一次调用 tool_register(definition, dryRun=true),平台只做校验和预览,不落盘;第二次带 dryRun=false + confirm=true 才真正写入。这个过程强制模型“先想清楚契约,再申请落地”。

5.4 风险推导与审批

服务端拿到声明后,不直接信任 risk,而是计算 effectiveRisk:

代码语言:javascript
复制
GET / HEAD                         → READ
POST / PUT / PATCH                 → WRITE
DELETE                             → DANGER
命中敏感目标(/api/studio 等)      → 至少 DANGER
最终 risk = max(声明 risk, 推导 risk)

WRITE/DANGER 声明落盘为 PENDING,不注册进工具面。管理员在审批台看到的是:

  • qualifiedId(tenant:id)
  • runtimeName(t-<ns>-<id>)
  • method / URL / params / risk / owner / 来源缺口
  • 可选的“四眼原则”提示

审批通过时,平台写入 approvedAt、approvedBy、contentHash,然后热注册。执行时重新计算 contentHash,如果不一致,直接拒绝执行——这防止“审批后声明文件被替换”。

5.5 热注册与运行时命名空间

注册器不覆盖核心工具,也不允许同名声明被非 owner 修订。对于租户工具:

  • 文件键:t-<tenantNs>-<id>.json
  • 注册键:t-<tenantNs>-<id>
  • 对外 id:<tenant>:<id>

查询工具面时,ToolCatalogCapability 会把动态工具并入候选集,但按当前会话租户过滤;执行时,DeclarativeToolUnit 再校验一次租户。这样“索引不可见”和“直接按名字调用”两条路径都被堵住。

5.6 安全加固

除了 URL 与密钥,OODER 还做了三件事:

  1. 响应大小限制:用 BodyHandlers.ofInputStream() 流式读取,超过 64KB 立即截断;JSON 响应不会因为“解析成功”就整包进入 LLM 上下文。
  2. 配额与限流:单用户最多 20 个声明、注册 20 次/分钟、参数/header/query/URL/body 都有上限。
  3. 审计与归档:audit.jsonl 超 10MB、gaps.jsonl 超 20MB 自动归档;审计字段包含 actor、paramsHash、contentHash。

5.7 真实闭环:weather_query

在 8014 的实测中,一次完整闭环如下:

  1. 真实会话上报 weather_query 缺口 → 看板“待补齐” +1;
  2. 带 gapId 创建草稿 → PENDING,不在工具索引;
  3. 管理员审批 → stage=applied,工具索引可见;
  4. tools_load 调用 → CALL httpStatus=200 / 12ms;
  5. 看板该缺口 resolved=True,resolvedByTool=weather_query。
图 7:真实工具卡的参数详情(结果脱敏)
图 7:真实工具卡的参数详情(结果脱敏)

图 7:真实工具卡详情截图(结果数据已脱敏)。工具名、参数结构与执行状态可追溯;这正是“造工具”之后必须保留的证据链。

这个闭环说明:自主造工具不是“模型写一段代码就完事”,而是“缺口—声明—审批—执行—审计—闭环”的系统工程。

5.8 技能中心:从本地工具到可分发能力

声明式工具如果只落在本地 data/tool-decls/,它仍然是一个“单机工具”。OODER 的第二步,是把工具声明接入技能中心(Skill Center),让它成为可发现、可安装、可授权、可审核的跨节点能力资产。

技能中心的完整管理流程可以概括为六段:

  1. 能力声明入统一真源:SkillCarrierRegistrar 遍历能力载体,把 @CapabilityDeclaration 与 CapabilityUnitPort 注册到 SkillRegistrationTable;
  2. 节点上行:节点把名册(roster)、场景(scene)、摘要(summary)、技能(skills)上行到中心;SDK 负责登录、激活、心跳与断线重连;
  3. 目录聚合:中心按能力域/租户/节点聚合目录,形成可检索的“技能市场”;
  4. 租户安装与授权:目录只代表“可见”,安装与授权才代表“可用”;未安装/未授权的技能不会进入工作区;
  5. 审核台:候选技能进入 CANDIDATE / IN_REVIEW,审核通过后变为 LISTED,驳回则回到 DRAFT;
  6. 运行与撤销:已安装技能在租户工作区运行;撤销安装/授权后,能力从工具面退出。

下面两张截图来自真实的技能中心页面(已裁剪并脱敏,保留流程与状态,去掉租户、账号和统计数字):

图 8:技能市场——目录、安装状态与技能卡
图 8:技能市场——目录、安装状态与技能卡

图 8:技能市场截图。每张卡展示技能 id、版本、能力标签、菜单数与安装状态;“未安装”是租户级状态,不是技能不存在。

图 9:技能审核台——CANDIDATE、契约校验与通过/驳回
图 9:技能审核台——CANDIDATE、契约校验与通过/驳回

图 9:技能审核台截图。候选技能在这里完成契约校验与人工审核;通过后状态变为 LISTED,租户才可安装。

这两个页面回答了一个关键问题:自主造工具不是“造完就能用”,而是“造完要能被分发、被安装、被授权、被审核”。 技能中心承担的就是“能力契约的分发与审核平面”,而不是简单的文件仓库。

技能中心与自主造工具的关系可以概括为:

代码语言:javascript
复制
tool_register(本地声明)
  → SkillRegistrationTable(统一真源)
  → SC 上行(roster / scene / summary / skills)
  → 技能市场(目录可见)
  → 租户安装 + 授权(可用)
  → 运行 / 撤销(生命周期)

5.9 工具生命周期:从 PENDING 到 RETIRED

工具不是“注册成功就结束”。它需要一条完整的生命周期,才能在长期运行中保持可治理。

图 10:工具从 DRAFT/PENDING/ACTIVE/DEPRECATED 到 RETIRED 的状态流转;修订会回到 PENDING 重新审批。

状态

含义

进入条件

退出条件

DRAFT

可选草稿

看板“补工具”生成

提交审核 / 删除

PENDING

待批,不注册、不可调用

WRITE/DANGER 声明、同名修订

管理员通过 / 驳回

ACTIVE

已审批、已热注册

管理员通过、READ 直生效

停用 / 修订 / 删除

REJECTED

已驳回,不注册

管理员驳回

修改后重新提交

DEPRECATED

停用,不接受新调用

运维主动停用

删除 / 归档

RETIRED

退役,归档留痕

删除 / 过期 / 上游失效

只读审计

生命周期的四个关键设计:

  1. 同名修订必须重新审批:即使新版本声明为 READ,也不能绕过审批,防止“降级接管”;
  2. 修订时旧版先下线:避免“文件里是新 risk、内存里是旧实现”的授权错配;
  3. 审批绑定内容指纹:contentHash 在审批时写入,执行前重算,不一致直接拒绝;
  4. 退役不等于删除审计:工具退役后,audit.jsonl 与缺口记录仍然保留,便于追责与复盘。

5.10 安全模型:把攻击面拆到每一段

“让模型造工具”本质上是在给模型增加一个写请求的能力。因此,安全设计不能只在执行阶段做,而要贯穿生命周期。

攻击面

典型风险

控制措施

工具投毒

模型在 description 中写入提示注入,影响其他用户

owner/租户隔离、审批、描述限长、工具面按租户过滤

风险降级

把 DELETE/POST 声明成 READ

服务端按 method + 目标推导 effectiveRisk,声明只能升高

审批绕过

用 tool_test 试跑 PENDING 工具

仅 ACTIVE 可自测;非 READ 自测需管理员;审批凭证 + contentHash

SSRF / 路径穿越

/api/../admin、任意端口、云元数据地址

路径规范化、编码变体拒绝、端口白名单、敏感前缀黑名单、元数据地址拒绝

密钥外带

${secret:任意系统属性} 被写入请求头

只允许 ooder.tool.secret.*,缺失 fail-closed,审计不落密钥值

租户逃逸

直接按运行时名调用其它租户工具

runtimeName = t-<tenant>-<id>;执行时校验 def.tenantId;目录按租户过滤

资源耗尽

大响应、无限声明、注册洪水

响应 64KB 流式截断、单用户声明上限、注册限流、文件归档

核心工具被顶替

声明与核心工具同名

运行时名冲突检查;永不覆盖核心工具;只注销本注册器注册的工具

审计缺失

不知道谁创建/审批/调用

actor、conversationId、paramsHash、contentHash、状态与耗时全部落盘

把这张表压缩成一句话:

自主造工具的安全边界,不是“模型会不会写坏代码”,而是“平台能不能在每个阶段说不”。

具体来说,平台在五个位置保留“说不”的能力:

  • 生成阶段:拒绝非法 URL、超长声明、密钥越界;
  • 审批阶段:拒绝非管理员、拒绝四眼冲突、拒绝降级修订;
  • 注册阶段:拒绝核心工具同名、拒绝租户冲突;
  • 执行阶段:拒绝租户不匹配、拒绝定义指纹不一致、拒绝超限响应;
  • 退役阶段:拒绝无确认删除、保留审计与回滚证据。

这也是 OODER 与“让模型自由写脚本”的根本区别:不是不给模型能力,而是给能力加上可验证、可审批、可回滚的边界。

六、工程验证与效果

本轮改造的验证口径不是“代码看起来对”,而是“编译 + 单测 + 关键路径可复现”:

验证项

结果

mvn -o -DskipTests compile

BUILD SUCCESS

mvn -o -Ptests test

318 passed, 0 failed, 0 skipped

声明式工具安全用例

风险推导、URL 穿越、审批指纹、密钥命名空间、租户命名空间均通过

沙箱工具风险分级

sandbox_agent_load/run/execute 等提升为 DANGER

缺口看板

仅管理员可访问

历史测试编译错误

已修复(TenantFilter 构造注入、A2A 过期用例替换)

上述结果覆盖编译、全量单测与安全用例回归;关键路径已在工程环境完成实现与回归验证,后续按灰度节奏推进生产验证。

七、讨论:边界与开放问题

7.1 “造工具”不等于“写代码”

OODER 的声明式工具只覆盖 HTTP 工具。它不解决“需要写一段本地算法”的场景。后者应该走沙箱代码生成与编译链路,且需要更严格的 DANGER 审批。两条链路的边界要清晰:HTTP 契约用声明,复杂逻辑用沙箱代码,二者都走治理面。

7.2 语义正确性仍需要人

tool_test 能证明“HTTP 通”,不能证明“业务语义对”。一个返回 200 但字段为空的接口,工具测试也会通过。因此:

  • 自测结果必须展示 httpStatus/data/elapsedMs;
  • 高风险工具需要管理员核对 URL、方法、参数;
  • 真实业务闭环需要“用户验收”而不是“模型自称完成”。

7.3 工具会漂移

上游 API 会改字段、改鉴权、改限流。声明式工具需要:

  • 定期回放样例;
  • 失败率监控;
  • 版本与回滚;
  • 上游变更时的失效标记。

7.4 评测仍是空白

目前没有公开 benchmark 能覆盖“企业内网 API + 多租户 + 审批 + 沙箱”的组合。OODER 的做法是用真实缺口、真实会话、真实审批记录做“运营式评测”。这比合成数据集更接近生产,但样本量小、可重复性弱,需要长期积累。

7.5 自治的边界

自主造工具的目标不是“让 Agent 无限扩张工具面”,而是“让 Agent 在边界内补齐能力”。因此,以下原则应长期保留:

  • 生成与审批分离;
  • 风险由服务端推导;
  • 租户命名空间隔离;
  • 审计可追溯;
  • 任何工具都可以被停用、回滚、删除。

八、结论

OODER SuperAgent 的这次升级,表面上解决的是“多执行体调度”和“工具按需装载”,本质上解决的是“Agent 如何面对自身能力边界”的问题。

从 Toolformer 到 LATM、CREATOR、Voyager、ToolMaker,再到 Self-Evolving Agents 综述,研究社区已经证明:工具可以成为 Agent 学习、创造和积累的对象。但企业级落地还需要另一套东西——声明化、风险推导、审批、租户命名空间、审计与配额。

一句话总结:

会调用工具的 Agent 是“执行者”;能为自己制造工具、并且知道何时不该制造工具的 Agent,才是“可运营的智能体”。

OODER 的实践把“造工具”从一次性的代码生成,变成了一个可治理的运行时能力。这条路径还远未完成,但它至少让“能力缺口”从一句“我没有这个能力”,变成了一个可以被审批、被执行、被审计、被关闭的工程对象。

参考文献

  1. Schick et al. Toolformer: Language Models Can Teach Themselves to Use Tools. arXiv:2302.04761.
  2. Qin et al. ToolLLM: Facilitating Large Language Models to Master 16000+ Real-world APIs. arXiv:2307.16789.
  3. Patil et al. Gorilla: Large Language Model Connected with Massive APIs. arXiv:2305.15334.
  4. Cai et al. Large Language Models as Tool Makers (LATM). arXiv:2305.17126.
  5. Qian et al. CREATOR: Tool Creation for Disentangling Abstract and Concrete Reasoning of Large Language Models. arXiv:2305.14318.
  6. Wang et al. Voyager: An Open-Ended Embodied Agent with Large Language Models. arXiv:2305.16291.
  7. LLM Agents Making Agent Tools (ToolMaker). arXiv:2502.11705.
  8. Wang et al. Agent Workflow Memory. arXiv:2409.07429.
  9. A Survey of Self-Evolving Agents: On Path to Artificial Super Intelligence. arXiv:2507.21046.
  10. A Comprehensive Survey of Self-Evolving AI Agents. arXiv:2508.07407.
  11. Tool Learning with Large Language Models: A Survey. arXiv:2405.17935.

本文基于 OODER Agent / SuperAgent 的工程实践与 2026-11-04/05 的审计记录整理。文中截图来自真实工具目录、真实会话与真实工具卡;涉及内网地址、账号与业务数据均已脱敏或未展示。

本文基于 OODER Agent / SuperAgent 工程实践与 2026-11-04/05 审计记录整理。截图来自真实工具目录、真实会话与真实工具卡;内网地址、账号与业务数据均已脱敏或未展示。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 从工具调用到工具生成:能力缺口驱动的 LLM Agent 自主工具构建机制与工程实践
    • 一、背景:为什么 Agent 必须学会“造工具”
      • 1.1 从固定工具面到 SuperAgent Runtime
      • 1.2 固定工具面的三重瓶颈
      • 1.3 真实需求:能力缺口不是异常,而是常态
    • 二、理论脉络:从工具调用到工具制造
    • 三、问题定义与总体框架
      • 3.1 能力缺口的定义
      • 3.2 五段闭环
      • 3.3 三层架构
    • 四、关键难点与设计取舍
      • 4.1 难点一:风险不可自证
      • 4.2 难点二:自治与审批的平衡
      • 4.3 难点三:运行时注册与命名空间
      • 4.4 难点四:安全边界
      • 4.5 难点五:可观测与可回滚
      • 4.6 难点六:场景覆盖
    • 五、实战:OODER 的实现路径
      • 5.1 总体链路
      • 5.2 能力缺口上报
      • 5.3 声明式工具合成
      • 5.4 风险推导与审批
      • 5.5 热注册与运行时命名空间
      • 5.6 安全加固
      • 5.7 真实闭环:weather_query
      • 5.8 技能中心:从本地工具到可分发能力
      • 5.9 工具生命周期:从 PENDING 到 RETIRED
      • 5.10 安全模型:把攻击面拆到每一段
    • 六、工程验证与效果
    • 七、讨论:边界与开放问题
      • 7.1 “造工具”不等于“写代码”
      • 7.2 语义正确性仍需要人
      • 7.3 工具会漂移
      • 7.4 评测仍是空白
      • 7.5 自治的边界
    • 八、结论
    • 参考文献
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档