🔧 研究进展 #2:Tool 系统深度解析
一、Tool 系统架构总览
Kimi Code CLI 的工具系统采用分层设计,基于 kosong 框架提供的 Tool/Toolset 抽象:
┌─────────────────────────────────────────────────────────┐
│ Tool Interface (kosong.tooling) │
│ ├── Tool - 基础工具接口 │
│ ├── CallableTool - 可调用工具 │
│ ├── CallableTool2[T] - 带参数模型的工具 │
│ └── Toolset - 工具集合 │
├─────────────────────────────────────────────────────────┤
│ KimiToolset (soul/toolset.py) │
│ - 工具加载、执行、MCP 管理 │
├─────────────────────────────────────────────────────────┤
│ Built-in Tools (tools/) │
│ ├── file/ - 文件读写、Glob、Grep │
│ ├── shell/ - Shell 命令执行 │
│ ├── web/ - 网页搜索和获取 │
│ ├── multiagent/ - 子 Agent 管理 │
│ ├── think/ - 思考工具 │
│ └── todo/ - 任务管理 │
├─────────────────────────────────────────────────────────┤
│ MCP Tools (外部扩展) │
│ - 通过 MCP 协议动态加载的外部工具 │
└─────────────────────────────────────────────────────────┘
二、KimiToolset 核心机制
1. 工具加载 (load_tools)
# 工具路径格式: "module.path:ClassName"
tool_paths = [
"kimi_cli.tools.shell:Shell",
"kimi_cli.tools.file.read:ReadFile",
...
]
toolset.load_tools(tool_paths, dependencies={Runtime: runtime})
依赖注入机制:
- 工具类可以通过构造函数参数声明依赖
KimiToolset._load_tool 会自动注入匹配的依赖- 支持
__init__ 方法中的位置参数
2. 工具执行 (handle)
def handle(self, tool_call: ToolCall) -> HandleResult:
# 1. 设置当前工具调用上下文
token = current_tool_call.set(tool_call)
# 2. 查找并执行工具
tool = self._tool_dict[tool_call.function.name]
arguments = json.loads(tool_call.function.arguments)
ret = await tool.call(arguments)
# 3. 返回 ToolResult
return ToolResult(tool_call_id=tool_call.id, return_value=ret)
3. MCP 工具集成
async def load_mcp_tools(self, mcp_configs: list[MCPConfig], ...):
# 1. 为每个 MCP 服务器创建 Client
# 2. 异步连接所有服务器
# 3. 列出工具并包装为 MCPTool
# 4. 添加到 toolset
MCPTool 特点:
- 自动添加来源服务器信息到描述
- 支持超时控制
- 需要用户审批(通过 Approval 系统)
三、内置工具详解
1. ReadFile 工具
功能: 安全地读取文本文件内容
参数模型 (Pydantic):
class Params(BaseModel):
path: str # 文件路径
line_offset: int # 起始行号(默认1)
n_lines: int # 读取行数(默认1000,最大1000)
安全机制:
- 工作目录外文件需要绝对路径
- 自动检测文件类型(拒绝图片/视频)
- 行数和字节数限制(防止大文件)
- 行长超过 2000 字符自动截断
输出格式:
1 第一行内容
2 第二行内容
...
2. Shell 工具
功能: 执行 Shell/PowerShell 命令
关键特性:
- 支持 Bash (Linux/Mac) 和 PowerShell (Windows)
- 实时流式输出(stdout/stderr)
- 可配置超时(默认60秒,最大5分钟)
- 需要用户审批才能执行
执行流程:
async def __call__(self, params: Params) -> ToolReturnValue:
# 1. 请求用户审批
if not await self._approval.request(...):
return ToolRejectedError()
# 2. 执行命令(带超时)
exitcode = await self._run_shell_command(...)
# 3. 返回结果
return builder.ok/error(...)
四、工具开发规范
基于源码分析,开发新工具需要遵循以下规范:
1. 基础模板
from pydantic import BaseModel, Field
from kosong.tooling import CallableTool2, ToolOk, ToolError
class Params(BaseModel):
param1: str = Field(description="参数描述")
param2: int = Field(default=10, ge=1, description="带约束的参数")
class MyTool(CallableTool2[Params]):
name: str = "MyTool"
params: type[Params] = Params
def __init__(self, runtime: Runtime):
super().__init__(description="工具描述")
self._runtime = runtime
async def __call__(self, params: Params) -> ToolReturnValue:
# 实现逻辑
return ToolOk(output="结果", message="成功消息")
2. 依赖注入
# 在 __init__ 中声明依赖
def __init__(self, runtime: Runtime, approval: Approval):
...
# 加载时注入
toolset.load_tools(
["mymodule:MyTool"],
dependencies={Runtime: runtime, Approval: approval}
)
3. 错误处理
# 返回结构化错误
return ToolError(
message="详细错误信息",
brief="简短错误提示"
)
# 或抛出异常让框架处理
raise ToolRuntimeError("错误信息")
五、MCP 集成机制
MCP (Model Context Protocol) 是 Anthropic 推出的开放协议,Kimi Code CLI 完整支持:
加载流程:
- 配置解析 - 从
mcpServers 配置读取服务器信息 - 客户端创建 - 使用
fastmcp.Client 创建连接 - 异步连接 - 后台并发连接所有服务器
- 工具同步 - 列出服务器工具并注册到 KimiToolset
工具调用:
class MCPTool(CallableTool):
async def __call__(self, *args, **kwargs):
# 1. 请求审批
if not await self._runtime.approval.request(...):
return ToolRejectedError()
# 2. 调用 MCP 服务器
result = await self._client.call_tool(...)
# 3. 转换结果格式
return convert_mcp_tool_result(result)
六、关键发现 💡
- 上下文变量
current_tool_call - 用于在工具执行期间获取当前调用信息,WireExternalTool 依赖此机制
- ToolResultBuilder - 用于构建流式输出结果,Shell 工具使用此模式
- 审批系统集成 - 所有"危险"操作(Shell、MCP)都通过 Approval 系统请求用户确认
- 动态工具加载 - 支持运行时从 Agent Spec 加载工具列表,非常灵活
七、下一步研究计划
| 阶段 | 目标 |
|---|
| #3 | Skill 系统 - 理解 Skill 的定义、加载和执行机制 |
| #4 | Context 管理 - 深入研究对话历史和 Compaction |
研究时间:2026-02-23
当前进度:Tool 系统 ✓