1. Introducción
Las tools (herramientas) son funciones personalizadas que el agente de IA puede ejecutar durante una conversación. OpenCode (y la mayoría de los agentes) traen de serie ciertas herramientas básicas integradas:
read: Lee un fichero específicowrite: Escribe un fichero específicobash: Ejecuta un comando específico de terminalgrep: Filtra o busca en el contenido de uno o varios ficheros
Sin embargo, a veces necesitas algo más específico y con estas tools te quedas corto.
No confundas las tools con los MCP servers. Los MCP generalmente son servidores externos que se conectan al agente, mientras que las tools son comandos que se ejecutan desde nuestro equipo.
2. ¿Por qué son importantes las tools?
Una tool es un script (TypeScript, JavaScript o cualquier otro lenguaje). La importancia radica en que el agente decide por sí mismo cuándo usar cada tool según la tarea que le pidas.
¿Cuándo interesa crear una tool? Es muy útil cuando tienes alguno de estos casos:
| Caso | Ejemplo |
|---|---|
| Optimizar contexto | Leer sólo partes de un fichero sin cargar todo el contenido |
| Validar datos | Comprobar que un JSON cumple un esquema antes de procesarlo |
| Transformar información | Convertir formatos (YAML a JSON, CSV a tablas, etc.) |
| Automatizar tareas repetitivas | Generar código boilerplate, crear estructuras de carpetas |
| Integrar servicios externos | Consultar APIs, bases de datos, sistemas de archivos especiales |
| Acceder a recursos restringidos | Leer ficheros .env, acceder a configuraciones del sistema |
3. Nuestra primera tool
Imagina que tienes muchos ficheros frontmatter (Son ficheros markdown con cabeceras YAML). Necesitas que el agente conozca esos metadatos sin cargar el contenido completo al contexto. Una tool como esta resuelve exactamente ese problema: lee únicamente la cabecera YAML y la devuelve como JSON, sin leer todo el fichero, ni añadirlo al contexto del agente y por lo tanto impide que esa información llegue hasta el modelo LLM.
Importante: Si usas
@en OpenCode para indicar un fichero, ten en cuenta que el agente ejecuta unREADdel fichero completo previamente.
Las tools en OpenCode se definen como ficheros TypeScript o JavaScript. Pueden estar en:
- Local del proyecto: En la ruta
.opencode/tools/ - Global: En la carpeta del sistema
~/.config/opencode/tools/
Estructura básica
Una tool se crea usando el helper tool() de @opencode-ai/plugin, en un fichero en una de las rutas mencionadas anteriormente:
import { tool } from "@opencode-ai/plugin";
export default tool({
description: "Descripción de lo que hace la tool",
args: {
parametro: tool.schema.string().describe("Descripción del parámetro"),
},
async execute(args, context) {
// Lógica de la tool
return "resultado";
},
});
4. Creando una tool en OpenCode
Sabiendo esto, vamos a crear nuestra primera tool de ejemplo: fmjson: la tool que mencionamos antes que lee únicamente la cabecera YAML de un fichero Markdown, sin meter el resto del contenido en el contexto del agente:
import { tool } from "@opencode-ai/plugin";
import { readFile } from "node:fs/promises";
import path from "node:path";
const FRONTMATTER_REGEX = /^---\s*\r?\n([\s\S]*?)\r?\n---\s*(?:\r?\n|$)/;
export default tool({
description: "Lee únicamente la cabecera YAML de un fichero Markdown " +
"y la devuelve como JSON. El contenido del Markdown posterior a la " +
"cabecera nunca se devuelve al modelo.",
args: {
file: tool.schema
.string()
.describe("Ruta relativa al fichero Markdown (.md)"),
},
async execute(args, context) {
const filePath = path.resolve(context.worktree, args.file);
if (!filePath.toLowerCase().endsWith(".md")) {
throw new Error("fmjson solo acepta ficheros .md");
}
const content = await readFile(filePath, "utf8");
const match = content.match(FRONTMATTER_REGEX);
if (!match) {
throw new Error(`La cabecera YAML de "${args.file}" no es válida`);
}
const frontmatter = match[1];
const yaml = await import("yaml");
const data = yaml.parse(frontmatter);
return JSON.stringify(data, null, 2);
},
});
Ten en cuenta que en el fichero anterior utilizamos la dependencia
yaml, por lo que debes instalar el paquete desde tu proyecto o desde la ruta global~/.config/opencode/con unpnpm add yaml.
Atento a los detalles de la tool:
| Parte | Descripción |
|---|---|
description |
Texto que el agente lee para decidir cuándo usar la tool. Debe ser clara y descriptiva |
args |
Objeto con los parámetros que acepta. Usa tool.schema (Zod) para definir tipos |
execute(args, context) |
Función que se ejecuta. args contiene los parámetros, context información de la sesión |
context.worktree |
Ruta raíz del proyecto Git. Úsala para resolver rutas relativas |
Múltiples tools en un fichero
Si necesitas varias tools relacionadas, puedes exportar varias en un solo fichero. Cada export se convierte en una tool separada con el nombre <fichero>_<nombre>. Por ejemplo, si creamos el fichero md.js:
import { tool } from "@opencode-ai/plugin"
export const read = tool({
description: "Lee el frontmatter de un fichero",
args: { file: tool.schema.string().describe("Ruta al fichero") },
async execute(args) { /* ... */ },
});
export const write = tool({
description: "Escribe el frontmatter de un fichero",
args: {
file: tool.schema.string().describe("Ruta al fichero"),
data: tool.schema.string().describe("Datos en JSON"),
},
async execute(args) { /* ... */ },
});
Esto crea dos tools diferentes con el nombre md_read y md_write.
5. Instalando la tool en OpenCode
Como ya mencionamos, para utilizar la tool, tenemos que crear la carpeta .opencode/tools/ en nuestro proyecto (o usar ~/.config/opencode/tools/ para tools globales) y colocar el fichero fmjson.js o fmjson.ts ahí.
Una vez hecho, ten en cuenta que las tools se cargan al iniciar OpenCode. Si ya tenías una sesión abierta, tendrás que cerrarla y volverla a abrir.
Por último, el agente ahora tiene disponible la tool fmjson. Simplemente pídele que la use:
Lee el frontmatter de src/data/file.md
El agente ejecutará fmjson automáticamente y devolverá únicamente la cabecera YAML en formato JSON:
{
"title": "Título del frontmatter",
"description": "Descripción del fichero frontmatter",
"logo": "icon.svg",
"version": 1.2
}
6. Añadir contexto al AGENTS o a skills
En tools muy sencillas puede que no haga falta (recuerda ser descriptivo en la descripción de la tool), pero si la tool es compleja o quieres dar contexto para que el agente sepa cuándo y cómo usar tu tool, es recomendable documentarla en el AGENTS.md (o mejor aún, en un skill).
En AGENTS.md
Añade una sección en tu AGENTS.md:
## Tools personalizadas
- Utiliza `fmjson` cuando quieras leer YAML de ficheros frontmatter (markdown) sin cargar todo su contenido o cuando se trata de grandes colecciones de archivos. Ejemplo: ``fmjson file="src/data/document.md"`
En un skill
Crea un skill en ~/.config/opencode/skills/frontmatter/SKILL.md:
---
description: "Herramienta para leer frontmatter de ficheros Markdown"
---
# fmjson
Herramienta para leer únicamente la cabecera YAML (frontmatter) de ficheros Markdown. Devuelve un JSON con los campos del frontmatter.
## Cuándo usar
- Cuando necesites consultar metadatos de un fichero `.md`
- Cuando quieras saber el título, descripción u otros campos
- **Nunca** uses `@`, ya que carga todo el contenido al contexto
- Ejemplo: `fmjson file="src/data/document.md"`

