核心原则
OpenManus的工具系统基于「插件化设计」,所有自定义工具需继承框架的BaseTool基类,实现标准化接口,再通过配置文件注册,即可被AI智能体识别和调用。
一、前置准备
确认目录结构:在OpenManus项目根目录下,建议创建custom_tools目录存放自定义工具(便于管理):
mkdir custom_tools # 项目根目录执行
核心依赖:确保已安装基础依赖(无需额外安装,框架自带工具基类):
pip install openmanus # 若未安装框架核心包
二、步骤1:编写自定义工具类(核心)
所有自定义工具必须继承BaseTool基类,并实现3个核心要素:
name:工具唯一名称(AI通过名称识别工具)description:工具描述(关键!AI通过描述判断何时调用该工具,需清晰说明「用途+输入格式」)run():工具执行逻辑(接收输入参数,返回执行结果)
示例:开发「实时天气查询工具」
创建custom_tools/weather_tool.py文件,写入以下代码(含完整注释):
# 导入框架核心基类和结果封装类
from openmanus.tools.base import BaseTool, ToolResult
# 按需导入第三方依赖(如请求网络需requests)
import requests
# 自定义工具类,必须继承BaseTool
class WeatherQueryTool(BaseTool):
# 1. 工具唯一名称(不可重复,建议英文)
name = "WeatherQueryTool"
# 2. 工具描述(核心!需明确:用途+输入格式+输出说明)
description = """
用于查询指定城市的实时天气信息,输入格式为「城市名」(如:北京、上海),
输出格式为「城市名 + 温度 + 天气状况」(如:北京 18℃ 晴)。
仅当用户询问天气相关问题时调用该工具。
"""
# 3. 工具执行逻辑,必须实现run方法
def run(self, city: str) -> ToolResult:
"""
参数说明:
- city: 字符串,用户输入的城市名
返回值:ToolResult对象(封装执行结果,必填)
"""
try:
# 步骤1:校验输入(可选,增强健壮性)
if not city or len(city) > 10:
return ToolResult(
success=False, # 执行失败标记
content="输入无效!请输入正确的城市名(如:北京)"
)
# 步骤2:核心业务逻辑(调用免费天气API)
# 替换为可靠的天气API,此处使用wttr.in(无需密钥)
url = f"http://wttr.in/{city}?format=3" # 精简格式:城市名: 天气 温度
response = requests.get(url, timeout=10)
# 步骤3:处理响应并封装结果
if response.status_code == 200:
weather_info = response.text.strip()
return ToolResult(
success=True, # 执行成功标记
content=f"✅ {weather_info}" # 返回给AI的内容
)
else:
return ToolResult(
success=False,
content=f"❌ 天气查询失败,API响应码:{response.status_code}"
)
# 异常处理(必加,避免工具崩溃)
except requests.exceptions.Timeout:
return ToolResult(success=False, content="❌ 网络超时,无法查询天气")
except Exception as e:
return ToolResult(success=False, content=f"❌ 查询出错:{str(e)}")
关键说明:
三、步骤2:配置文件注册自定义工具
修改OpenManus的核心配置文件config.yaml(无则从config.example.yaml复制),将自定义工具添加到tools列表中:
1. 复制配置模板(首次需做)
cp config.example.yaml config.yaml # 项目根目录执行
2. 编辑config.yaml,添加工具配置
找到tools节点,新增自定义工具的配置项:
# config.yaml 核心配置片段
llm:
type: openai
model: gpt-4-turbo
api_key: "sk-xxxxxx" # 替换为你的LLM密钥
base_url: "https://api.openai.com/v1"
# 工具注册列表(内置工具 + 自定义工具)
tools:
# 保留框架内置工具(按需取舍)
- name: BrowserTool # 浏览器工具
- name: CodeExecutorTool # 代码执行工具
- name: FileTool # 文件操作工具
# 新增自定义工具(关键配置)
- name: WeatherQueryTool # 必须和工具类的name一致
path: custom_tools/weather_tool.py # 工具文件的绝对/相对路径
enabled: true # 是否启用该工具(默认true)
配置说明:
name:必须和自定义工具类中定义的name完全一致(大小写敏感)。path:工具文件的路径,支持相对路径(相对于项目根目录)或绝对路径。enabled:是否启用该工具,设为false则AI不会调用。
四、步骤3:测试自定义工具
编写测试代码,验证自定义工具是否能被AI智能体识别并调用:
1. 创建测试文件test_custom_tool.py
import asyncio
from openmanus.agent import Agent # 单智能体
from openmanus.config import Config # 配置加载类
# 异步测试函数(OpenManus核心逻辑为异步)
async def test_weather_tool():
# 步骤1:加载配置文件
config = Config.from_file("config.yaml")
# 步骤2:初始化AI智能体
agent = Agent(config=config)
# 步骤3:发送包含工具调用的任务指令
task = "查询深圳市的实时天气"
# 步骤4:执行任务并获取结果
result = await agent.run(task)
# 步骤5:打印结果
print("=== 自定义工具调用结果 ===")
print(result)
# 执行测试
if __name__ == "__main__":
asyncio.run(test_weather_tool())
2. 运行测试代码
python test_custom_tool.py
预期输出:
=== 自定义工具调用结果 ===
✅ 深圳: 晴 25℃
五、进阶:支持多参数的自定义工具
若工具需要多个输入参数(如「根据城市和日期查询天气预报」),修改工具类的run方法即可:
示例:多参数天气工具
class WeatherQueryTool(BaseTool):
name = "WeatherQueryTool"
description = """
查询指定城市指定日期的天气预报,输入格式为「城市名,日期」(日期格式:YYYY-MM-DD,例:北京,2026-01-20)。
若未指定日期,则查询实时天气。
"""
def run(self, input_str: str) -> ToolResult:
# 解析多参数
parts = input_str.split(",")
city = parts[0].strip()
date = parts[1].strip() if len(parts) > 1 else None
# 核心逻辑(示例)
if date:
content = f"✅ {city} {date} 的天气预报:晴 22-30℃"
else:
content = f"✅ {city} 实时天气:晴 25℃"
return ToolResult(success=True, content=content)
测试指令可改为:查询上海2026-01-20的天气预报。
六、常见问题与排查
问题1:AI不调用自定义工具
- 原因:
description描述不清晰,AI无法判断何时调用;或工具名称/路径配置错误。 解决:
- 优化
description,明确「触发条件+输入格式」; - 检查
config.yaml中工具name是否和类名一致; - 测试时指令明确(如「用WeatherQueryTool查询北京天气」)。
问题2:工具执行报错「找不到模块」
- 原因:工具文件路径配置错误,或未继承
BaseTool。 解决:
- 确认
config.yaml中path是相对项目根目录的路径; - 检查工具类是否正确导入
from openmanus.tools.base import BaseTool。
问题3:工具返回结果为空
- 原因:
run方法未正确返回ToolResult对象,或业务逻辑出错。 解决:
- 确保
run方法最后return ToolResult(...); - 在
run方法中添加日志(如print(city)),调试业务逻辑。
总结
- 核心步骤:自定义工具开发需遵循「继承BaseTool→实现name/description/run→配置文件注册→测试验证」的流程,缺一不可。
- 关键要点:
description是AI调用工具的核心依据,需精准描述用途和输入格式;ToolResult是结果返回的标准格式,必须使用。 - 扩展技巧:单参数工具直接接收字符串,多参数工具可通过分隔符(如逗号)解析输入,复杂场景可使用JSON格式传参。