Un modelo frontera coordina, los baratos ejecutan
Notas de campo sobre una pipeline de agentes construida sobre Orca: dónde termina el control plane, qué políticas aporta la capa propia y por qué un Delivery sin ack parecía una notificación perdida.
Durante cuatro días, una combinación de un coordinador frontera y ejecutores baratos cerró seis épicas en dos proyectos reales: más de cuarenta tareas y una suite que creció de unos 1.100 tests a casi 2.000. El coste estimado que enseñaba el agente por tarea iba de $0,01 a $0,13.
La arquitectura separa dos responsabilidades: Orca es el control plane; la pipeline es un adaptador de políticas. Orca conserva la ejecución y su estado duradero. La capa propia decide qué puede tocar cada agente, qué pruebas debe superar y cuándo es seguro aceptar, reintentar o cerrar su trabajo.
Un incidente muestra por qué importa esa frontera. Dos subagentes terminaron casi a la
vez. El coordinador atendió al primero y el segundo pareció desaparecer. No se había
perdido ningún mensaje. Había un Delivery FIFO antiguo sin ack, y Orca estaba
reproduciendo correctamente ese lote mientras los avisos posteriores esperaban detrás.
La solución no necesita otro buzón: necesita respetar el contrato del que ya existe.
1. La frontera que hace útil a la pipeline
Orca ya sabe crear Runs, representar un DAG, despachar una Task, mantener threads duraderos, supervisar terminales y crear worktrees. Volver a implementar cualquiera de esas piezas exige sincronizar dos verdades. En la práctica acabas preguntándote si manda el Dispatch de Orca, el fichero de una guardia o el PID de un watcher.
La capa propia solo merece existir donde añade una decisión comprobable:
| Orca, control plane | Pipeline, policy adapter |
|---|---|
| Run, DAG, Task y Dispatch | perfil de proyecto y límite de concurrencia |
| Delivery FIFO y threads | resolución completa antes del ack |
| terminal y transcript | comando seguro del agente y confirmación de arranque |
| worktree y ciclo de vida | setup, raíces editables y cleanup seguro |
| outcome del worker | gates, QA y política de retry |
Esta frontera elimina mucho código. No hay daemon, broker, SQLite, spool NDJSON ni cola local. Tampoco hay un wrapper para cada comando de Orca: si el wrapper no puede imponer o verificar una política, sobra.
2. Las decisiones que sostienen el sistema
Cuatro decisiones hacen que esta capa propia merezca su sitio.
Worktrees reales. Cada worker tiene checkout, rama y terminal propios. No comparte índice, cachés de build ni servidor de desarrollo. Y el trabajo sobrevive a la sesión: si falla el proveedor, se reemplaza el proceso y se conserva el disco.
Specs completas. La Task de Orca contiene el contrato entero: objetivo, alcance,
criterios, rutas, casos y gates. No se mantiene una copia en .pipeline/specs/ ni se
despacha una frase que apunte a un fichero externo: eso crearía artefactos huérfanos y
specs ausentes tras una recuperación. La Task es la única copia, lo que además encaja
con una propiedad importante de Orca: el spec de una Task es inmutable.
Default-deny. OpenCode arranca con una base cerrada, una capa del stack y una overlay
del perfil. Un worker de web no puede tocar Electron; uno de seguridad puede editar dos
directorios; uno de QA solo escribe evidencia. Secretos, claves, .git/** y
.pipeline/** no se pueden reabrir desde una capa posterior.
Verificación independiente. El coordinador vuelve a ejecutar los gates y revisa el diff. No basta con que el worker diga «todo verde». En Lawyer, una tarea que crea rutas usa un perfil que añade build y el verificador de bundle. En BIA, tocar estilos globales añade CSS computado y Playwright: typecheck, lint y unit tests pasaron dos veces con la aplicación visualmente rota.
La elección del gate sale de lo que el cambio puede romper, no de una lista ceremonial.
3. El mensaje no se perdió: estaba detrás de un Delivery
El mailbox público de Orca tiene un contrato preciso. check devuelve el Delivery FIFO
más antiguo. Ese Delivery puede contener muchos mensajes y se reproduce idéntico hasta
que el coordinador confirma el lote entero con su deliveryId.
El bucle correcto es pequeño:
- Obtener el Delivery más antiguo.
- Procesar todos sus mensajes.
- Para cada
worker_done, validar Task, Dispatch y outcome; después reutilizar, retener o liberar el terminal. - Dejar una pregunta como
needs_inputen su thread; bloquear la Task ante una escalation. - Hacer
acksolo cuando cada decisión ya sea duradera en Orca. - Volver a comprobar sin espera hasta vaciar lo ya disponible.
Si el coordinador se cierra entre los pasos 3 y 5, Orca entrega el mismo lote al volver.
Por eso las acciones deben ser idempotentes: worker-release lo es, marcar una Task como
bloqueada lo es y una reutilización comprueba antes si la nueva Task ya tiene Dispatch.
La semántica importante es esta: worker_done no significa que el proceso haya
muerto. Completa Task y Dispatch, y deja el worker idle. Mandarle un mensaje al
Dispatch completado no crea un segundo intento. Hay que reutilizar explícitamente el
terminal con otra Task, retenerlo para depurar o liberarlo.
4. Notificación básica no es mailbox fiable
La versión 1.4.182 de Orca incluye el aviso básico al coordinador de
worker_done (#12988). Lo que todavía no
incluye es el retry que cubre carreras, reinicios y waiters obsoletos
(#14332), fusionado después de la
release 1.4.182.
La consecuencia no es construir otro buzón. Es tratar esa versión como degradada: el perfil puede declarar tres workers, pero el límite efectivo es uno. El paralelismo solo se fuerza de forma explícita por Run, y queda visible en el receipt.
Tampoco basta con decir «cualquier versión posterior estará arreglada». La pipeline
lleva una tabla exacta de compatibilidad. La primera release que incluya #14332 se añade
después de verificarla y superar un smoke real: dos workers terminan casi a la vez, el
coordinador no mira mientras trabajan, se comprueban Delivery, replay, ack y cleanup.
Un terminal coordinador mantiene un Run supervisado. Si quieres dos Runs simultáneos, necesitas dos coordinadores. Eso evita waiters que compiten por el mismo buzón.
5. La carrera de lanzamiento sigue siendo un workaround
El atajo de crear worktree, arrancar agente e inyectar la tarea en una sola llamada puede despachar antes de que un agente nuevo esté listo. La carrera sigue documentada en la issue #13488.
Mientras no exista una release verificada, la secuencia es deliberadamente aburrida:
- Crear el worktree sin agente.
- Ejecutar setup.
- Escribir la política de OpenCode.
- Lanzar el agente.
- Esperar
tui-idley despachar sobre ese terminal existente. - Confirmar un transcript real con
worker-read.
Leer la pantalla con grep, medir timestamps de silencio o enviar sondas al buzón
confundiría estados legítimos con fallos. La pipeline solo reintenta por algo observable:
dispatch no iniciado, outcome fallido, error de proveedor o gate fallido. El silencio,
por sí solo, no es un error.
6. OpenCode y Codex no ofrecen la misma garantía
OpenCode puede prevenir escrituras por ruta. Su política se compone como base + stack + overlay y se valida antes de arrancar. Una sustitución puede estrechar el mapa de edición, pero no borrar prohibiciones no negociables.
Codex tiene otra granularidad. Arranca con workspace-write, red desactivada y approvals
desactivados, siguiendo su
configuración oficial. Eso limita
el proceso al workspace, pero no equivale a permitir solo dos carpetas dentro del repo.
La garantía adicional es detectiva: antes de aceptar el resultado, la pipeline compara
todo el diff —commits, staged, unstaged y untracked— con las raíces del perfil.
No vender ambas cosas como equivalentes importa. Una barrera preventiva y un gate detectivo pueden producir el mismo rechazo final, pero tienen distinta exposición.
7. Recuperación sin autocuración imaginaria
«Autocurarse por silencio» parece seductor: si un worker lleva 210 segundos sin salida, leer la pantalla, clasificar y relanzar. En la práctica, un turno largo, un TUI que parte palabras y un coordinador ocupado producen falsos positivos.
La política de recuperación empieza por estados que Orca sí conoce:
- un Dispatch no arrancó;
- el outcome es
failedo el proveedor devolvió error; - un gate independiente falló;
- una Task quedó bloqueada por una escalation.
Tras fallos repetidos, el orden es: partir la Task, relanzar limpio en el mismo worktree y solo entonces escalar el modelo. Una sesión rota no obliga a tirar el código. Y un modelo más caro no arregla una tarea mal partida.
El cierre tampoco improvisa. Primero worker-release, que archiva el output y libera el
terminal exacto; luego worktree rm. Si hay cambios sin guardar, se niega. No silencia
errores ni baja a Git por detrás de Orca.
8. QA: estructura, píxeles y evidencia
Un ejecutor sin visión puede recorrer el árbol de accesibilidad, comprobar texto y estructura y producir capturas. Lo que no puede hacer es dictaminar peso visual, contraste o fidelidad. Ese veredicto pertenece a quien tenga ojos: el coordinador o el humano.
La separación funciona si el reporte enumera también lo que no pudo juzgar. En una tanda, un worker comprobó correctamente que una cuadrícula tenía cinco celdas y escaló que no podía saber si las pistas vacías parecían pintadas. La revisión visual encontró justo ese defecto.
Y la evidencia también se verifica. Una captura existe, pesa cientos de kilobytes y aun
así puede estar corrupta. Después de ver PNG cuya firma empezaba por efbfbd50 en vez de
89504e47, la firma pasó a ser un gate.
9. Qué costó de verdad
Datos observados entre el 8 y el 11 de agosto de 2026, no una tabla de precios del proveedor:
| Métrica | Observado |
|---|---|
| Épicas cerradas | 6 |
| Tasks procesadas | ~40 |
| Tests | ~1.100 → ~1.950, verdes |
| Coste estimado mostrado por el ejecutor | $0,01–$0,13 por Task |
| Suscripción que pagaba entonces | $10/mes; las llamadas aparecían como $0,00 |
| Presupuesto de tiempo por Task | 45 minutos |
El coste de tokens nunca fue la parte cara. Lo caro fue una spec ambigua, un gate que no cubría la superficie, un Delivery mal confirmado o veinte minutos mirando el indicador equivocado.
La pipeline se mantiene pequeña porque solo conserva lo que Orca no puede conocer: qué puede tocar una Task y qué evidencia la hace aceptable. Runs, mensajes, Tasks y Dispatches siguen perteneciendo a Orca. La meta no es que la pipeline «se arregle sola», sino que cada fallo tenga un dueño, un estado duradero y una recuperación que no invente otra fuente de verdad.