ManzGPU

Orquestador de agentes

Hype-Generator 3000™: It's a game-changer

Aprende a crear un agente orquestador en OpenCode que decide qué hace cada subagente: guiar con modelo frontera, trabajo mecánico en local o con un modelo pequeño y barato.

1. Introducción

Esta guía va de una idea muy concreta: no pagues un modelo frontera por leer un fichero. Si le pides a un modelo potente que busque una función, renombre una variable y te devuelva el resultado, has gastado tokens de entrada y salida carísimos para hacer el trabajo más sencillo del mundo.

La realidad es que casi todo el trabajo de un agente es mecánico: leer, buscar, renombrar, formatear, listar. Y ese trabajo se puede hacer con modelos 100 veces más baratos o directamente en tu máquina, si utilizas modelos locales.

Para montar esto necesitas dos cosas que ya deberías tener:

📌 Esta guía está escrita para OpenCode V2. Usaremos permissions (en lugar de permission), usaremos acciones shell y subagent (y no bash ni task), y el campo tools ya no existe.

Para entender porque es útil seguir esta mecánica de trabajo para ahorrar costes, mira la siguiente tabla con la diferencia de precios por millón de tokens (entrada / salida) (puedes ver más de otros modelos o versiones en la sección Cloud):

ModeloEntradaSalidaUso previsto
openai/gpt-6-astra 10 $ 50 $ Diseño, arquitectura, decisiones
deepseek/deepseek-v4-flash 0,15 $ 0,6 $ Tareas mecánicas
openai/gpt-6-luna 0,1 $ 0,5 $ Tareas mecánicas

Entre el primero y el último hay una gran diferencia. Si el 80% de tus tokens acaba en el modelo barato, el coste y factura es muy diferente. Y si además parte de ese trabajo lo hace un modelo local, ese porcentaje no solo es barato: no sale de tu equipo (privacidad).

2. Qué es un orquestador

Un orquestador es un agente cuyo trabajo no es programar, sino dirigir y decidir. Es el agente principal de la sesión: recibe tu petición, la descompone, lanza a los subagentes adecuados y te devuelve un resultado.

Tú ──► Orquestador (modelo frontera)
          ├──► local   · llama.cpp · gratis y privado
          └──► barato · Luna / DeepSeek Flash · ~100x más barato

En OpenCode esto se apoya en dos mecanismos:

  • Agentes: Mediante un fichero .md puedes definir un agente. El frontmatter decide su modelo, sus permisos y su forma de trabajar; el cuerpo del fichero es su prompt de sistema.
  • Subagentes: Mediante la tool subagent el orquestador puede abrir una sesión hija. Cada subagente arranca con contexto limpio y su conversación nunca se mezcla con la del padre: el padre sólo recibe el resumen final.

Ese último punto es la clave económica de todo esto. Si un subagente lee 40 ficheros, esos 40 ficheros se pagan en su sesión, pero no vuelven a la tuya. Sin subagentes, cada turno del padre vuelve a pagar todo el historial. Por eso delegar no sólo abarata: reduce el contexto del modelo caro.

Resumen

Obviamente, puedes tener cuantos agentes quieras (por ejemplo, un modelo para tareas avanzadas o especializadas en un tema), pero vamos a establecer estos 3 agentes a modo de ejemplo:

AgenteModeloDónde correCuándo usarloCoste
orquestador Frontera (ej: gpt-6-astra) Nube Diseño, descomponer la tarea, decidir, responderte 💸 Alto
pequeño gpt-6-luna / deepseek-v4-flash Nube Renombrados, formateo, redacción simple, referencias 🟡 Barato
local GGUF en llama.cpp Tu máquina Leer, buscar, editar en masa, refactors mecánicos 🟢 Cero

⚠️ OJO: Un subagente sin model en su configuración hereda el modelo de la sesión padre. Fija siempre un model en cada subagente, o ciérralo con permisos subagent.

3. Crear un agente

En Opencode V2, los agentes se pueden crear en markdown, y guardar en uno de estos dos sitios:

  • Global: ~/.config/opencode/agents/<nombre>.md → disponible en todos
  • Por proyecto: .opencode/agents/<nombre>.md → sólo en ese proyecto

Si el fichero va en una subcarpeta, el nombre debe incluir la ruta. Es decir, si tienes el fichero .opencode/agents/team/reviewer.md, el nombre del modelo debe ser team/reviewer.

Sintaxis markdown

