Herramientas
Un módulo de herramientas se ejecuta en cada entorno de agente. beeuni.yaml enumera las herramientas de Beeuni y las herramientas propias del proyecto, y la lista de herramientas de cada agente determina quién puede usarlas.
Una herramienta es una función que el modelo llama durante un turno. Una sesión tiene tres tipos, en ambos arneses, harness estándar y harness experimental:
| Tipo | Nombres | Implementado por |
|---|---|---|
| Herramientas del arnés | bash, read, write, edit, glob, grep, task, question, … |
El arnés. |
| Herramientas de Beeuni | web_search, image_search, scrape_webpage, memory, show |
Beeuni. beeuni.yaml enumera cada una como <name>: beeuni:<name>. Si un proyecto no tiene la clave tools:, obtiene las cinco. |
| Herramientas del proyecto | Cualquier nombre que declares | Tu proyecto: un módulo, declarado bajo tools: en beeuni.yaml. |
Las herramientas de Beeuni y las del proyecto son independientes del arnés. El daemon del entorno aislado carga un módulo por herramienta y lo ejecuta en cualquiera de los dos arneses, con el mismo nombre, argumentos y resultado. harness experimental llama al módulo en el proceso del daemon. harness estándar lo llama mediante un complemento que escribe el daemon y que reenvía cada llamada al daemon. Un módulo nunca importa un paquete de arnés.
Herramientas de Beeuni en beeuni.yaml
Un proyecto nuevo enumera las cinco herramientas de Beeuni bajo tools::
tools:
web_search: beeuni:web_search # maintained by Beeuni, updated automatically
image_search: beeuni:image_search
scrape_webpage: beeuni:scrape_webpage
memory: beeuni:memory
show: beeuni:show
# lookup_order: tools/lookup_order.ts # your own tool: a module in your repo
beeuni:<name> significa: la herramienta que mantiene Beeuni. Una corrección se aplica a todos los proyectos que la enumeran, sin que estos tengan que cambiar nada.
Qué herramientas de Beeuni obtiene una sesión
beeuni.yaml |
La sesión obtiene |
|---|---|
No hay clave tools:, ni en el archivo raíz ni en ningún archivo importado |
Las cinco herramientas de Beeuni. Un proyecto creado antes de que existiera esta lista las conserva todas. |
Hay una clave tools:, aunque esté vacía (tools: {}, o tools: con todas las líneas eliminadas) |
Solo las herramientas de Beeuni que enumere, como beeuni:<name> o como un módulo que reemplace la herramienta. |
En ambos casos se cargan las herramientas propias del proyecto.
Consultar qué obtiene una sesión
beeuni tools ls lee beeuni.yaml y sus importaciones, e imprime cada herramienta que obtiene una sesión y, después, las herramientas de Beeuni que el proyecto quitó:
$ beeuni tools ls
NAME KIND SOURCE
web_search beeuni (overridden) tools/web_search.ts
scrape_webpage beeuni beeuni:scrape_webpage
memory beeuni beeuni:memory
show beeuni beeuni:show
lookup_order project tools/lookup_order.ts
Removed Beeuni tools: image_search
Add `<name>: beeuni:<name>` under `tools:` to get one back.
| Tipo | Significado |
|---|---|
beeuni |
Una herramienta de Beeuni, enumerada como beeuni:<name> (o todas, si no hay clave tools:). |
beeuni (overridden) |
Un nombre de herramienta de Beeuni con una ruta de módulo: se ejecuta el módulo del proyecto en su lugar. |
project |
Una herramienta propia del proyecto. |
beeuni tools ls --json imprime { manifest, tools_key, tools: [{ name, kind, source }], removed }.
Quitar una herramienta de Beeuni
Elimina su línea bajo tools:. Todos los agentes del proyecto pierden la herramienta, en ambos arneses y en todas las sesiones que comiencen después de que se integre la solicitud de cambio. Para conservar una herramienta para un solo agente, usa agents.<name>.tools.
En una sesión de un proyecto que quitó una herramienta:
- harness estándar no ofrece la herramienta al modelo.
- harness experimental no ofrece la herramienta. Si se la llama, falla con
Tool show not found(parashow). - El daemon responde
POST /beeuni/tools/<name>con404yno tool named <name> is loaded. - Una habilidad que mencione la herramienta se sigue cargando. Por ejemplo,
beeuni-memorymencionamemory. El modelo lee la habilidad, no encuentra esa herramienta y usa otras: si no tienememory, lee y edita los archivos dememory/con las herramientas de archivos.
Cambiar una herramienta de Beeuni: copiarla al proyecto
beeuni tools eject <name> crea una copia propia de una herramienta de Beeuni en el proyecto:
$ beeuni tools eject web_search
✓ Ejected web_search
wrote tools/web_search.ts (the Beeuni source, now the project's to change)
set beeuni.yaml: tools.web_search: tools/web_search.ts
Next:
1. Edit tools/web_search.ts. Keep the default export: { description, parameters, execute(args, context) }.
2. beeuni validate
3. git add tools/web_search.ts beeuni.yaml && git commit -m "Own the web_search tool"
4. Open a change request: git push origin HEAD && beeuni cr open --title "Own the web_search tool"
Sessions load the copy after the change request merges.
- Escribe el código fuente de Beeuni —los mismos bytes que ejecuta el entorno aislado— en
tools/<name>.ts. El archivo solo importa módulosnode:*y leeBEEUNI_API_URL,BEEUNI_TOKENy las claves del proveedor desdecontext.env, por lo que funciona tal cual. - Establece
<name>: tools/<name>.tsenbeeuni.yaml, en el archivo que declara la entrada (el archivo raíz o uno importado). Conserva todas las demás líneas y comentarios. La línea modificada termina en# ejected from beeuni:<name>. - Si no hay una clave
tools:, la crea y enumera las otras cuatro herramientas de Beeuni comobeeuni:<name>, de modo que la copia no quita ninguna. - No continúa si existe
tools/<name>.tso si la herramienta ya apunta a otro módulo.--forcesobrescribe. - No continúa si el nombre no corresponde a una herramienta de Beeuni.
La copia es tuya. Beeuni ya no la actualiza. Para volver a la herramienta mantenida, cambia la línea a <name>: beeuni:<name> y elimina el archivo.
Reemplazar sin copiar
Un nombre de herramienta de Beeuni con una ruta de módulo reemplaza la herramienta de Beeuni en todos los arneses:
tools:
web_search: integrations/search/web_search.ts
Vistas de la interfaz web
La interfaz web tiene una vista para cada herramienta de Beeuni, seleccionada por el nombre de la herramienta. Las vistas show y memory leen los argumentos de la llamada (type, path, url,
content, items; command, path). Las vistas web_search, image_search y
scrape_webpage leen el JSON de salida. Una copia modificada que conserve el nombre debe mantener esos argumentos y esa estructura de salida; de lo contrario, la interfaz muestra la salida sin procesar.
Validación
beeuni validate comprueba la lista:
<name>enbeeuni:<name>debe ser una herramienta de Beeuni, y la clave debe coincidir con ella.web_search: beeuni:image_searches un error:must be `beeuni:web_search` (the Beeuni tool) or a repo-relative path to a .ts or .js module (e.g. `tools/web_search.ts`) that replaces it.- Una clave
tools:que no enumere ninguna herramienta de Beeuni genera una advertencia:Sessions of this project get no Beeuni tool (web_search, image_search, scrape_webpage, memory, show). Add `<name>: beeuni:<name>` to keep one.Esto detecta si un proyecto añade su primera herramienta propia y, por accidente, elimina las cinco de Beeuni. - Si
toolsde un agente incluye una herramienta de Beeuni que el proyecto no carga, se genera una advertencia:"show" is a Beeuni tool this project does not load: add `show: beeuni:show` under the top-level `tools`, or remove it here.
La referencia del manifiesto contiene todas las reglas.
Escribir una herramienta del proyecto
// tools/lookup_order.ts
export default {
description: 'Look up an order by id. Returns its status and carrier.',
parameters: {
type: 'object',
properties: {
id: { type: 'string', description: 'The order id, e.g. "A-1042"' },
include_items: { type: 'boolean', description: 'Also list the items' },
},
required: ['id'],
},
async execute(args, context) {
const response = await fetch(`https://orders.example.com/v1/orders/${args.id}`, {
headers: { authorization: `Bearer ${context.env.ORDERS_API_KEY}` },
signal: context.signal,
})
if (!response.ok) throw new Error(`orders API answered ${response.status}`)
return await response.json()
},
}
# beeuni.yaml
tools:
web_search: beeuni:web_search
# … the other Beeuni tools you keep
lookup_order: tools/lookup_order.ts
La exportación predeterminada es un objeto simple:
| Campo | Regla |
|---|---|
description |
Cadena no vacía. El modelo la lee para decidir cuándo llamar a la herramienta. |
parameters |
Esquema JSON de los argumentos, type: 'object'. El modelo lo recibe tal cual, así que enumera los argumentos obligatorios en required. Beeuni no valida los argumentos con este esquema. |
execute(args, context) |
Devuelve una cadena o cualquier valor JSON (enviado como JSON con sangría). Puede ser async. Si se lanza un error, este será el error de la herramienta y el modelo leerá su mensaje. |
context contiene:
| Campo | Qué es |
|---|---|
sessionId |
La sesión de Beeuni a la que pertenece la llamada. |
agent |
El agente que hizo la llamada. |
directory |
La copia de trabajo del proyecto, /workspace. Resuelve las rutas relativas con respecto a ella. |
env |
El entorno del equipo y los secretos que recibe este agente, tal como están ahora. Lee un secreto como context.env.NAME: un secreto modificado después del arranque del equipo está en context.env, no en process.env. |
signal |
Un AbortSignal que aborta cuando el usuario detiene el turno. Pásalo a fetch. |
- Tamaño de salida. Una salida de más de 50 KB o 2.000 líneas se guarda completa en un archivo del directorio temporal del sandbox. El modelo recibe el inicio, el tamaño y la ruta del archivo. Devuelve lo que el modelo necesita, no un volcado sin procesar.
- Errores. Un error lanzado termina la llamada y el modelo lee el mensaje de error. Lanza un mensaje que indique qué hay que cambiar.
- Importaciones. Un módulo puede importar módulos
node:*, API de Bun y archivos relativos. Un paquete se resuelve desde unnode_modulesjunto al módulo o en un directorio superior. El sandbox no instala ningún paquete para una herramienta, y una versión de configuración solo contiene los archivos que Git rastrea. Usafetchpara las API HTTP. TypeScript se ejecuta sin un paso de compilación. - Fallos. Si un módulo no se carga (falta un archivo, no hay exportación predeterminada, un
parametersque no es un esquema de objeto, un error durante la importación o un paquete que no se resuelve), se omite y las demás herramientas se siguen cargando. El daemon registra[tools] project tools that did not loadcon el motivo de cada herramienta.
parameters con zod
zod 4 genera el mismo esquema JSON:
import { z } from 'zod'
export default {
description: 'Look up an order by id.',
parameters: z.toJSONSchema(z.object({ id: z.string().describe('The order id') })),
async execute(args) {
return `order ${args.id}: shipped`
},
}
Este módulo solo se carga cuando zod se resuelve desde un node_modules en el checkout que ejecuta la sesión. De lo contrario, falla con Cannot find package 'zod'.
Para escribir el esquema con zod y distribuir un esquema JSON sin formato, imprímelo una vez y pega el resultado en parameters:
bun -e "import { z } from 'zod'; console.log(JSON.stringify(z.toJSONSchema(z.object({ id: z.string() })), null, 2))"
Ejemplo: llamar a una API HTTP con un secreto del proyecto
Guarda la clave como secreto del proyecto. El comando lee el valor desde la entrada estándar:
beeuni secrets set WEATHER_API_KEY=-
Concede acceso al secreto a los agentes que llaman a la herramienta. El agente beeuni del starter tiene secrets: all. Un agente con alcance limitado lo indica así: secrets: [WEATHER_API_KEY].
Escribe el módulo:
// tools/weather_now.ts
export default {
description: 'Current weather for a city: temperature in °C and conditions.',
parameters: {
type: 'object',
properties: { city: { type: 'string', description: 'City name, e.g. "Berlin"' } },
required: ['city'],
},
async execute(args, context) {
const key = context.env.WEATHER_API_KEY
if (!key) throw new Error('WEATHER_API_KEY is not set: run `beeuni secrets set WEATHER_API_KEY=-` and grant it to this agent.')
const url = `https://api.weather.example.com/v1/current?city=${encodeURIComponent(args.city)}`
const response = await fetch(url, { headers: { authorization: `Bearer ${key}` }, signal: context.signal })
if (!response.ok) throw new Error(`weather API answered ${response.status}: ${await response.text()}`)
const data = await response.json()
return { city: args.city, temperature_c: data.temp_c, conditions: data.conditions }
},
}
Decláralo:
tools:
# … the Beeuni tools you keep
weather_now: tools/weather_now.ts
Ejemplo: reemplazar web_search
beeuni tools eject web_search escribe tools/web_search.ts y establece web_search: tools/web_search.ts. Luego modifica el código. Por ejemplo, para conservar solo los resultados de un sitio, añade el sitio a cada consulta en execute, antes de la solicitud:
// tools/web_search.ts, inside execute()
const queries = String(args.query ?? '').split('|||').map((query) => query.trim()).filter(Boolean)
.map((query) => `site:docs.example.com ${query}`)
Conserva el nombre, los argumentos y el JSON de salida para que sigan funcionando las habilidades que usan web_search y la vista de la interfaz web.
Probar una herramienta
beeuni validate comprueba el nombre, la ruta, la ausencia de un archivo y los valores de beeuni:. beeuni tools ls muestra lo que recibe una sesión.
Después, confirma los cambios, haz push y abre una solicitud de cambio. Cuando se integre, inicia una sesión y solicita una llamada con argumentos reales:
beeuni sessions new --wait --prompt "Call the weather_now tool once with city Berlin and print its output."
Una herramienta que no se carga no se ofrece al modelo. Una herramienta que lanza un error responde con el mensaje de error. beeuni sessions log <id> imprime los mensajes de la sesión, con cada llamada a una herramienta y su estado.
Declarar herramientas
tools: asigna cada nombre de herramienta a su módulo, o un nombre de herramienta de Beeuni a beeuni:<name>. Tú eliges la carpeta del módulo.
tools:
web_search: beeuni:web_search
memory: beeuni:memory
lookup_order: tools/lookup_order.ts
crm_note: integrations/crm/note.ts
- Los nombres usan snake_case y no pueden superar los 64 caracteres:
^[a-z][a-z0-9_]{0,63}$. - Un nombre de herramienta del harness es un error. Para una herramienta de Beeuni, se indica
beeuni:<name>o la ruta del módulo; el módulo reemplaza la herramienta de Beeuni en todos los harnesses. - Las rutas son relativas al repositorio y terminan en
.ts,.js,.mts,.mjs,.ctso.cjs. - Los archivos indicados en
imports:pueden declarar herramientas. Si un nombre se declara en dos archivos, se produce un error. Una clavetools:en un archivo importado cuenta como clavetools:para la regla de selección.
La referencia del manifiesto contiene todas las reglas.
Quién puede usar cada herramienta
agents.<name>.tools decide qué herramientas ve el modelo de un agente. Incluye por igual herramientas del harness, de Beeuni y del proyecto.
agents:
beeuni:
tools: all # every tool (the default)
researcher:
tools: [read, grep, web_search, lookup_order] # only these
support:
tools:
exclude: [bash, write, edit] # every tool but these
greeter:
tools: none # no tool
| Valor | Herramientas disponibles para el agente |
|---|---|
Omitido o all |
Todas las herramientas. |
none |
Ninguna herramienta. |
| Una lista | Solo las herramientas incluidas en la lista. Una lista con * no es válida: all. |
{ exclude: [...] } |
Todas las herramientas, excepto las incluidas en la lista. |
{ bash: false, … } |
El formato anterior de mapa: false excluye una herramienta. |
toolsdecide la visibilidad. Las reglaspermissiondel agente siguen determinando si se permite, se solicita o se deniega una llamada. Una herramienta que no está en la lista se oculta al modelo y se deniega si este intenta llamarla.- Una lista de agente no puede añadir una herramienta de Beeuni que el proyecto no carga. Primero, inclúyela en el
tools:de nivel superior. - Un subagente iniciado con la herramienta
task: en harness experimental solo obtiene las herramientas permitidas tanto por su propia lista como por la lista del agente de la sesión. En harness estándar obtiene las herramientas de su propia lista: harness estándar aplica las reglas de cada agente solo a ese agente. Para evitar que un agente delegue, no incluyastasken su lista. - Las herramientas de Connector siguen
agents.<name>.connectors, no esta lista. beeuni validateadvierte si un nombre no corresponde a una herramienta del harness, de Beeuni o del proyecto, y si el proyecto no carga una herramienta de Beeuni. Un error tipográfico en una listaexcludehace que la herramienta real siga habilitada.
En harness estándar, bash también abarca las herramientas pty_* del complemento de terminal, y write, edit y apply_patch comparten un permiso: incluir una muestra las tres y excluir una las oculta todas. harness experimental tiene herramientas write y edit independientes.
Cuándo se aplica un cambio
Una sesión carga sus herramientas cuando se inicia el entorno de ejecución. Un cambio se aplica una vez integrada la solicitud de cambio: las sesiones nuevas lo cargan y, con las versiones de configuración, una sesión en curso lo carga en la siguiente convergencia. En harness experimental, los cambios en una herramienta del proyecto o en la lista de herramientas de Beeuni reinician el entorno de ejecución en el mismo lugar cuando no hay ningún turno en curso; la conversación continúa.
Herramientas en harnesses/opencode/tools/
harness estándar sigue cargando herramientas personalizadas desde su directorio de configuración. harness experimental no lo hace. Los proyectos creados antes de que hubiera herramientas alojadas incluyen copias de las herramientas de Beeuni allí (web_search.ts, memory.ts, …).
- En harness estándar, una herramienta de esa carpeta prevalece sobre la herramienta alojada con el mismo nombre, así que el proyecto conserva su copia hasta que se elimine. Elimina las copias de las herramientas de Beeuni: el daemon aloja las que indica
beeuni.yaml, en ambos harnesses. - Para que una herramienta de harness estándar funcione en ambos harnesses, muévela fuera de la carpeta, reemplaza
tool({ description, args, execute })por un objeto simple cuyoparameterssea un esquema JSON, lee los secretos desdecontext.envy declárala entools:.