Runbook: Dispatch

Dispatch reclama tareas automaticas y las lanza con el runtime configurado.

Servicios

  • ops-center.service: API y UI.
  • ops-dispatch-launcher.service: launcher de tareas.

Salud

Validar:

  • worker heartbeat fresco
  • dispatch_enabled
  • runtimes disponibles
  • credenciales configuradas
  • tareas en estado correcto
  • que las plantillas activas tengan algun worker compatible con su agente/modelo
  • que los agentes anunciados por worker esten autenticados realmente

Un health no es suficiente si solo confirma que hay heartbeat. Tambien debe detectar desalineaciones entre plantilla, workspace, agente, modelo, proveedor y worker.

Interpretacion de /api/dispatch/health:

  • ok=true significa que no hay blockers de los workers activos ni warnings de cola.
  • blockers solo debe incluir agentes anunciados por workers frescos. Un agente activo en catalogo pero no anunciado por ningun worker no bloquea dispatch.
  • opencode puede estar sano con mode=task_scoped aunque el OAuth local este caducado, siempre que haya credenciales OPS activas y un worker fresco con ALLOW_TASK_SCOPED_CREDENTIAL_AUTH=true.
  • local_reason es diagnostico del host local; no es blocker si ready=true.

Politica De Agentes Y Fallback

OpenCode es el runtime preferente del workspace interno mientras este configurado y autenticado.

Hermes es valido si se configura explicitamente en tarea, plantilla, perfil o workspace. Hermes no debe usarse como fallback silencioso.

Los fallbacks deben:

  • estar en configuracion o metadata;
  • respetar workspace y credenciales;
  • quedar en auditoria, comentario, contexto u output;
  • no cambiar proveedor/modelo de forma enganosa.

Los modelos y proveedores cambian rapido. La UI puede sugerir modelos conocidos, pero dispatch debe admitir cualquier modelo que el runtime configurado soporte.

Autenticacion De Runtimes

Orden recomendado para OpenCode:

  1. Preferir credencial de workspace en OPS para el agente opencode y proveedor real (openai, minimax, openrouter, etc.).
  2. Usar API key global en el worker solo para workspaces internos o workers dedicados.
  3. Usar OAuth local de OpenCode solo si se acepta que esa sesion pertenece al host.

El launcher resuelve credenciales antes de seleccionar runtime. Si una tarea trae una credencial de workspace valida, puede ejecutar OpenCode aunque el OAuth local este caducado.

Variables soportadas por OpenCode en el worker o por credenciales inyectadas:

  • OPENAI_API_KEY
  • ANTHROPIC_API_KEY
  • MINIMAX_API_KEY
  • GOOGLE_API_KEY
  • GEMINI_API_KEY
  • OPENROUTER_API_KEY
  • XAI_API_KEY
  • OPENCODE_API_KEY

ALLOW_TASK_SCOPED_CREDENTIAL_AUTH=true permite que un worker anuncie un runtime cuando el binario existe y la autenticacion puede venir de la tarea. Si la tarea no tiene credencial ni existe auth global/local, el launcher falla de forma visible y deja blocker; no cambia a Hermes ni a otro proveedor.

Flujo Hibrido

No todas las tareas tienen que pasar por el worker del VPS. Si una tarea necesita credenciales locales, repos abiertos o supervision estrecha, puede reclamarse desde la aplicacion de escritorio.

Regla operativa:

  • Dispatcher automatico para tareas repetibles, acotadas y con credenciales configuradas en OPS.
  • Escritorio para tareas con contexto local, sesiones ya abiertas o decisiones humanas frecuentes.
  • En ambos casos, la salida obligatoria es la misma: comentario final, evidencia visible, tiempo registrado y estado correcto.

Antes de lanzar o reclamar una tarea de IA, revisa que tenga bloque Instrucciones para agente en la descripcion o en contexto. Ese bloque debe incluir agente/modelo preferente, contexto operativo, criterio de terminado, donde registrar y que hacer si se bloquea.

