5.1 工具抽象接口设计
工具抽象接口是工具系统的核心基础,需要在通用性、类型安全、可观测性和性能间取得平衡。本节介绍 Claude Code 的泛型设计、工具实现示例、注册中心机制,以及权限管理策略。
5.1.1 统一工具接口的设计目标
工具抽象接口的设计需要平衡以下目标:
通用性:支持各种异构工具(文件、网络、计算、数据库等)
类型安全:在编译时(或运行时)检查参数和返回值类型
可观测性:支持进度报告、事件发射、日志记录
可扩展性:易于添加新工具类型
性能:最小化开销,支持并发执行
安全性:权限检查、资源限制、错误隔离
5.1.2 Claude Code 的 Tool<Input,Output,Progress> 泛型设计
Claude Code 采用泛型 Tool 接口,明确定义输入、输出和进度类型:
"""
Claude Code 风格的工具接口
"""
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Generic, TypeVar, Optional, Dict, Any, List
import asyncio
# 类型变量
# (Claude Code 的 Tool<Input,Output,Progress> 三泛型中的 Progress,
# 本简化实现用下方具体的 ToolProgress 类承载,不再单设类型变量)
InputType = TypeVar('InputType')
OutputType = TypeVar('OutputType')
@dataclass
class ToolProgress:
"""工具执行进度"""
step: int # 当前步骤号
total_steps: int # 总步骤数
current_status: str # 当前状态描述
estimated_time_remaining: Optional[float] = None # 剩余时间(秒)
def percentage(self) -> float:
"""进度百分比"""
return (self.step / self.total_steps * 100) if self.total_steps > 0 else 0
class Tool(ABC, Generic[InputType, OutputType]):
"""通用工具抽象"""
@abstractmethod
async def call(self, input_data: InputType) -> OutputType:
"""
执行工具
Args:
input_data: 工具输入,已验证和类型检查过
Returns:
工具执行结果
Raises:
ToolExecutionError: 工具执行失败
"""
pass
@abstractmethod
def name(self) -> str:
"""工具名称"""
pass
@abstractmethod
def description(self) -> str:
"""工具描述"""
pass
@abstractmethod
def input_schema(self) -> Dict[str, Any]:
"""输入的 JSON Schema"""
pass
def check_permissions(self, context: Any) -> bool:
"""
检查当前上下文是否有权限调用此工具
Args:
context: 执行上下文(包含用户、会话信息等)
Returns:
是否有权限
"""
return True # 默认允许
async def get_progress(self) -> Optional[ToolProgress]:
"""
获取工具执行进度
Returns:
进度对象,如果工具不支持进度报告则返回 None
"""
return None
def supports_streaming(self) -> bool:
"""工具是否支持流式输出"""
return False
async def stream_output(self, input_data: InputType):
"""
流式输出(可选)
Yields:
OutputType: 逐个产生的输出
"""
if not self.supports_streaming():
output = await self.call(input_data)
yield output⚠️ 类型系统说明:上述
Tool[InputType, OutputType]的泛型注解为设计理想。在 Python 运行时,由于动态类型特性,实际实现常使用Dict[str,Any]承载参数和返回值。这是 Python 动态类型系统与静态类型检查间的权衡——静态分析可以验证泛型约束,但运行时仍需灵活处理异构数据。关于完整的类型安全实现,请参考第 5.3 节和附录 D(MiniHarness 类型体系)。
本节展示了工具的核心设计模式与流程。为了更好地理解如何将这些模式应用于实践,下面我们通过具体的实现示例来演示工具的常见用法。
5.1.3 工具实现示例
1. 简单工具:Bash 执行
一个简单的 Bash 命令执行工具的实现如下:
2. 支持进度报告的工具:文件复制
一个支持进度报告的文件复制工具,展示如何在长时间运行的操作中提供实时反馈:
3. 流式输出工具:数据库查询
一个支持流式输出的数据库查询工具,展示如何处理大结果集:
💡 类型参数说明:以下示例中
Tool<I,O,P>的类型参数为概念占位符。运行时实现使用Dict[str,Any]承载动态数据。如需真正的静态类型约束,可改用Pydantic BaseModel或TypedDict(见附录 D MiniHarness 实现)。
5.1.4 buildTool() 工厂函数
Claude Code 使用工厂函数动态构造工具,支持参数化和延迟初始化:
5.1.5 工具注册中心
工具注册中心是所有工具的中枢,负责工具的注册、发现和管理。下面的流程图展示了工具的注册、发现和查询的完整流程:
图 5-1:工具注册与发现流程
5.1.6 OpenClaw 的工具策略模型
OpenClaw 支持更细粒度的权限管理:
5.1.7 本节小结
工具抽象接口的设计决定了整个工具系统的质量和可维护性:
Claude Code 的 Tool<I,O,P> 泛型设计 提供了强类型检查,但需要 Python 的高级类型系统支持
工具工厂函数 支持动态工具构造和参数化配置
工具注册中心 管理工具的生命周期和 Schema 缓存
权限检查 在工具调用前进行,可以是简单的 boolean 也可以是复杂的策略模型
OpenClaw 的工具策略模型 提供更细粒度的权限管理,支持不同智能体的不同权限
好的工具抽象应该既通用又灵活,既简单又强大。在实践中,需要根据具体场景选择合适的抽象级别。
最后更新于
