--- title: Custom Tools description: Create tools the LLM can call in OpenCode. --- custom tool은 대화 중 LLM이 호출할 수 있도록 사용자가 직접 만든 함수입니다. `read`, `write`, `bash` 같은 OpenCode의 [built-in tools](/docs/tools)와 함께 동작합니다. --- ## 도구 만들기 tool은 **TypeScript** 또는 **JavaScript** 파일로 정의합니다. 다만 tool 정의에서 호출하는 스크립트는 **어떤 언어든** 사용할 수 있습니다. 즉, TypeScript/JavaScript는 tool 정의 자체에만 필요합니다. --- ### 위치 tool은 다음 위치에 둘 수 있습니다. - 프로젝트의 `.opencode/tools/` 디렉토리(로컬) - `~/.config/opencode/tools/` 디렉토리(전역) --- ### 구조 tool을 가장 쉽게 만드는 방법은 타입 안정성과 validation을 제공하는 `tool()` helper를 사용하는 것입니다. ```ts title=".opencode/tools/database.ts" {1} 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) { // Your database logic here return `Executed query: ${args.query}` }, }) ``` **파일 이름**이 **tool 이름**이 됩니다. 위 예시는 `database` tool을 생성합니다. --- #### 파일 하나에 여러 tool 정의 하나의 파일에서 여러 tool을 export할 수도 있습니다. 각 export는 **별도의 tool**이 되며 이름은 **`_`** 형식을 사용합니다. ```ts title=".opencode/tools/math.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` 두 tool이 생성됩니다. --- #### 기본 도구와 이름 충돌 커스텀 도구는 도구 이름으로 식별됩니다. 커스텀 도구가 기본 도구와 같은 이름을 사용하면 커스텀 도구가 우선순위를 갖습니다. 예를 들어, 이 파일은 기본 `bash` 도구를 대체합니다: ```ts title=".opencode/tools/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}` }, }) ``` :::note 의도적으로 기본 도구를 대체하려는 경우가 아니라면 고유한 이름을 사용하는 것이 좋습니다. 도구를 오버라이드하지 않고 비활성화만 하려면 [permissions](/docs/permissions)를 사용하세요. ::: --- ### 인자 인자 타입은 `tool.schema`로 정의할 수 있습니다. `tool.schema`는 [Zod](https://zod.dev) 기반입니다. ```ts "tool.schema" args: { query: tool.schema.string().describe("SQL query to execute") } ``` [Zod](https://zod.dev)를 직접 import해서 일반 객체를 반환하는 방식도 사용할 수 있습니다. ```ts {6} import { z } from "zod" export default { description: "Tool description", args: { param: z.string().describe("Parameter description"), }, async execute(args, context) { // Tool implementation return "result" }, } ``` --- ### Context tool은 현재 세션의 context 정보를 전달받습니다. ```ts title=".opencode/tools/project.ts" {8} import { tool } from "@opencode-ai/plugin" export default tool({ description: "Get project information", args: {}, async execute(args, context) { // Access context information const { agent, sessionID, messageID, directory, worktree } = context return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}` }, }) ``` 세션 작업 디렉토리는 `context.directory`를 사용하세요. git worktree 루트는 `context.worktree`를 사용하세요. --- ## 예시 ### Python으로 tool 작성 tool은 원하는 언어로 작성할 수 있습니다. 아래는 Python으로 두 숫자를 더하는 예시입니다. 먼저 Python 스크립트로 tool을 만듭니다. ```python title=".opencode/tools/add.py" import sys a = int(sys.argv[1]) b = int(sys.argv[2]) print(a + b) ``` 그다음 이 스크립트를 호출하는 tool 정의를 만듭니다. ```ts title=".opencode/tools/python-add.ts" {10} 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() }, }) ``` 여기서는 Python 스크립트를 실행하기 위해 [`Bun.$`](https://bun.com/docs/runtime/shell) 유틸리티를 사용합니다.