【免费下载链接】software-agent-sdk
A clean, modular SDK for building AI agents with OpenHands V1.
OpenHands Software Agent SDK 是一个用于构建 AI 智能体的模块化 SDK,而「自定义工具」正是它最有扩展性的能力之一。本教程带你走通完整流程:如何为 OpenHands Software Agent SDK 定义一个自定义工具——从输入(Action)、输出(Observation)、执行器(ToolExecutor)到最终用register_tool()注册并挂载给 Agent。只需 4 步,你就能让 AI 智能体获得调用你专属 API、查询数据库或执行领域逻辑的能力 🚀
一、先看全貌:一个自定义工具由 4 部分组成
在 Software Agent SDK 中,每一个工具都是「契约 + 实现」的组合,核心代码位于 openhands-sdk/openhands/sdk/tool/ 目录:
| 组成 | 基类 | 职责 | 源码位置 |
|---|---|---|---|
| Action | Action | 定义工具的输入参数(LLM 提供什么) | schema.py |
| Observation | Observation | 定义工具的返回结果(LLM 看到什么) | schema.py |
| Executor | ToolExecutor | 工具的实际执行逻辑 | tool.py |
| ToolDefinition | ToolDefinition | 把上面三者装配成一个完整工具 | tool.py |
注册中心在 registry.py 中,register_tool()负责把工具类按名字登记到全局目录,供Tool(name=...)按名解析。
二、第一步:定义 Action 与 Observation(工具的输入输出)
Action和Observation都是 Pydantic 模型,字段上可以直接写Field(description=...)——这些描述会原样进入 LLM 的工具提示词,写得越清楚,LLM 调用越准确💡。
以官方示例 02_custom_tools.py 中的 grep 工具为例:
class GrepAction(Action): pattern: str = Field(description="Regex to search for") path: str = Field(default=".", description="Directory to search") include: str | None = Field(default=None, description="Optional glob (e.g. '*.py')") class GrepObservation(Observation): matches: list[str] = Field(default_factory=list) files: list[str] = Field(default_factory=list) count: int = 0一个实用技巧:为 Observation 重写to_llm_content属性,把原始数据整理成 LLM 友好的精简文本(比如只返回前 10 条匹配),既省 token 又提高可读性。
三、第二步:实现 ToolExecutor(核心逻辑)
ToolExecutor定义了__call__(action, conversation) -> Observation接口(见 tool.py)。它接收 Action,执行真实工作,返回 Observation:
class GrepExecutor(ToolExecutor[GrepAction, GrepObservation]): def __call__(self, action: GrepAction, conversation=None) -> GrepObservation: cmd = f"grep -rHnE {pat} {root_q} | head -100" result = self.terminal(TerminalAction(command=cmd)) # 解析输出,组装成 GrepObservation 返回 return GrepObservation(matches=matches, files=files, count=len(matches))如果工具需要持有资源(如终端连接、数据库句柄),可以在__init__中初始化,并覆写close()做清理。
四、第三步:编写 ToolDefinition 并注册
ToolDefinition必须实现一个类方法create(cls, conv_state, **params),它负责创建 Executor 并返回工具实例列表。conv_state里可以拿到当前工作目录(conv_state.workspace.working_dir)等上下文:
class GrepTool(ToolDefinition[GrepAction, GrepObservation]): @classmethod def create(cls, conv_state, terminal_executor=None) -> Sequence[ToolDefinition]: if terminal_executor is None: terminal_executor = TerminalExecutor( working_dir=conv_state.workspace.working_dir ) return [ cls( description=_GREP_DESCRIPTION, # 给 LLM 看的工具说明 action_type=GrepAction, observation_type=GrepObservation, executor=GrepExecutor(terminal_executor), ) ] # 注册:注册后即可通过名字使用 register_tool("GrepTool", GrepTool)两个细节值得注意:
- 工具名
name会由类名自动生成(GrepTool→grep),也可以在注册时显式指定; description是 LLM 唯一看到的"说明书",建议说明何时该用这个工具、参数如何配合,完整写法可参考 02_custom_tools.py 和内置 glob 工具 definition.py。
五、第四步:把工具交给 Agent 运行
注册完成后,只需用Tool(name=...)引用即可(见 registry.py 的解析逻辑):
tools = [ Tool(name=FileEditorTool.name), Tool(name=BashAndGrepToolSet.name), # 你的自定义工具 ] agent = Agent(llm=llm, tools=tools) conversation = Conversation(agent=agent, workspace=cwd) conversation.send_message("用 grep 工具找出所有包含 'class' 的 Python 文件") conversation.run()一个进阶技巧:多个工具可以共享同一个 Executor(例如上例中 terminal 和 grep 共享一个终端会话),只需把它们打包成一个 ToolDefinition 在create()中一并返回即可。
六、进阶:在远程 Agent Server 中使用自定义工具
如果你的 Agent 跑在远程沙箱(Agent Server)里,自定义工具必须打包进服务端环境。官方示例 06_custom_tool/ 演示了完整方案:
- 把工具代码放进
custom_tools/目录(如 log_data.py,一个把结构化数据写入 JSON 文件的LogDataTool); - 在 Dockerfile 中拷贝该目录并设置
OH_EXTRA_PYTHON_PATH环境变量; - 创建会话时,SDK 会自动收集客户端注册表的工具模块名发送给服务端,触发动态注册,工具随即可用。
详细步骤见该示例的 README.md,里面附了一份「从零写一个自定义工具」的完整模板代码。
七、小结与参考资料
回顾一下为 Software Agent SDK 编写自定义工具的 4 步法 ✅:
- 定义
Action(输入)与Observation(输出),写好description; - 实现
ToolExecutor,完成核心执行逻辑; - 编写
ToolDefinition.create()装配工具,并调用register_tool()注册; - 用
Tool(name=...)挂到 Agent 上,启动 Conversation 即可。
📚 继续深入可阅读:
- 自定义工具完整示例:examples/01_standalone_sdk/02_custom_tools.py
- 内置工具实现参考(可直接"抄作业"):openhands-tools/openhands/tools/
- 工具注册机制源码:openhands-sdk/openhands/sdk/tool/registry.py
- 远程服务端自定义工具:examples/02_remote_agent_server/06_custom_tool/
- 仓库总览与快速上手:README.md
【免费下载链接】software-agent-sdk
A clean, modular SDK for building AI agents with OpenHands V1.
相关推荐
如何为Espruino编写自定义JavaScript库:从入门到精通的完整指南
如何为Espruino编写自定义JavaScript库:从入门到精通的完整指南 Espruino是一款轻量级JavaScript解释器,专为嵌入式设备设计,让开
编译器/解释器物联网claude-agent-sdk-python 自定义 Agent 完整指南:从 Markdown 文件到 AgentDefinition 编程式定义
claude agent sdk python 自定义 Agent 完整指南:从 Markdown 文件到 AgentDefinition 编程式定义 本指南以
人工智能AI Agent工具调用MCP Clients大模型如何为Superpowers编写自定义技能:从创意到发布的完整流程
如何为Superpowers编写自定义技能:从创意到发布的完整流程 Superpowers技能库为Claude Code提供了强大的扩展能力,让AI能够掌握各种
AI 技能AI 插件开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考