工具基类与接口规范

📎 引用文件

本文引用的文件 - agent/src/agent/tools.py - agent/src/tools/__init__.py - agent/src/tools/market_data_tool.py - agent/src/tools/web_search_tool.py - agent/src/tools/remember_tool.py - agent/src/tools/options_chain_tool.py - agent/tests/test_institutional_holdings_tool.py

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考虑
  8. 故障排查指南
  9. 结论
  10. 附录:自定义工具开发示例

简介

本文件面向 Vibe-Trading 的工具子系统,系统化说明 BaseTool 抽象类的设计原理、工具注册机制、执行契约以及 OpenAI 函数调用格式的转换过程。文档同时提供可操作的自定义工具开发指引,帮助开发者快速实现符合规范的本地工具,并理解其在代理循环中的行为约束(如只读标记、可重复执行标志)和错误处理约定。

项目结构

Vibe-Trading 的工具子系统以“约定优于配置”的方式组织: - 基类与注册表定义位于 agent/src/agent/tools.py,提供 BaseTool 抽象类和 ToolRegistry 容器。 - 工具自动发现与装配位于 agent/src/tools/init.py,通过扫描包内模块并收集 BaseTool 子类完成注册。 - 具体工具实现位于 agent/src/tools/* 下,每个工具一个文件,继承 BaseTool 并实现 execute 等方法。

graph TB A["BaseTool<br/>抽象类"] --> B["ToolRegistry<br/>工具注册表"] C["工具自动发现<br/>build_registry()"] --> B D["MarketDataTool"] --> B E["WebSearchTool"] --> B F["RememberTool"] --> B G["OptionsChainTool"] --> B C --> D C --> E C --> F C --> G

图表来源 - agent/src/agent/tools.py:13-95 - agent/src/tools/__init__.py:33-63 - agent/src/tools/market_data_tool.py:11-104 - agent/src/tools/web_search_tool.py:134-170 - agent/src/tools/remember_tool.py:13-66 - agent/src/tools/options_chain_tool.py:37-68

章节来源 - agent/src/agent/tools.py:13-95 - agent/src/tools/__init__.py:33-63

核心组件

关键要点 - 工具标识符 name:唯一名称,用于注册表索引与 LLM 调用。 - 描述 description:向 LLM 暴露的工具用途说明。 - 参数 parameters:JSON Schema 形式,用于 LLM 参数校验与生成。 - repeatable:是否允许重复调用;影响 LLM 的调用策略。 - is_readonly:是否为只读工具;影响安全策略与通道包装。 - check_available:可选覆盖,用于运行时依赖检查(如第三方库或密钥)。 - execute:必须实现,接收任意关键字参数,返回 JSON 字符串结果。 - to_openai_schema:将工具元信息转换为 OpenAI function calling 格式。

章节来源 - agent/src/agent/tools.py:13-51 - agent/src/agent/tools.py:54-95

架构总览

工具在启动时通过自动发现被注册到 ToolRegistry,随后由上层(如 MCP 适配层或代理循环)通过名称调用。执行路径包括: - 构建注册表:扫描 src/tools 包,导入各模块,收集 BaseTool 子类实例并注册。 - 过滤与注入:根据策略决定是否包含 shell 工具、是否注入会话 ID、是否合并远程 MCP 工具等。 - 执行与封装:ToolRegistry.execute 捕获异常并返回统一的 JSON 信封,避免异常上抛破坏流程。

sequenceDiagram participant Reg as "工具注册表" participant Disc as "自动发现" participant T as "具体工具(BaseTool)" participant L as "调用方(代理/MCP)" L->>Reg : 获取工具定义(get_definitions) Reg-->>L : OpenAI函数列表(to_openai_schema) L->>Reg : 执行(name, params) Reg->>T : execute(**params) T-->>Reg : JSON字符串结果 Reg-->>L : JSON字符串结果(统一信封)

图表来源 - agent/src/agent/tools.py:68-84 - agent/src/tools/__init__.py:66-245

章节来源 - agent/src/tools/__init__.py:66-245 - agent/src/agent/tools.py:68-84

详细组件分析

BaseTool 抽象类

classDiagram class BaseTool { +string name +string description +dict parameters +bool repeatable +bool is_readonly +check_available() bool +execute(**kwargs) string +to_openai_schema() dict }

图表来源 - agent/src/agent/tools.py:13-51

章节来源 - agent/src/agent/tools.py:13-51

ToolRegistry 执行与错误封装

flowchart TD Start(["调用 ToolRegistry.execute"]) --> Find{"是否存在工具?"} Find -- 否 --> ErrNotFound["返回未找到错误(JSON)"] Find -- 是 --> Call["调用 tool.execute(**params)"] Call --> TryOK{"是否抛出异常?"} TryOK -- 是 --> WrapErr["记录异常并返回错误(JSON)"] TryOK -- 否 --> Return["返回工具执行结果(JSON)"] ErrNotFound --> End(["结束"]) WrapErr --> End Return --> End

图表来源 - agent/src/agent/tools.py:72-84

章节来源 - agent/src/agent/tools.py:54-95

工具自动发现与注册

flowchart TD S(["开始构建注册表"]) --> Scan["扫描src/tools模块"] Scan --> Import["导入模块(忽略内部模块)"] Import --> Collect["收集BaseTool子类"] Collect --> Filter{"check_available?"} Filter -- False --> Skip["跳过该工具"] Filter -- True --> Special{"是否特殊工具?"} Special -- 是 --> Inject["注入依赖/上下文"] Special -- 否 --> Register["直接注册"] Inject --> Register Register --> MergeMCP{"是否合并MCP工具?"} MergeMCP -- 是 --> AddRemote["添加远程工具(失败隔离)"] MergeMCP -- 否 --> Done(["完成"]) AddRemote --> Done Skip --> Done

图表来源 - agent/src/tools/__init__.py:33-63 - agent/src/tools/__init__.py:66-245

章节来源 - agent/src/tools/__init__.py:33-63 - agent/src/tools/__init__.py:66-245

具体工具示例分析

MarketDataTool(市场数据)

章节来源 - agent/src/tools/market_data_tool.py:11-104

WebSearchTool(网络搜索)

章节来源 - agent/src/tools/web_search_tool.py:134-200

RememberTool(持久记忆)

章节来源 - agent/src/tools/remember_tool.py:13-178

OptionsChainTool(期权链)

章节来源 - agent/src/tools/options_chain_tool.py:37-156

OpenAI 函数调用格式转换

sequenceDiagram participant T as "工具实例" participant R as "注册表" participant L as "LLM/调用方" L->>R : get_definitions() R->>T : to_openai_schema() T-->>R : {"type" : "function","function" : {...}} R-->>L : 函数定义列表 L->>R : execute(name, params) R-->>L : JSON字符串结果

图表来源 - agent/src/agent/tools.py:42-51 - agent/src/agent/tools.py:68-70 - agent/tests/test_institutional_holdings_tool.py:1637-1646

章节来源 - agent/src/agent/tools.py:42-70 - agent/tests/test_institutional_holdings_tool.py:1637-1646

依赖关系分析

graph LR BT["BaseTool"] --> TR["ToolRegistry"] AD["自动发现"] --> TR T1["MarketDataTool"] --> TR T2["WebSearchTool"] --> TR T3["RememberTool"] --> TR T4["OptionsChainTool"] --> TR MCP["MCP适配器"] --> TR

图表来源 - agent/src/agent/tools.py:13-95 - agent/src/tools/__init__.py:66-245

章节来源 - agent/src/tools/__init__.py:66-245 - agent/src/agent/tools.py:13-95

性能考虑

[本节为通用指导,不直接分析具体文件]

故障排查指南

章节来源 - agent/src/agent/tools.py:72-84 - agent/tests/test_institutional_holdings_tool.py:1653-1664

结论

BaseTool 与 ToolRegistry 构成了 Vibe-Trading 工具系统的核心骨架:前者定义统一契约与扩展点,后者提供注册、发现与执行保障。通过 JSON Schema 参数、OpenAI 函数调用格式转换、可重复执行与只读标记,系统实现了高内聚、低耦合、可扩展的工具生态。结合自动发现与依赖检查,开发者可以专注于业务逻辑,而无需关心底层编排细节。

[本节为总结性内容,不直接分析具体文件]

附录:自定义工具开发示例

以下示例展示如何继承 BaseTool 并实现必要接口,满足自动发现与执行契约:

步骤概览 - 新建工具文件:在 agent/src/tools 目录下创建新模块(文件名不以“_”开头)。 - 定义类:继承 BaseTool,设置 name、description、parameters、repeatable、is_readonly。 - 实现 check_available:如需依赖检查,重写该方法返回布尔值。 - 实现 execute:接收 **kwargs,进行参数校验与业务处理,返回 JSON 字符串。 - 自动注册:无需额外代码,工具会在构建注册表时被自动发现与注册。

参考实现路径 - 简单只读工具:参见 MarketDataTool 的参数定义与 execute 委托模式。 - 带依赖检查的工具:参见 WebSearchTool 的 check_available 与 execute 的错误封装。 - 写操作工具:参见 RememberTool 的 is_readonly=False 与多动作路由。 - 复杂数据工具:参见 OptionsChainTool 的参数校验、异常捕获与结构化返回。

章节来源 - agent/src/tools/market_data_tool.py:11-104 - agent/src/tools/web_search_tool.py:134-200 - agent/src/tools/remember_tool.py:13-178 - agent/src/tools/options_chain_tool.py:37-156 - agent/src/tools/__init__.py:33-63