---
description: "Para qué sirve y cuándo debe usarse"
mode: subagent
model: openai/gpt-6-luna#low
---

El cuerpo del fichero es el prompt de sistema del agente.

En este primer ejemplo solo hemos usado los campos description, mode y model, pero tenemos más:

CampoValoresPara qué sirve
description Texto El criterio con lo único que lee el padre para decidir a quién llamar.
mode primary, subagent, all Con primary → cambiar en la TUI, subagent sesión hija.
model provider/modelo#variante El modelo que usa. Sin él, hereda el del padre
permissions Lista de reglas Qué puede hacer (y qué no)
steps Número Máx. pasos del modelo. En el último se quitan tools y se pide resumen
color Hex Color del agente en la interfaz TUI. Código hexadecimal
hidden true Lo esconde del listado y del catálogo de subagentes

4. El agente orquestador

Empecemos creando el agente orquestador. Vamos a ~/.config/opencode/agents/orquestador.md y escribimos lo siguiente:

---
description: "Coordina el trabajo y delega a otros modelos baratos/locales"
mode: primary
model: openai/gpt-6-astra#high
color: "#fff833"
permissions:
  - action: edit
    resource: "*"
    effect: deny
  - action: write
    resource: "*"
    effect: deny
  - action: subagent
    resource: "*"
    effect: deny
  - action: shell
    resource: "*"
    effect: deny
  - action: subagent
    resource: local
    effect: allow
  - action: subagent
    resource: barato
    effect: allow
---

Eres el orquestador del proyecto.

## Objetivo

Tu objetivo es entender el problema (sin hacer ninguna acción, salvo razonar) y crear un TODO de subtareas pequeñas y sencillas (divide y vencerás). No realices las tareas aunque sean sencillas y rápidas.

## Asignar subtareas

Cada una de esas subtareas, las asignarás y enrutarás a un subagente apropiado. Una vez asignadas, le enviarás la información necesaria para que el subagente asignado pueda resolver esa subtarea.

## Enrutado

Cada subtarea tendrá un grado de complejidad: nano (muy sencilla), small (sencilla), medium (normal), large (compleja).

- `local`: Si es `nano` o `small`, deriva a este subagente.
- `barato`: Si es `medium` o `large` deriva a este subagente.

## Reglas

- Nunca realices tareas tu mismo
- Antes de delegar, reduce la tarea a un objetivo verificable
- Nunca copies contenido de ficheros en el prompt: pásale rutas y deja que los lea
- Si dudas entre `local` y `barato`, elige `local`
- Si dudas entre delegar y hacerlo tú, delega: tu contexto es más caro
- Lanza en paralelo las tareas independientes (`background: true`)

## Ejecución

- Cada subagente devuelve un resumen corto. Si no basta, lanza una segunda pasada con una pregunta concreta en lugar de leer los ficheros tú
- Si una decisión es de arquitectura, pregunta al usuario mediante la tool `question` antes de lanzarla
- Al usuario le hablas tú: qué se ha hecho, qué has decidido y qué queda pendiente

Conviene tener bien claro lo siguiente:

  • 1️⃣ Los permisos se evalúan en orden y gana el último. Evitamos que el orquestador pueda crear subagentes, escribir o editar ficheros o ejecutar comandos. El objetivo del orquestador es sólo coordinar. Luego, damos permisos para crear subagentes local y barato. Añadir más si es necesario.
  • 2️⃣ mode: primary hace que sea el agente principal de la sesión, que es justo lo que queremos (el que habla contigo)
  • 3️⃣ El cuerpo es el prompt de sistema. Ahí van las reglas de enrutado. Cuanto más concreto sea, menos decisiones raras toma el modelo. Puedes cambiarlas para hacerlas menos o más estrictas.

Para que sea el agente por defecto al abrir una sesión, añádelo a tu opencode.jsonc:

{
  "$schema": "https://opencode.ai/config.json",
  "default_agent": "orquestador"
}

🛑 OJO: Si utilizas modelos gratuitos de Opencode para orquestar subagentes, te puede salir el mensaje Error: Opencode's free tier can only be used from within OpenCode. Para evitar saturación, no permiten abuso de subagentes con los planes gratuitos. Usa modelos de pago.

5. El agente local

Tener un modelo local nos permitirá realizar ciertas tareas sencillas o mecánicas mediante un modelo de IA en nuestro propio sistema. Aunque un modelo local no puede realizar tareas muy complejas igual de bien que un modelo frontera, con el hardware adecuado, es perfectamente capaz de hacer ciertas tareas reduciendo a coste cero.