El contrato estructurado vive en execution_contract:

  • tasks.execution_contract para overrides por tarea.
  • task_templates.execution_contract para recurrentes.
  • metadata.execution_contract en workspace/profile como fuente heredable.

El dispatcher recibe el contrato efectivo como JSON dentro del prompt. El preflight solo bloquea dispatch cuando el contrato efectivo incluye preflight_required=true, require_preflight=true o required=true; esto evita romper tareas antiguas mientras permite tareas estrictas.

Contexto Operativo Para Agentes

Cuando una tarea pertenece a un proyecto ejecutable, el agente que la cree o la desglose debe rellenar execution_contract con el contexto minimo para que otro agente pueda continuar sin preguntar lo basico. No se usa una columna separada tipo context_json: la fuente oficial es execution_contract, porque ya se hereda desde workspace, perfil, plantilla y tarea.

Chuleta Rapida Para Agentes

Copia este bloque cuando pidas a un agente que cree o divida tareas para ejecucion autonoma:


Cuando crees o dividas tareas OPS para ejecucion autonoma, rellena `execution_contract` en cada tarea que vaya a ejecutar un agente.



No uses `context_json`. La fuente oficial es `execution_contract`.



Estructura base:



{

  "preflight_required": true,

  "preferred_agent_slug": "opencode",

  "preferred_model": "openai/gpt-5.4",

  "project_path": "/ruta/absoluta/al/proyecto",

  "working_folder": "src",

  "depends_on": [ID_TAREA_PREVIA],

  "deliverables": [

    "ruta/del/archivo-a-crear-o-modificar"

  ],

  "verify_commands": [

    "comando seguro de verificacion"

  ],

  "acceptance_criteria": [

    "Condicion observable para considerar la tarea terminada"

  ],

  "blocked_fallback": "Si falta ruta, credencial, repo o decision funcional, dejar la tarea en waiting con una pregunta concreta."

}



Reglas:



1. Si una tarea B necesita que A termine antes, B debe incluir `"depends_on": [A]`.

2. No confies en score, orden visual o posicion en cola para definir dependencias.

3. Si la tarea toca codigo, incluye `project_path` y, si aplica, `working_folder`.

4. `working_folder` puede ser relativo a `project_path` o una ruta absoluta.

5. Incluye `deliverables` con archivos, rutas o artefactos esperados.

6. Incluye `verify_commands` solo con comandos seguros de verificacion.

7. No pongas comandos destructivos en `verify_commands`.

8. Si falta informacion real, no inventes rutas ni dependencias: deja la tarea en `waiting` y pregunta.

9. Mantén `execution_contract` corto y operativo. La explicacion larga va en descripcion o contexto.

10. Cada tarea debe poder entenderse aislada: titulo, descripcion, proyecto, contrato, criterio de aceptacion y fallback.

Estructura recomendada:


{

  "preflight_required": true,

  "preferred_agent_slug": "opencode",

  "preferred_model": "openai/gpt-5.4",

  "project_path": "/Volumes/Disco SSD/Desarrollo/clientes/cliente/proyecto",

  "working_folder": "src",

  "depends_on": [1011],

  "deliverables": [

    "src/Models/Expediente.php",

    "src/Controllers/ExpedienteController.php"

  ],

  "verify_commands": [

    "php -l src/Models/Expediente.php",

    "php -l src/Controllers/ExpedienteController.php"

  ],

  "acceptance_criteria": [

    "El modelo existe y no rompe carga/autoload.",

    "El controlador compila sin errores de sintaxis.",

    "La tarea deja evidencia de comandos ejecutados."

  ],

  "blocked_fallback": "Si falta repo, credencial o decision funcional, dejar la tarea en waiting con pregunta concreta."

}

