工具系统 ToolRegistry
源码版本v2026.7.20
职责
Tool 是 agent 能调用的原子函数(终端、浏览器、文件、MCP、技能调用……)。ToolRegistry 在模块导入时通过 AST 扫描自动发现 tools/*.py 里的工具并注册,提供一个 name → ToolEntry 的查询表给主循环做工具分发。工具是静态的——与技能的「可演化」相对。
关键文件
discover_builtin_tools:67-86— AST 扫描tools/*.py找出注册了工具的模块_is_registry_register_call / _module_registers_tools:30-43— 判断某模块是否调用registry.registerclass ToolEntry:87-153— 单个工具的元数据(handler、schema、toolset、缓存标志)class ToolRegistry:217-365— 注册表本体def register:365-436— 注册一个工具,内部构造ToolEntryget_entry / register_toolset_alias:274-290— 查询与 toolset 别名register_plugin_override_policy:316-365— 插件工具的命名空间准入策略registry 单例:765—registry = ToolRegistry()(模块级单例)tool_error / tool_result:784-810— 工具返回值标准封装tools/ 目录— 约 80 个工具文件(terminal/browser/web/file/mcp/skills/delegate…)
数据流
- 启动期
init_agent:276触发 toolsets 配置。 discover_builtin_tools:67遍历tools/目录,用 AST 判断每个模块是否调用registry.register(tools/registry.py:30)。- 命中的模块被导入,其模块级
registry.register(...)调用执行,把ToolEntry写入registry 单例:765。 - 主循环每轮把启用的 toolsets 对应的
ToolEntry.schema收集进发给 provider 的tools字段。 - provider 返回 tool_call → 主循环用
get_entry(name)(tools/registry.py:274)查到 handler 执行 → 结果用tool_result:798封装回填。
小结
工具系统的精妙在「导入即注册」——靠 AST 扫描避免手动维护清单,新增工具只需往 tools/ 丢一个调 register 的文件。registry 单例是全局唯一真相,主循环只读它。和技能的区别:工具是死的函数,技能是可被学习循环改写的流程。