Un modelo local sólo puede trabajar como subagente si sabe pedir tools. En llama.cpp eso lo habilita la plantilla de chat del modelo, que se usa con --jinja:

llama-server \
  -m Qwen3.6-35B-A3B-UD-IQ2_XXS.gguf \
  --alias qwen-local \
  --jinja \
  -fa on \
  --ctx-size 32768 \
  --host 0.0.0.0 --port 8080

Con esto levantamos un modelo local Qwen 3.6 35B/A3B, creando un alias qwen-local para llamarlo, usando un contexto de 32K, activando ciertas optimizaciones y permitiendo su acceso vía API.

⚠️ Cuantizar el KV cache -ctk q4_0 y -ctv q4_0 ahorra mucha VRAM pero puede degradar mucho la capacidad del modelo para llamar tools con agentes. Si tienes VRAM suficiente, evítalo.

Añadirlo en Opencode

OpenCode no sabe que existe un llama.cpp en tu sistema o red automáticamente, así que tenemos que configurarlo como un servidor compatible con la API de OpenAI:

{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "llamacpp": {
      "name": "llama.cpp",
      "package": "@opencode/ai/providers/openai-compatible",
      "settings": {
        "baseURL": "http://localhost:8080/v1",
        "apiKey": "llamacpp"
      },
      "models": {
        "qwen3.6-35b": {
          "modelID": "qwen-local",
          "name": "Qwen 3.6 35B (local)",
          "capabilities": {
            "tools": true,
            "input": ["text"],
            "output": ["text"]
          },
          "limit": {
            "context": 32768,
            "output": 8192
          }
        }
      }
    }
  }
}

Una vez hecho esto, hemos configurado Opencode para que sepa que tenemos un llama.cpp que provee ciertos modelos locales a través de http://localhost:8080/v1. Más abajo, definimos el modelo que vamos a utilizar y sus características. Con esto debería aparecer en el menú /models de selección de modelos.

Ahora que Opencode ya conoce nuestro modelo local, creamos el agente local:

Lo primero será crear un markdown similar al que creamos para el orquestador, pero con los datos del modelo local. Creamos ~/.config/opencode/agents/local.md:

---
description: "Trabajo sencillo y/o mecánico sobre los ficheros del proyecto con un modelo local (llama.cpp). Úsalo para leer, buscar y editar de forma masiva sin que nada salga de este equipo."
mode: subagent
model: llamacpp/qwen3.6-35b
color: "#ff8236"
steps: 40
permissions:
  - action: subagent
    resource: "*"
    effect: deny
  - action: webfetch
    resource: "*"
    effect: deny
  - action: websearch
    resource: "*"
    effect: deny
  - action: read
    resource: "*.env"
    effect: deny
  - action: edit
    resource: ".env"
    effect: deny
---

Eres un agente para tareas sencillas y trabajas en el equipo del usuario con un modelo local. Nada de lo que hagas sale de aquí.

## Cómo trabajas

- No hagas preguntas: ejecuta la tarea con lo que tengas y anota al final cualquier
  suposición que hayas tomado.
- Lee lo justo. Si te piden un resumen de 5 ficheros, no los pegues en tu respuesta.
- Prefiere `grep` y `glob` antes que `read` sobre ficheros enteros.
- Si un cambio es grande, hazlo en pasos pequeños y comprueba que el proyecto sigue
  compilando o pasando los tests que ya usara el proyecto.

## Qué devuelves

Un resumen de máximo 15 líneas:

- Qué has cambiado o encontrado, agrupado por fichero.
- Rutas y líneas concretas, no contenidos.
- Tests o comandos que has ejecutado y su resultado.
- Dudas o suposiciones que necesite que el padre decida.

Nunca devuelvas el contenido completo de un fichero. Debes consumir tu propio contexto y no el del padre.

Algunos puntos importantes:

  • 1️⃣ webfetch y websearch se prohiben: podrían usarse para enviar información hacia fuera. El modelo local no tiene por qué salir a internet, y así es imposible que lo haga aunque lo intente.
  • 2️⃣ .env se prohibe: los ficheros de credenciales no se leen ni se escriben.
  • 3️⃣ subagent prohibido: aunque la profundidad de anidamiento ya es 1 por defecto, indicarlo evita sorpresas si algún día subes ese valor.

