opencode / packages /web /src /content /docs /ko /custom-tools.mdx
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
0dbc9de verified
Raw
History Blame Contribute Delete
5.37 kB
---
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**์ด ๋˜๋ฉฐ ์ด๋ฆ„์€ **`<filename>_<exportname>`** ํ˜•์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
```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) ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.