自定义工具开发
Riverse 采用即插即用的工具系统。只需在 agent/tools/ 目录下创建一个 .py 文件即可添加新工具,无需额外注册。
接口
每个工具继承 BaseTool,实现两个方法:
from agent.tools import BaseTool, ToolManifest, ToolResult
class MyTool(BaseTool):
def __init__(self, config: dict):
self.config = config
def manifest(self) -> ToolManifest:
return ToolManifest(
name="my_tool", # 唯一标识
description="供 LLM 判断何时使用该工具的一句话描述",
parameters={
"param_name": "参数含义说明",
},
examples=[
"自然语言触发示例 1",
"自然语言触发示例 2",
],
)
def execute(self, params: dict) -> ToolResult:
value = params.get("param_name", "")
# 在这里实现你的逻辑...
result = f"处理结果: {value}"
return ToolResult(success=True, data=result)
ToolManifest
| 字段 | 用途 |
|---|---|
name |
唯一标识符,LLM 通过此名称调用工具。 |
description |
一句话描述,LLM 据此判断何时使用该工具。 |
parameters |
{参数名: 说明} 字典,LLM 会自动填入参数值。 |
examples |
2-3 个会触发该工具的自然语言示例。 |
ToolResult
| 字段 | 用途 |
|---|---|
success |
True / False |
data |
字符串,作为参考信息注入 LLM 上下文。 |
error |
错误信息(仅在 success=False 时使用)。 |
可选:is_available()
重写此方法可在依赖缺失时禁用工具:
def is_available(self) -> bool:
return self.config.get("tools", {}).get("my_tool", {}).get("enabled", True)
示例:天气查询工具
import requests
from agent.tools import BaseTool, ToolManifest, ToolResult
class WeatherTool(BaseTool):
def __init__(self, config: dict):
self.config = config
def manifest(self) -> ToolManifest:
return ToolManifest(
name="weather",
description="查询指定城市的当前天气",
parameters={"city": "城市名,例如 东京、伦敦"},
examples=["东京今天天气怎么样?", "伦敦在下雨吗?"],
)
def execute(self, params: dict) -> ToolResult:
city = params.get("city", "").strip()
if not city:
return ToolResult(success=False, data="", error="缺少城市名")
try:
r = requests.get(f"https://wttr.in/{city}?format=j1", timeout=10)
data = r.json()["current_condition"][0]
summary = f"{city}: {data['temp_C']}°C, {data['weatherDesc'][0]['value']}"
return ToolResult(success=True, data=summary)
except Exception as e:
return ToolResult(success=False, data="", error=str(e))
保存为 agent/tools/weather.py,下次启动即可使用。
工作原理
- 启动时,
ToolRegistry扫描agent/tools/下所有.py文件(跳过_开头的文件)。 - 对每个
BaseTool子类调用is_available()。 - 可用的工具按
manifest().name注册。 - 用户发送消息时,LLM 会看到所有工具的 manifest,决定调用哪个。
- 工具的
execute()结果会注入 LLM 上下文,用于生成最终回复。