6. El agente barato

Vamos ahora con el siguiente agente. El agente «barato» se encarga de tareas mecánicas que realizan tareas que no son demasiado críticas. Conviene usar un modelo pequeño en la nube, porque es más rápido y más fiable que tu modelo local, y sigue siendo bajo coste.

Lo primero, crear el ~/.config/opencode/agents/barato.md:

---
description: "Tareas mecánicas, poco críticas con un modelo pequeño y barato (Luna / DeepSeek Flash). Renombrados, formateo, redacción simple, buscar referencias, primera pasada de refactors.
mode: subagent
model: openai/gpt-6-luna#low
color: "#0c8c0c"
steps: 12
permissions:
  - action: subagent
    resource: "*"
    effect: deny
  - action: webfetch
    resource: "*"
    effect: deny
  - action: shell
    resource: "*"
    effect: ask
  - action: edit
    resource: "*"
    effect: ask
---

Eres un agente definido para realizar tareas mecánicas o sencillas.

## Qué haces

- Renombrar, mover y formatear siguiendo el estilo del proyecto.
- Corregir typos y redacción menor en comentarios o documentación.
- Localizar referencias y devolver rutas.
- Preparar el terreno: buscar, listar y proponer un primer cambio.

## Qué no haces

- No tomas decisiones de diseño.
- No refactorizas la arquitectura.
- Si la tarea es ambigua, eliges la interpretación más conservadora, la haces, y
  avisas de la suposición en el resumen.

## Cómo respondes

Máximo 10 líneas. Dices qué cambiaste y dónde, nada más. No explicas el porqué.

Algunas cosas que no he mencionado antes:

  • 1️⃣ El #variant define el esfuerzo: #low (o none a veces) baja el esfuerzo de razonamiento. Comprueba qué variantes expone tu modelo con /models.
  • 2️⃣ steps: 12. Indica el máximo de pasos a realizar. En el último paso, OpenCode quita tools y pide resumen, así evitas posibles bucles.
  • 3️⃣ edit: ask y shell: ask mecanismo de seguridad de un modelo «no demasiado inteligente»: te pregunta antes de tocar nada. Cuando te fíes de él, cambia esos ask por allow.

Si prefieres DeepSeek (u otro modelo económico), cambia la línea donde defines el campo model y listo. Por ejemplo: deepseek/deepseek-v4-flash#low.

7. Probar orquestación

Una vez llegado a este punto, abre OpenCode en un proyecto de prueba, selecciona el agente orquestador y lanza una petición para desarrollar algo que pueda orquestar. Al no tener permisos de hacer cambios, obligatoriamente delegará a otros subagentes:

  • 1️⃣ El orquestador decide (a sí mismo o con un question) y lanza local o barato con un prompt que sólo contiene rutas, no contenidos.
  • 2️⃣ Verás una llamada a la tool subagent con el nombre del agente y el modelo.
  • 3️⃣ El subagente trabaja en su sesión hija, con su contexto, y devuelve un resumen de 15 líneas.
  • 4️⃣ El orquestador lee ese resumen, decide si vale y te responde a ti.

Prueba también algunos detalles:

  • Prueba forzar agentes: usa el subagente local para esto o delega en el agente barato.
  • Tareas independientes en paralelo: pedir dos refactors a la vez hará que el orquestador lance dos subagentes en background.

⚠️ Intenta evitar @fichero.md en el prompt del padre. Eso adjunta el contenido del fichero a tu contexto y a la del orquestador: es exactamente el coste que estás intentando evitar. Pide «lee src/api/client.ts» y deja que lo lea el subagente.

7. Consejos y revisión

Para asegurarnos que todo está yendo bien y realmente estamos ahorrando en nuestro trabajo, puedes hacer lo siguiente:

opencode stats
  • Mira los tokens/sesión, coste estimado/modelo e historial de uso, para ver si está funcionando.
  • Con /copy puedes hacer transcripción de la sesión, útil si quieres revisar.
  • Para un análisis más fino de consumo, pnpx tokscale.

Señales de que el orquestador no está funcionando:

  • ⚠️ El coste total no baja: el orquestador hace la tarea él mismo. Refuerza el prompt de sistema.
  • ⚠️ El coste viene de un solo modelo: un subagente heredó el modelo del padre. Revisa model.
  • ⚠️ Las sesiones del padre son enormes: estás pegando contenidos en lugar de pasar rutas.