Coordinator
El coordinator es la persona con la que realmente habla el usuario. Cada sesión de chat (UI web, Slack, Telegram, Feishu) es propiedad de una instancia de coordinator. No es un worker — es el loop ReAct de larga vida que conduce la conversación, decide cuándo responder directamente y cuándo despachar a un specialist vía AgentTool.
Identidad
| Campo | Valor |
|---|---|
| Nombre de persona | default |
| Lanzable como worker | No — el catálogo de agentes excluye default |
| Modelo de sesión | Una fila chat_sessions de larga vida por (user, hilo de chat) |
| Toolbag | Amplio: query_*, AgentTool, SendMessage, TaskStop, redirect stubs |
| Cuerpo de persona | Viene en la imagen del manager; override por organización vía archivo montado |
Si quieres cambiar el comportamiento del coordinator a nivel de flota, monta un default.md custom sobre el integrado (ver Agentes custom). El seam AgentRegistry.Replace es lo que alimenta la UI de edición de user-agent; un archivo de override usa la misma code path al arranque.
Qué puede hacer directamente
El toolbag del coordinator incluye todos los tools query de solo lectura que funcionan en el scope del manager:
query_promql,query_logql,query_traceql— telemetría. Stubbed en el coordinator (redirect al incident-investigator) para casos de alucinación conocidos — ver abajo.query_knowledge— RAG sobre el vault + uploads.query_incidents,get_incident_detail,query_alert_rules,query_devices— alerta / inventario.query_change_events— mutaciones recientes de config / regla / device.expand_topology,find_topology_node— grafo de servicios.get_active_incidents— alertas abiertas actuales.- Tools de handlers BC — cualquier cosa que un admin de organización o usuario haría desde la UI.
Deliberadamente no lleva tools de host-shell o inspección por host. Esos viven en los specialists.
El trío de tools de control
Tres tools especiales viven solo en el coordinator. Controlan la orquestación multi-agente; no consultan nada.
AgentTool
Despacha un worker. Síncrono. El schema completo, el comportamiento de dedupe y la guard rail de "no delegues trivialidades" están documentados en Overview de agentes. La forma:
{
"description": "Find which process is OOM-ing on node-01",
"subagent_type": "specialist-compute",
"prompt": "On device_id=7 we saw mem_used_pct=98 at 14:02. Find the top RSS processes and check dmesg for oom-killer hits. The user originally asked: 'who's eating memory on node-01?'"
}El system reminder inyecta el catálogo de personas para que el LLM conozca los valores válidos de subagent_type. El reminder es por turno — incluso tras deriva de atención en sesiones largas, el LLM nunca olvida qué specialists existen.
SendMessage
Envía un mensaje intermedio al usuario sin terminar el turno. Se usa cuando el coordinator quiere decir "estoy despachando a specialist-network — dame un minuto" antes de que el dispatch se asiente. Los workers no llevan este tool — solo el coordinator habla con el usuario.
El bridge de IM lo usa para actualizar el mensaje placeholder en chat (chat.update en Slack, editMessageText en Telegram, PUT /messages en Feishu). La UI web lo usa para streamear texto intermedio en la transcripción antes de la respuesta final.
TaskStop
Cancela educadamente un worker en ejecución. El coordinator emite TaskStop cuando, p. ej., el usuario cambia de tema en medio del dispatch y la respuesta del worker que está corriendo ya no es relevante.
Internamente llama a Runtime.StopWorker, que dispara el context.CancelFunc del worker. El worker observa ctx.Done() en su próxima llamada de tool y fija Status = killed.
Cuándo despachar vs responder directamente
El prompt de persona del coordinator codifica la regla:
AgentTool 不是默认选项。能用本地工具 1-2 步答出来的,自己答。复杂深挖 (需要 5+ 步 / 跨主机 / 跨信号面)才派。
En español: despacha solo cuando la tarea
- necesita iteración profunda (5+ llamadas de tool de inspección enfocada),
- necesita tools del lado del host (
host_bash,host_probe_*,host_du_summary), o - se beneficia de un toolbag específico de dominio que el coordinator no lleva.
Para "¿cuál es la load en node-01?" el coordinator responde directamente con un get_host_load (bueno — con un AgentTool(specialist-compute) mediado por un redirect stub; el principio es el mismo). Para "¿por qué el order service está tirando 502 y qué debo hacer al respecto?" el coordinator despacha al incident-investigator.
Redirect stubs (anti-alucinación)
El bag del coordinator lleva entradas RedirectStub para nombres de tools que el LLM tiende a alucinar (host_bash, host_du_summary, host_restart_service, get_host_load, correlate_incident, …). Cuando el LLM elige un nombre stubbed, el stub devuelve:
{
"status": "redirect",
"hint": "This tool is not available in coordinator scope. Re-invoke via AgentTool to dispatch to specialist-disk.",
"reason": "目录占用分析",
"suggested_call": "AgentTool(description=\"…\", subagent_type=\"specialist-disk\", prompt=\"<self-contained task>\", background=true)",
"why_stub_exists": "Coordinator's job is dispatch + triage. Deep-dive tools live on specialist workers; calling them inline is the wrong pattern."
}Sin estos stubs, el graph runtime de eino abortaría con [NodeRunError] tool X not found in toolsNode indexes y desperdiciaría el turno. Con ellos, el LLM aprende del resultado y reintenta con la llamada AgentTool correcta en la siguiente iteración. La lista de stubs vive en CoordinatorRedirectStubs; es data pura — anexa con el tiempo cuando aparezcan nuevas alucinaciones.
No ensombrezcas el bag entero del specialist
Cada stub ocupa un slot en la lista de schemas que se le presenta al LLM. Stubbear demasiadas tools infla el presupuesto del prompt; el LLM puede empezar a tratar los stubs como opciones válidas a considerar. Solo las tools que se haya observado que alucinan en evals obtienen un stub.
Lo que el usuario ve
Cada turno el coordinator puede:
- Streamear tokens directamente — la respuesta es corta y autocontenida.
- Llamar tools de query de solo lectura inline —
query_incidents,expand_topology,query_knowledge. - Despachar un worker vía AgentTool — la SPA renderiza un "Agent tile" con el nombre de la persona + la descripción de 1 línea mientras el worker corre. El resultado final del worker aterriza como hijo del tile.
- Enviar un mensaje intermedio vía SendMessage — normalmente antes de que un dispatch lento se asiente ("investigando; lanzando specialist-network").
- Detener un worker vía TaskStop — raro, normalmente solo cuando el usuario redirige en medio del dispatch.
El usuario nunca ve la transcripción cruda del worker. El coordinator sintetiza el Result del worker en su propia respuesta.
Sesión y audit
- La sesión del coordinator vive en
chat_sessionsconagent_id = "default"yparent_session_id = NULL. - Las sesiones de worker reciben
parent_session_idapuntando a la fila del coordinator. La UI de audit recorre este árbol para renderizar las ejecuciones parent → child. - Cada llamada de tool obtiene una fila
audit_logscon la vista del LLM de los args y el resultado truncado (ver self-observability).
Customizando el coordinator
Puedes sobreescribir el archivo de persona del coordinator. Cosas que típicamente querrías cambiar:
- La guía de dispatch (tu equipo tiene una política distinta de "cuándo delegar").
- El idioma / tono de salida (usa default_locale en el canal; o fíjalo vía cuerpo de persona).
- La lista de tools inline de solo lectura que quieres que el coordinator use antes de despachar.
Cosas que no deberías cambiar:
- El bloque de catálogo de agentes — se genera por máquina. Editarlo no tiene efecto; el siguiente reload lo regenera.
- La semántica de redirect-stub — es código, no persona.
- El
namedefault— el runtime busca al coordinator por nombre.
Ver Agentes custom para la historia de hot-reload.