OpenCode 自定义工具
自定义工具(Custom Tools)允许你为 OpenCode 扩展能力,让 LLM 在对话过程中调用你定义的函数,从而实现数据库查询、脚本执行、API 调用等复杂操作。
这些工具会与内置工具(如 read、write、bash)协同工作,构建完整的自动化开发能力体系。
自定义工具是 OpenCode 的核心扩展能力,它让 LLM 从只会生成代码,升级为可以执行任务。
通过合理设计工具,你可以构建:
- 自动化开发流水线
- 智能代码助手
- AI 运维系统
- 企业内部 AI 工具平台
一、什么是自定义工具
自定义工具本质上是一个函数接口,LLM 可以在运行过程中主动调用它,并获取执行结果。
典型应用场景:
- 查询数据库(SQL / NoSQL)
- 调用内部 API
- 执行脚本(Python / Shell)
- 读取系统状态或环境信息
- 封装复杂业务逻辑
你可以理解为:让 AI 拥有执行能力的插件机制。
二、工具存放位置
OpenCode 会自动加载以下目录中的工具:
- 项目级:
.opencode/tools/ - 全局级:
~/.config/opencode/tools/
文件名即工具名称(非常关键)。
三、基础工具定义(推荐方式)
使用 tool() 辅助函数可以获得类型安全和参数校验能力。
import { tool } from "@opencode-ai/plugin"
export default tool({
description: "Query the project database",
args: {
query: tool.schema.string().describe("SQL query to execute"),
},
async execute(args) {
return `Executed query: ${args.query}`
},
})
说明:
description:工具描述,LLM 用于判断是否调用args:参数定义(基于 Zod)execute:实际执行逻辑
四、单文件多工具
一个文件可以导出多个工具,每个工具会自动命名为:
<文件名>_<导出名>
import { tool } from "@opencode-ai/plugin"
export const add = tool({
description: "Add two numbers",
args: {
a: tool.schema.number(),
b: tool.schema.number(),
},
async execute(args) {
return args.a + args.b
},
})
export const multiply = tool({
description: "Multiply two numbers",
args: {
a: tool.schema.number(),
b: tool.schema.number(),
},
async execute(args) {
return args.a * args.b
},
})
最终生成工具:
math_addmath_multiply
五、与内置工具冲突
如果你的工具名称与内置工具相同,会覆盖内置工具。
// 覆盖内置 bash 工具
export default tool({
description: "Restricted bash wrapper",
args: {
command: tool.schema.string(),
},
async execute(args) {
return `blocked: ${args.command}`
},
})
建议:
- 避免命名冲突
- 如果只是限制能力,优先使用
permission配置
六、参数定义(Zod)
参数使用 Zod Schema 定义,支持类型校验与描述:
args: {
query: tool.schema.string().describe("SQL query"),
limit: tool.schema.number().optional(),
}
也可以直接使用 Zod:
import { z } from "zod"
export default {
description: "Example tool",
args: {
name: z.string(),
},
async execute(args) {
return `Hello ${args.name}`
},
}
七、上下文(Context)
工具执行时会自动注入上下文信息:
export default tool({
description: "Get project info",
args: {},
async execute(args, context) {
const { agent, sessionID, directory, worktree } = context
return `Agent: ${agent}, Dir: ${directory}`
},
})<
可用字段:
agent:当前代理sessionID:会话 IDmessageID:消息 IDdirectory:当前工作目录worktree:Git 根目录
八、调用外部语言(Python 示例)
你可以用任何语言实现工具逻辑,例如 Python。
1、Python 脚本
# .opencode/tools/add.py import sys a = int(sys.argv[1]) b = int(sys.argv[2]) print(a + b)
2、工具封装
import { tool } from "@opencode-ai/plugin"
import path from "path"
export default tool({
description: "Add two numbers using Python",
args: {
a: tool.schema.number(),
b: tool.schema.number(),
},
async execute(args, context) {
const script = path.join(context.worktree, ".opencode/tools/add.py")
const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text()
return result.trim()
},
})
这种方式适合:
- 已有 Python 工具链
- 调用数据分析 / AI 模型
- 执行复杂计算任务
九、最佳实践
- 工具描述要清晰,帮助 LLM 正确选择
- 参数设计尽量简单明确
- 避免副作用(除非明确需要)
- 优先通过 permission 控制风险操作
- 工具应聚焦单一职责
点我分享笔记