# 04 — Custom Tools (自定义工具) > 源: > 适用: 在 `.opencode/tools/*.ts` 创建 LLM 可调用的工具 ## 位置 - 项目级: `.opencode/tools/.ts` (本仓库用) - 全局: `~/.config/opencode/tools/.ts` > 文件名**即工具名**。`database.ts` → `database` 工具。 ## 最小结构 (用 `tool()` 辅助) `.opencode/tools/database.ts`: ```ts 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}` }, }) ``` ## 参数 (Zod) `tool.schema` 即 Zod 命名导出: ```ts args: { query: tool.schema.string().describe("SQL query to execute"), limit: tool.schema.number().int().min(1).default(20).describe("Max rows"), filter: tool.schema.enum(["all", "active"]).describe("Status filter"), } ``` 或直接 import: ```ts import { z } from "zod" export default { description: "...", args: { param: z.string().describe("...") }, async execute(args, context) { ... } } ``` ## Context (工具能拿到的会话上下文) ```ts async execute(args, context) { const { agent, sessionID, messageID, directory, worktree } = context return JSON.stringify({ agent, sessionID, messageID, directory, worktree }) } ``` | 字段 | 含义 | |---|---| | `agent` | 当前代理名 | | `sessionID` | 会话 ID | | `messageID` | 消息 ID | | `directory` | 会话工作目录 | | `worktree` | git worktree 根 | ## 单文件多导出 `.opencode/tools/math.ts`: ```ts import { tool } from "@opencode-ai/plugin" export const add = tool({ description: "Add two numbers", args: { a: tool.schema.number().describe("First number"), b: tool.schema.number().describe("Second number"), }, async execute(args) { return args.a + args.b } }) export const multiply = tool({ description: "Multiply two numbers", args: { a: tool.schema.number().describe("First number"), b: tool.schema.number().describe("Second number"), }, async execute(args) { return args.a * args.b } }) ``` → 工具名 `math_add` / `math_multiply` (`_`)。 ## 与内置工具同名 → 覆盖 `.opencode/tools/bash.ts` 取代内置 `bash`: ```ts import { tool } from "@opencode-ai/plugin" export default tool({ description: "Restricted bash wrapper", args: { command: tool.schema.string() }, async execute(args) { return `blocked: ${args.command}` } }) ``` > 想禁用内置**不**覆盖,改用 `permission.bash: "deny"`。 ## 非 TS 实现 (Python 等) 工具定义用 TS,**实现**可调任意语言。 `add.py`: ```python import sys a = int(sys.argv[1]) b = int(sys.argv[2]) print(a + b) ``` `python-add.ts`: ```ts import { tool } from "@opencode-ai/plugin" import path from "path" export default tool({ description: "Add two numbers using Python", args: { a: tool.schema.number().describe("First number"), b: tool.schema.number().describe("Second 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() }, }) ``` ## 验证清单 1. 文件名 `*.ts` (不是 `.js`/`.mjs`,虽然支持)。 2. 默认导出用 `tool()` 或返回 `{ description, args, execute }` 对象。 3. Zod schema 全部字段都 `.describe()` (LLM 用作工具描述)。 4. 多导出文件名 `` + 导出名 `` 形成工具名 `_`。 5. **退出重启 opencode**。 6. 在 prompt 看 `` 是否列出新工具。 7. 调一次验证参数/返回/错误处理。