agent skills工具建立与注册流程

先定义一个工具函数,比如my_calculator_tool.py
在这个文件里面定义一个函数,注册这个工具
代码如下

def create_calculator_registry():
    """创建包含计算器的工具注册表"""
    registry = ToolRegistry()

    # 注册计算器函数
    registry.register_function(
        name="my_calculator",
        description="简单的数学计算工具,支持基本运算(+,-,*,/)和sqrt函数",
        func=my_calculate
    )

    return registry

其中创建了 ToolRegistry类对应的实例registry
将这个工具命名为my_calculator,并给了他一个简单的描述“简单的数学计算工具,支持基本运算(+,-,*,/)和sqrt函数”

然后在test_my_calculator.py中调用这个工具
result = registry.execute_tool(“my_calculator”, expression)

在这里插入图片描述
下面我按“从零到可用”的视角,把 skills(工具)建立与注册流程拆开讲清楚:你要写什么文件、每个字段/接口怎么设计、怎么注册到 Agent、怎么做参数校验与错误处理、怎么测试与上架(可选)。我会以你前面那套 Tool(ABC) / run() / get_parameters() 的风格来对齐。


1)先统一概念:Tool / Skill / Registry / Executor

很多框架里叫法不一样,但结构基本一致:

  • Tool(工具):一个可被 LLM 调用的“函数”,有名字、描述、参数 schema、执行逻辑 run()
  • Skill(技能):一组相关工具的集合(比如“文件检索技能”包含 search/read/summarize 3 个 tools)
  • Registry(注册表):保存所有已注册工具的地方(name → tool instance / tool meta)
  • Executor(执行器):拿到“函数调用请求”(tool_name + args)后,做校验、执行、返回结果

你问的“建立与注册流程”,核心就是:
写 Tool → 描述参数(schema)→ 注册到 Registry → Agent 在推理时把 tools 暴露给模型 → 模型选择并调用 → Executor 执行并回传


2)建立一个 Tool 的标准流程(工程落地)

Step A:定义 Tool 的最小接口

你已有类似:

  • run(parameters: Dict[str, Any]) -> str
  • get_parameters() -> List[ToolParameter]

建议再补两个“工程里几乎必需要素”:

  1. 返回结构:不建议纯字符串。至少要有 success/data/error 的包装,方便 agent 处理失败重试、fallback。
  2. 元信息:例如 version、timeout、idempotent、rate_limit、tags(可选但很有用)

Step B:参数 Schema(你提到的 schema)

你现在是 ToolParameter 列表,这很好(对应 function calling 的 JSON schema)。

一个常见参数描述需要包含:

  • name: 参数名
  • type: string/number/integer/boolean/object/array
  • required: bool
  • description: 给模型看的提示(非常重要)
  • enum / min/max / pattern:约束(能显著减少乱填)
  • default: 默认值(可选)
  • items / properties:复杂结构(object/array)用

经验:描述写给模型看,要明确格式、单位、例子,比如 “date: YYYY-MM-DD”。

Step C:实现 run()

run() 里建议固定三层:

  1. 参数校验 & 归一化(类型转换、默认值、范围检查)
  2. 核心逻辑(真正干活)
  3. 结果包装(统一返回结构;异常转为可读错误)

3)工具注册:Registry 怎么设计最稳

Step A:Registry 需要做什么

  • 防止重名覆盖:同名工具拒绝或显式覆盖
  • 提供查询:get(name) / list() / export_schemas()
  • 输出给 LLM 的格式:function calling 需要一个 schema 列表

常见方法:

  • register_tool(tool: Tool)
  • register_tools(tools: List[Tool])
  • get_tool(name: str) -> Tool
  • list_tools() -> List[Tool]
  • to_openai_functions() / to_json_schema_list()

Step B:注册时做的校验(强烈建议)

注册那一刻就把坑堵住:

  • name 是否符合规范(小写+下划线/中划线,长度限制)
  • 描述不能为空
  • 参数名唯一
  • required 参数都出现在 schema 里
  • object 类型是否提供 properties
  • run 是否可调用(抽象类未实现会报错)

4)把 Tool 暴露给 LLM:Function Calling 的“绑定点”