Campos que el dispatcher/launcher ya entiende:

  • depends_on: lista de IDs de tareas que deben estar done o archived antes de ejecutar. Si alguna sigue abierta, el dispatcher no selecciona ni reclama la tarea.
  • project_path: ruta absoluta del proyecto en el worker que ejecutara la tarea.
  • working_folder: subcarpeta relativa dentro de project_path, o ruta absoluta si aplica. El launcher la usa como cwd real.
  • deliverables: archivos, rutas o artefactos que la tarea debe producir o modificar.
  • verify_commands: comandos concretos de verificacion que el agente debe ejecutar cuando proceda.
  • runtime_timeout_ms o runtime_timeout_minutes: limite de ejecucion para tareas largas. Si expira, el launcher deja la tarea en waiting con timed_out=true, rutas de logs parciales y una pista de reanudacion.
  • resume_hint o timeout_resume_hint: instruccion breve para reintentar, dividir o revisar salida parcial tras timeout.

Campos de calidad recomendados:

  • acceptance_criteria: condiciones observables para considerar la tarea terminada.
  • required_outputs: evidencias obligatorias que deben aparecer en la respuesta final.
  • completion_checklist: checklist que el agente debe completar en contexto/comentario.
  • human_gate_policy: required si hay datos sensibles, despliegue, borrado, pagos, usuarios o credenciales.
  • blocked_fallback: que debe hacer el agente cuando no pueda continuar.

Reglas para agentes que creen o dividan tareas:

  • Si las tareas tienen orden logico, rellenar depends_on en las posteriores. No confiar solo en score o posicion en cola.
  • Si una tarea debe tocar codigo, indicar project_path y, si procede, working_folder.
  • Si no se conoce una ruta o dependencia con seguridad, no inventarla: dejar la tarea en waiting o pedir aclaracion.
  • Si un comando puede ser destructivo, no ponerlo en verify_commands; dejarlo como paso con Human Gate.
  • Mantener execution_contract corto y operativo. La explicacion larga va en descripcion, plan o contexto.
  • Cada tarea debe poder entenderse aislada: titulo, descripcion, proyecto, contrato, criterio de aceptacion y fallback.

Flujo De Estados

Estados visibles:

  • inbox
  • next
  • doing
  • waiting
  • review
  • done
  • archived

Estados tecnicos:

  • queued
  • dispatching

Solo dispatch encola una tarea. Mover a doing no ejecuta automatismo.

Tareas Recurrentes

El scheduler crea instancias desde task_templates.

  • human/manual crea en inbox.
  • interactive/auto crea en queued.
  • si ya existe una instancia viva de la plantilla que no este done ni archived, no duplica.
  • si la plantilla define execution_contract.allow_overlapping_instances=true, solo evita duplicados de la misma ventana planificada y permite que el siguiente ciclo nazca aunque quede trabajo anterior en review.

Salvo que la plantilla permita solape, si una instancia recurrente queda en review, waiting, next o doing, puede bloquear la siguiente ocurrencia. Hay que cerrarla, archivarla o relanzarla de forma consciente.

El scheduler abre o reabre alertas de sistema cuando una recurrente falla por RRULE invalida, error de scheduler o instancia activa bloqueante. Si el fallo requiere correccion de plantilla, crea o reutiliza una tarea scheduler-watchdog con tag recurring-watchdog.

Bloqueos Y Re-dispatch

Cuando una tarea automatizable esta bloqueada por falta de input:

  1. escribir la resolucion en el panel superior de Respuesta requerida;
  2. elegir Responder y ejecutar para continuar automatico;
  3. elegir Responder y desbloquear si solo se quiere quitar el bloqueo;
  4. aprobar Human Gate si la tarea es sensible;
  5. usar Dispatch now para lanzar manualmente tareas automatizables en next.

Solo guardar nota conserva contexto, pero no desbloquea ni ejecuta. Comentar en una tarea no debe interpretarse mentalmente como ejecutar. Reencolar significa llamar a dispatch y pasar a queued.

Recuperacion

  1. Revisar health de API.
  2. Revisar logs del launcher.
  3. Ejecutar doctor de worker.
  4. Pausar dispatch si hay fuga de errores.
  5. Reencolar tareas solo si el output previo lo permite.