上一小节我们保存的是:
name → function
够不够?
短期够。
但很快你会想知道:
这个 Tool 是干什么的?
有没有副作用?
属于哪一类?
是否需要审批?
超时多少?
后面 Schema 怎么生成?
如果 Registry 只保存 Callable,这些信息没地方放。
所以更好的方式是定义:
Tool
对象。
一个 Tool 最少可以有什么?
当我们说“注册一个工具”时,真正被放进 Registry 的,最好不是孤零零的函数指针,而是一个带上下文信息的 Tool 对象。这样后面的描述、参数、权限控制才能自然长出来。
![图片[1]-核心小节二:Tool 不只是函数——为什么 Registry 最好保存 Tool 对象和 Metadata-大赛人网](https://www.dsrw.com/wp-content/uploads/2026/11/image-1466.png)
图里把这个关系拆得比较直观:函数只是 callable,本体之外还会带上 name、description、schema、permission、side_effect 等信息。这样 Registry 才不仅能“存起来”,还能真正支撑模型调用和工程治理。
例如:
name
description
func
再进一步:
category
risk_level
requires_approval
但这一节不要过度设计。
先做:
@dataclass
class Tool:
name: str
description: str
func: Callable
为什么 description 很重要?
因为后面模型不是只看到:
read_file
它还要知道,这个 Tool 到底什么时候用?
例如:
read_file:
读取工作目录内一个 UTF-8 文本文件的完整内容。
与:
search_files:
按关键词搜索文件名和文本内容。
如果描述模糊,模型 Tool 选择质量会明显下降。
所以 description 不是文档附属品。
它会直接影响 Agent 决策。
完整 Tool 数据类
from dataclasses import dataclass
from typing import Any, Callable
@dataclass
class Tool:
name: str
description: str
func: Callable[..., Any]
Registry:
class ToolRegistry:
def __init__(self):
self._tools: dict[
str,
Tool
] = {}
这时 get() 返回的就不是函数,而是 Tool 对象。
执行:
tool = registry.get(name)
result = tool.func(**arguments)
一个完整可运行版本
现在 Registry 已经开始像一个真正工具目录。
Tool Metadata 为什么要逐步增加?
这一节特别适合配一张演进图来看。因为很多同学容易误会成:一上来就要把所有 metadata 设计得特别全。其实真实工程一般不是这么推进的。
![图片[2]-核心小节二:Tool 不只是函数——为什么 Registry 最好保存 Tool 对象和 Metadata-大赛人网](https://www.dsrw.com/wp-content/uploads/2026/11/image-1467.png)
更自然的方式是先让工具跑起来,再逐步补齐描述、参数 schema、标签、版本、权限、风险等级这些信息。也正因为是逐步长出来的,所以前期的设计要尽量留出扩展空间。
后面很自然会加:
schema
risk_level
timeout
tags
requires_approval
例如:
read_file
risk_level=low
write_file
risk_level=medium
run_shell
risk_level=high
然后 Middleware 就可以:
if tool.risk_level == "high":
...
这就是 Registry 作为统一入口的真正扩展价值。
Metadata 本身只是声明。给工具写上 risk_level="high",不会自动阻止任何调用;标记 idempotent=False,也不会自动获得防重能力。只有 Middleware、重试策略和 Trace 真正读取这些字段,它们才会变成运行约束。看到元数据已经存在时,记得再追问一句:谁在消费它?
Registry 和 Schema 的边界
这里很多人会串线:Registry、Schema、Executor 都和工具有关,但职责并不一样。把边界看清楚,后面设计代码结构就会顺很多。
![图片[3]-核心小节二:Tool 不只是函数——为什么 Registry 最好保存 Tool 对象和 Metadata-大赛人网](https://www.dsrw.com/wp-content/uploads/2026/11/image-1468.png)
简单说,Registry 负责存定义和统一来源;Schema 是从 Registry 里裁出来给模型看的可见视图;Executor 则拿到 tool_call 以后做校验、权限判断和真正执行。三者相关,但绝不是一回事。
先提前说清楚。
Registry 负责,有哪些 Tool,真实 Callable 是什么。
Schema 负责,怎么把 Tool 描述给模型。
例如 Registry 保存:
Tool(
name="read_file",
description="读取文件",
func=read_file
)
下一节会从函数签名:
read_file(path: str)
生成:
{
"name": "read_file",
"parameters": {
...
}
}
两者紧密相关,但不是同一个概念。
















请登录后查看评论内容