Incident investigator
incident-investigator es el más profundo de los workers de Ongrid. El coordinator despacha a él cada vez que el usuario quiere causa raíz, no solo un resumen de síntomas. La persona recorre la cadena causal desde la alerta observada hasta la fuente originaria ("patient zero" — 0 号病人 en el prompt de la persona) y devuelve un informe estructurado.
Esta es la persona detrás de RCA
El pipeline causal RCA HLD-013 (entorno de test, rollout en mayo 2026) está construido sobre esta persona. Cuando /incident/<id> → Get RCA corre, el manager lanza este worker con el incident id pre-rellenado en el prompt.
Cuándo la elige el coordinator
El archivo de persona declara los patrones de trigger. Citando el frontmatter verbatim:
when_to_use: |
coordinator 在用户问以下场景时 spawn 本 worker:
• "这条告警的根因是什么 / 到底是谁导致的"
• "incident 123 怎么排查 / 受影响范围 / 持续多久"
• "这个告警是不是误报 / 跟上次那个相关吗"
• "这台机器 mem 飙了,看一下"Traducción: cada vez que el usuario pregunta por qué en vez de qué. El entregable del investigator es la cadena causal hasta la fuente, no un snapshot de "estado actual".
Toolbag
Whitelisted en la persona — el filtro del runtime elimina todo lo demás:
tools:
- query_knowledge # KB / vault / uploads
- get_incident_detail
- query_incidents
- correlate_incident # metric+log+trace pulled together
- query_change_events # config / rule / device mutations
- query_promql
- query_logql
- query_traceql
- get_edge_summary
- query_alert_rules
- query_devices
- get_host_load
- get_host_processes
- expand_topology
- find_topology_node
- host_find_large_files
- host_du_summary
- host_stat_file
disallowed_tools:
- execute_skill
- host_restart_service
- run_shell
permission_mode: read-onlyConsecuencias clave:
- Read-only. Sin
host_restart_service, sinexecute_skill, sinrun_shell. Si la investigación concluye que un servicio necesita reinicio, lo devuelve como propuesta al coordinator; el coordinator despachaspecialist-opscon una intención mutadora, y el reviewer la gatea. - Topología y change events. La ventaja única que tiene sobre los specialists es
expand_topology+find_topology_node(recorrer el grafo de servicios hacia atrás hasta fuentes upstream) yquery_change_events(correlacionar síntomas con mutaciones recientes de config / regla / device alrededor delfired_atde la alerta). - El bash cross-host y las probes por host están ausentes. Esos viven en los specialists (
specialist-network,specialist-compute,specialist-disk); el investigator coordina sobre el data plane de observabilidad.
El workflow de 5 pasos
El cuerpo de la persona codifica el workflow. Cada investigación corre:
- KB primero (obligatorio). Una vez con el
incident_iden mano,query_knowledgeexactamente una vez con el nombre de la regla + síntoma como query en lenguaje natural (p. ej. "swap_high 告警怎么 排查"). Un hit (score ≥ 0.6) significa seguir el playbook; la respuesta final lleva una citación(参考 KB: <title>). Un miss significa proceder al paso 1. - Síntoma + blast radius.
get_incident_detailpara el nombre de la regla / severidad / target /fired_at/ labels. Este es el final de la cadena causal (el efecto), no la causa raíz. No te detengas aquí. - Timeline.
correlate_incidentjala metric + log + trace para la misma ventana del incidente en una llamada. Ordena porfired_at/ primer momento de desviación. La señal más temprana es el candidato fuente; la CPU/latencia alta downstream usualmente es efecto, no causa. "Más ruidoso" ≠ "más temprano". - Un salto causal upstream. Elige un tool con un propósito claro:
- ¿Qué cambió? →
query_change_events(around_ts=fired_at). Los cambios del lado producto son frecuentemente patient zero. - ¿Dependencias? →
expand_topologyupstream (no blast radius downstream) /find_topology_node. - ¿Recorrer la cadena de callers? →
query_traceqlpara encontrar el originador del span más lento. - ¿Primer error? →
query_logqlgrep por device_id para el ERROR / PANIC / OOM más temprano antes defired_at. - ¿Quién se movió primero? →
query_promqlpara encontrar la métrica que se desvió primero.
- ¿Qué cambió? →
- Recursa. Trata al candidato upstream como el nuevo punto actual. Repite el paso 3 hasta una de:
- Tocar fondo — no queda upstream in-system. La hoja es un proceso / un único cambio / una dependencia externa = patient zero.
- Señal agotada — no se puede ir más allá. Reporta "capa más profunda alcanzada + qué señal nos dejaría continuar".
- Validar. La causa raíz propuesta debe explicar toda la cadena downstream — temporalmente anterior al síntoma, magnitud y dirección consistentes. Si no, baja a "hipótesis" y dilo.
El presupuesto de 18 tools — cava profundo, nunca da vueltas
La persona refuerza una disciplina de iteración estricta. Del cuerpo:
你有 ~18 个工具调用预算(够上溯 4-6 层)。深挖允许,但死分支立刻砍:
- 工具返回空(
result:[]/streams:[]):第一次空可换思路;第二次 空立刻停这条线,换方向或就此上溯为止。- 同一工具失败 / 空 ≥2 次 → 必须换工具或换方向,禁止反复换表达式空转 (v0.7.51-55 的失败都栽在这).
- 每一步都要朝"再上溯一层"前进 — 调之前问自己 "这步能让我更接近源头吗"。
- 上溯到 4-5 层仍未触底、或预算用到 ~15:停,输出"目前最深一层 + 缺失 信号",别为凑满空转。
El tope max_turns: 40 en el frontmatter es el techo duro — el grafo de eino cuenta MaxStep = MaxIterations*2+2, así que 40 → MaxStep=82 → aproximadamente 41 turnos de ChatModel. El presupuesto de 18 tools es la guía más suave en el prompt; el tope es la red de seguridad del runtime.
Los dead branches no son negociables
El prompt del investigator lo hace una regla explícita de "no hagas" porque las primeras evals v0.7.51-55 vieron al worker quemar 30+ turnos re-permutando expresiones PromQL intentando hacer que una range query vacía devolviera data. Un solo resultado vacío es información; un segundo resultado vacío significa que ya aprendiste lo que ibas a aprender — pivota o asciende.
Formato de salida
La respuesta final al coordinator es Markdown verbatim de esta forma:
**根因(0 号病人)**
{One-line patient zero — process / change / upstream service+node /
config. Concrete identifiers (pid + cmdline / service name / change
key) — this is the source of pinpoint_target. If we didn't hit bottom:
"未触底,最深到 X;要继续需 Y 信号".}
**因果链**
{Source → … → alert symptom. One line per hop, each with "why this
caused the next" plus evidence (PromQL / LogQL / trace span /
process line).}
**现象**
{1-2 sentences: when did it start / which host / what crossed
threshold / for how long.}
**置信度与验证**
{High / medium / low + reason. Plus: "what query or action would
further validate or falsify this root cause".}El coordinator sintetiza esto en la respuesta hacia el usuario (un idioma, un párrafo, la citación si hubo hit de KB). El Markdown crudo del investigator también se persiste como el Result del worker en la sesión — la UI de RCA lo muestra verbatim bajo el desplegable Razonamiento.
El test e2e F1
F1 es la eval end-to-end que ejercita esta persona contra un incidente sembrado en el entorno de test. Forma:
- Sembrar un incidente sintético
swap_highennode-01(device_id=7) con un procesosearxngfijado al 95% RSS durante 30 minutos. - Cablear el pipeline de alerta para que el incidente dispare con las labels esperadas +
fired_at. - Despachar al investigator con
prompt = "rca incident 1234". - Asegurar que la respuesta final contenga:
- regla
swap_highmencionada en现象. - proceso
searxngidentificado en根因(0 号病人)con un pid + línea de comando. - Al menos 2 saltos causales en
因果链(síntoma → upstream). - Citación
(参考 KB: …)SI el KB sembrado tiene un playbook matcheando.
- regla
La primera versión de HLD-013 falló F1 porque default_provider no estaba seteado en la DB — el resolver cayó a openai con un nombre de modelo glm, el chat model erroró y el worker devolvió un análisis vacío. La lección: F1 también cubre el resolver de LLM como side-effect, por lo cual es el gate canónico "¿RCA realmente cabló end-to-end?".
Razones comunes por las que se queda corta
La persona devuelve "patient zero no alcanzado" honestamente cuando:
- La causa está fuera del cluster — proveedor DNS, API upstream, energía.
query_change_eventsno ve cambios de infra fuera del scope del manager. - Faltan datos de trazas — las queries TraceQL no devuelven spans para el servicio relevante. El investigator no puede recorrer una cadena de callers sin trazas; reporta "缺失 trace 信号".
- La línea de log que apuntaría al trigger ha rotado. La retención de Loki < el time-to-first-investigate. El investigator lo dice y recomienda extender la retención para investigaciones recurrentes.
Esta honestidad es por diseño. Una respuesta equivocada con confianza es peor que "tocamos la señal X y necesitamos Y para continuar".
Tuning
Cosas que realísticamente cambiarías en un fork de esta persona:
- Añadir hits de KB específicos del dominio — escribe playbooks para tus modos de falla comunes, distribúyelos vía el vault, el paso
KB firstdel investigator los descubrirá. - Ajustar la whitelist de tools — añade variantes de
query_traceqlsi tu stack de tracing no es Tempo, o quitahost_du_summarysi no quieres que el investigator despache inspección de disco inline (el default es delegar aspecialist-diskvía la propia salida del worker — pero la persona sí lleva las tools para inspeccionar él mismo cuando es rápido). - Apretar el presupuesto — si el costo por-token de tu modelo importa, baja
max_turnsa 25-30. El presupuesto blando de 18 llamadas en el cuerpo de la persona ya mantiene la mayoría de investigaciones por debajo de eso.
Ver Agentes custom para cómo montar tu fork sobre la integrada.