Skip to content

Coordinator

O coordinator é a persona com quem o usuário de fato conversa. Toda sessão de chat (web UI, Slack, Telegram, Feishu) pertence a uma instância de coordinator. Ele não é um worker — é o loop ReAct de longa duração que conduz a conversa, decide quando responder diretamente, e decide quando despachar para um specialist via AgentTool.

Identidade

CampoValor
Nome da personadefault
Pode virar worker?Não — o catálogo de agents exclui default
Modelo de sessãoUma linha de longa duração em chat_sessions por (usuário, thread de chat)
Tool bagAmpla: query_*, AgentTool, SendMessage, TaskStop, redirect stubs
Corpo da personaEmbarcada na imagem do manager; override por organização via arquivo montado

Se você quiser mudar o comportamento do coordinator em toda a frota, monte um default.md customizado sobre o built-in (veja Agents customizados). A costura AgentRegistry.Replace é o que sustenta a UI de edição de user-agent; um arquivo de override usa o mesmo caminho de código no startup.

O que ele pode fazer diretamente

A tool bag do coordinator inclui todas as ferramentas query somente-leitura que operam no escopo do manager:

  • query_promql, query_logql, query_traceql — telemetria. Stubbed no coordinator (redirecionam para incident-investigator) para casos conhecidos de alucinação — veja abaixo.
  • query_knowledge — RAG sobre o vault + uploads.
  • query_incidents, get_incident_detail, query_alert_rules, query_devices — alerta / inventário.
  • query_change_events — mutações recentes de config / regra / device.
  • expand_topology, find_topology_node — grafo de serviços.
  • get_active_incidents — alertas abertos no momento.
  • BC handler tools — qualquer coisa que um admin de org/usuário faria pela UI.

Ele deliberadamente não carrega ferramentas de shell de host nem de inspeção por host. Essas vivem nos specialists.

O trio de control-tools

Três ferramentas especiais existem apenas no coordinator. Elas controlam orquestração multi-agente; não consultam nada.

AgentTool

Despacha um worker. Síncrono. O schema completo, o comportamento de dedupe, e a regra "não delegue trivialidades" estão documentados em Visão geral dos agents. O formato:

json
{
  "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?'"
}

O system reminder injeta o catálogo de personas para que o LLM saiba os valores válidos de subagent_type. O reminder é por turno — mesmo após attention drift em sessões longas, o LLM nunca esquece quais specialists existem.

SendMessage

Envia uma mensagem intermediária ao usuário sem encerrar o turno. Usada quando o coordinator quer dizer "Estou despachando para specialist-network — me dê um minuto" antes do dispatch concluir. Workers não carregam essa ferramenta — só o coordinator fala com o usuário.

A ponte IM usa isso para atualizar a mensagem placeholder no chat (chat.update no Slack, editMessageText no Telegram, PUT /messages no Feishu). A web UI usa para fazer stream de texto intermediário no transcript antes da resposta final.

TaskStop

Cancela educadamente um worker em execução. O coordinator emite TaskStop quando, por exemplo, o usuário muda de assunto no meio de um dispatch e a resposta do worker em execução não é mais relevante.

Internamente ele chama Runtime.StopWorker, que dispara o context.CancelFunc do worker. O worker observa ctx.Done() na próxima chamada de tool e define Status = killed.

Quando despachar vs responder direto

O prompt de persona do coordinator codifica a regra:

AgentTool não é a opção padrão. Se você consegue responder em 1-2 passos com ferramentas locais, responda você mesmo. Investigação profunda (precisa de 5+ passos / cross-host / cross-signal) é que deve ser despachada.

Em outras palavras: despache apenas quando a tarefa

  • precisa de iteração profunda (5+ chamadas de tool para inspeção focada),
  • precisa de ferramentas no host (host_bash, host_probe_*, host_du_summary), ou
  • se beneficia de uma tool bag específica de domínio que o coordinator não carrega.

Para "qual a carga do node-01?" o coordinator responde direto com um get_host_load (bem — com um stub-mediado redirect para AgentTool(specialist-compute); o princípio é o mesmo). Para "por que o serviço de pedidos está retornando 502 e o que devo fazer?" o coordinator despacha para incident-investigator.

Redirect stubs (anti-alucinação)

A bag do coordinator carrega entradas RedirectStub para nomes de tool que o LLM tende a alucinar (host_bash, host_du_summary, host_restart_service, get_host_load, correlate_incident, …). Quando o LLM escolhe um nome com stub, o stub retorna:

json
{
  "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."
}

Sem esses stubs, o runtime de grafo do eino abortaria com [NodeRunError] tool X not found in toolsNode indexes e desperdiçaria o turno. Com eles, o LLM aprende com o resultado e tenta de novo com a chamada AgentTool correta na próxima iteração. A lista de stubs vive em CoordinatorRedirectStubs; é puro dado — acrescente conforme novas alucinações aparecem.

Não sombreie a bag inteira do specialist

Cada stub consome um slot na lista de schemas apresentada ao LLM. Stubs em excesso inflam o budget de prompt; o LLM pode começar a tratar stubs como opções válidas a considerar. Apenas ferramentas observadas alucinando em evals ganham um stub.

O que o usuário vê

A cada turno o coordinator pode:

  1. Fazer stream de tokens diretamente — a resposta é curta e auto-contida.
  2. Chamar ferramentas de query somente-leitura inlinequery_incidents, expand_topology, query_knowledge.
  3. Despachar um worker via AgentTool — o SPA renderiza um "Agent tile" com o nome da persona + a descrição de 1 linha enquanto o worker roda. O resultado final do worker aparece como filho do tile.
  4. Enviar mensagem intermediária via SendMessage — geralmente antes que um dispatch lento conclua ("Investigando; subindo specialist-network").
  5. Parar um worker via TaskStop — raro, geralmente só quando o usuário redireciona no meio do dispatch.

O usuário nunca vê o transcript bruto do worker. O coordinator sintetiza o Result do worker em sua própria resposta.

Sessão e auditoria

  • A sessão do coordinator vive em chat_sessions com agent_id = "default" e parent_session_id = NULL.
  • Sessões de worker recebem parent_session_id apontando para a linha do coordinator. A UI de auditoria percorre essa árvore para renderizar runs pai → filho.
  • Cada chamada de tool gera uma linha em audit_logs com a visão do LLM dos args e o resultado truncado (veja self-observabilidade).

Customizando o coordinator

Você pode sobrescrever o arquivo de persona do coordinator. Coisas que tipicamente você quer mudar:

  • A orientação de dispatch (sua equipe tem uma política de "quando delegar" diferente).
  • O idioma / tom da saída (use default_locale no canal; ou fixe via corpo da persona).
  • A lista de ferramentas somente-leitura inline que o coordinator deve usar antes de despachar.

Coisas que você não deve mudar:

  • O bloco do catálogo de agents — é gerado por máquina. Editá-lo não tem efeito; o próximo reload regenera.
  • A semântica do redirect-stub — são código, não persona.
  • O name default — o runtime localiza o coordinator por nome.

Veja Agents customizados para a história de hot-reload.