Topología
La topología es el grafo que convierte "un incidente en el host edge-prod-04" en "un incidente que tira pagos y búsqueda y email". Sin ella el LLM solo puede razonar sobre la única serie que está disparando.
ADR-025
Los BaseTools de topología actuales (expand_topology, find_topology_node) aterrizaron el 2026-05-18. Antes de eso, el LLM tenía una lista plana de devices y ninguna forma de recorrer relaciones; "qué depende de X" requería que el operador ya supiera la respuesta.
El modelo de datos
Cuatro tablas, todas en MySQL:
| Tabla | Contiene |
|---|---|
topology_nodes | Una fila por nodo. Tiene un type (device / service / cluster / ...), un name, y un props_json de forma libre. |
topology_node_types | El conjunto cerrado de valores permitidos para node.type. |
topology_relations | Edge dirigido src_node_id -> dst_node_id con un type. |
topology_relation_types | Conjunto cerrado de tipos de edge, cada uno tagueado con un campo semantics (hard_dep / runtime_dep / traffic / annotation / observation). |
El tag semantics es la idea clave. Un edge tagueado hard_dep propaga el fallo (si src muere, dst se ve afectado); un edge tagueado annotation no. El recorrido de blast-radius usa esto para filtrar.
Ver internal/manager/biz/topology/.
De dónde viene la data
Tres fuentes, en capas:
- Auto desde spans — el procesador
service_graphde Tempo emite edgesservice_a -> service_bcon un tag de semánticaroutes_to. El manager los espeja atopology_relationsen un tick de sync. - Auto desde edges — cada edge registrado se convierte en un nodo
type=device; el node id queda back-linked a la columnahost_devices.node_idpara queexpand_topology(device_id=X)resuelva a través. - Manual — los operadores añaden nodos
type=service/type=clustery edges a través de la página/topologyde la SPA. Usado para nodos que quieres direccionar pero que no se observan directamente (una base de datos managed, una API de terceros).
Tools
expand_topology
Recorre hacia afuera desde un nodo, devuelve cada nodo alcanzable más cómo se alcanzó. BFS depth 2 default, cap 5. Dirección default both (el blast radius es simétrico — qué podría romper esto, Y qué rompe esto).
{
"node_id": 142,
"depth": 2,
"only_propagating": true,
"direction": "downstream"
}O, cuando arrancas desde un device id:
{ "device_id": 17, "depth": 3 }El tool resuelve device_id → device.node_id automáticamente. only_propagating=true (default) recorre solo edges hard_dep / runtime_dep / traffic; pasa a false para incluir edges de observation / annotation (útil para los casos "muéstrame todo lo relacionado con X").
Los hits devueltos llevan la metadata de path que el LLM necesita para razonar sobre impacto:
{
"center": { "node_id": 142, "node_name": "payments-api", "node_type": "service", "hops": 0, "propagates_failure": false },
"max_hops": 2,
"reachable_count": 7,
"reachable": [
{ "node_id": 71, "node_name": "edge-prod-04", "node_type": "device", "hops": 1,
"relation_type": "deployed_on", "semantics_tag": "runtime_dep", "reached_via": "downstream",
"propagates_failure": true,
"via_node_id": 142, "via_node_name": "payments-api" }
]
}La lista plana (sin struct anidado por-vecino) es intencional — mantiene el JSON barato de embeber en el prompt. Ver expand_topology_basetool.go.
find_topology_node
El pre-step "tengo un nombre dado por humano, dame un node_id". La persona corre esto antes de expand_topology cada vez que el prompt menciona un servicio / host por nombre:
User: "what does loki-write depend on?"
Agent:
→ find_topology_node{ name: "loki-write" }
← { node_id: 219, node_type: "service", name: "loki-write" }
→ expand_topology{ node_id: 219, direction: "upstream" }
← { reachable_count: 4, ... }Ambos están registrados como BaseTools ScopeManager (sin argumento edge_id) — la DB de topología vive del lado del manager.
Recorrido de blast-radius en la práctica
El prompt de la persona investigator incluye un explícito "después de identificar el servicio que dispara, llama a expand_topology para ver qué más está afectado". Así es como se pueblan las related_alerts del informe y la sección "业务影响 / Business impact" — el agente recorre el grafo desde el device que dispara hacia arriba / hacia abajo y cruza con qué otros incidentes han disparado en la misma ventana en esos nodos.
La code path relevante:
correlate_incidentdevuelve resúmenes de métrica + log + trace más eldevice_iddel incidente.expand_topology { device_id, direction: both, depth: 2 }devuelve el conjunto alcanzable.- La extracción Pass-2 lee la narrativa del worker y extrae
pinpointed_target(el zero patient) +related_alerts(la cascada).