你前面问过 function calling,这里把链路说透:

  1. Agent 构造 prompt + tools schema

  2. LLM 返回

    • 普通文本(不需要工具)
    • tool_call(包含 tool_name + args JSON)
  3. Executor 执行 tool_call

  4. 把 tool result 作为 ToolMessage 回给 LLM

  5. LLM 继续生成最终答案

所以“注册流程”的关键一步是:
Registry 导出 schema → LLM invoke 时传入 tools 参数(或 frameworks 里的 Tool list)


5)一个可复用的“注册与执行”标准模板(推荐架构)

5.1 Tool 层(定义)

  • BaseTool(ABC):统一接口
  • 每个 tool 一个文件:tools/weather.py, tools/web_search.py

5.2 Registry 层(管理)

  • ToolRegistry

    • register(tool)
    • get(name)
    • schemas()(导出给模型)

5.3 Executor 层(调用)

  • ToolExecutor

    • execute(tool_name, args)
    • 内置:参数校验、异常捕获、超时、日志、重试策略(可选)

5.4 Agent 层(集成)

  • 初始化时:

    • 创建 registry
    • 注册 tools(或加载 skills 包)
    • 构造 LLM 的 tools schema
  • 推理循环中:

    • 如果 LLM 返回 tool call → executor 执行 → 回填 tool result → 继续

6)“Skill(技能包)”级别的注册(工具集合)

当工具多了以后,你会希望按模块组织:

  • skills/search/__init__.py 暴露 get_tools()
  • skills/math/__init__.py 暴露 get_tools()

注册时:

  • registry.register_tools(search_skill.get_tools())
  • registry.register_tools(math_skill.get_tools())

这样你可以做到:

  • 按业务场景只加载部分技能
  • 做权限控制(某些 tool 仅内部可用)
  • 做能力路由(不同 agent 装配不同 skills)

7)参数校验怎么做最实用(避免模型乱填)

你问过“期望是这个类型,不强制,那怎么保证”:
答案是:运行时强校验 + 清晰 schema + 失败可恢复的错误信息

推荐策略(按强度从低到高):

  1. schema 约束(enum/min/max/pattern)
  2. 执行前 validate(缺字段/类型不对直接报错)
  3. 错误信息写给模型:告诉它“哪里错了、应该怎么改”
  4. 可选:自动修复(比如把 "1" 转 int,把逗号分隔 string 转 list)

关键:错误不是给人看的,是给 LLM 看的。要能让模型下一次 tool call 修正参数。


8)注册后的测试与验收清单(非常重要)

8.1 单测(Tool)

  • 正常输入 → 正常输出
  • 缺 required 参数 → 明确错误
  • 类型错误 → 明确错误
  • 边界值:min/max、空数组、空字符串

8.2 集成测试(Agent loop)

  • 提问触发 tool call
  • tool 返回结果后,模型能用结果完成回答
  • tool 失败时,模型能改参重试或 fallback(你可以在 prompt 里教它)

8.3 可观测性

  • 每次 tool call 记录:name、args、耗时、成功/失败、错误码
  • (可选)将结果截断,防止 log 过大

9)一个“典型注册流程”串起来(从启动到调用)

  1. 启动应用
  2. 创建 registry
  3. 加载 skills(按配置选择)
  4. registry 注册工具(校验 + 索引)
  5. agent 初始化:从 registry 导出 tools schema
  6. 用户提问
  7. LLM decide:是否 tool call
  8. executor:validate args → call tool.run → wrap result
  9. 将 tool result 反馈给 LLM
  10. LLM 输出最终答案

10)你现在这套 Tool(ABC) 该怎么扩展到“可注册、可调用、可扩展”

你目前抽象类已经很好了,我建议最少加三件事就能跑通工业级链路:

  1. ToolParameter → JSON Schema 的转换函数
  2. ToolRegistry:管理、导出 schemas、按名查 tool
  3. ToolExecutor:负责校验、执行、异常处理、日志

如果你愿意,我也可以直接按你现有代码风格,给你一套“可直接复制”的最小可用实现(包含 ToolParameter、registry、executor、一个 demo tool、一个模拟 function calling 的调用示例),这样你能立刻跑通整条链路。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