An autonomous 5G incident-triage system that stops before it acts.
One real dispatch run, end to end: the n4_upf_timeout lab scenario drops the UPF’s PFCP traffic, KPI detection raises an Alarm, three specialist agents gather 47 evidence items, a LATS search explains it — and the remediation proposal stops at a human gate. Every number on this page is from the run itself.
The sandbox runs a live Open5GS core (AMF, SMF, UPF, gNB, UE). The capture script
blackholes the UPF’s PFCP port — udp/8805 — for the
duration of one UE session, then packets flow again. Nothing else is touched.
./capture.sh --scenario n4_upf_timeout — three pcaps (N2, N4, SBI)
overwrite the committed fixtures; the window is one session’s worth of PDU
establishment attempts against the silenced UPF.
The merged export’s KPIs are compared to the golden baseline; the deltas break
thresholds, and detect-kpi synthesizes the Alarm event
inc-kpi-06eebc61.
gather validates the event and loads the stub (here: none — all agents
run live). Then the evidence fans out to three specialists in parallel, each grounded to
its source before it is ever recorded.
Runs 5gcap analyze over the three captures, then delegates the decode to
triage analyze — its own LATS search — which traced
318 chain steps and 114 LLM calls. Returns 5 items: one explicit
5GSMPDUSessionEstabReject cause 38 on N2, four PFCP Session Establishment
Requests that never got a terminal message.
Re-computes the export’s KPIs against the event. 19 items: two deviations and one reject-message item per failed procedure.
Pulls docker compose logs for the event’s window, hands the extractor
the text with every line numbered [001], [002], …, and the model
proposes items citing log:<n> — resolved in code, never trusted.
23 items ground, each carrying its looked-up line.
All 47 items, as recorded — grouped by source. Log items render their citation and the exact looked-up line. The warm-striped rows are the smoking gun: the UPF’s own heartbeat timeout.
0.9 ms of deterministic code: items that share a key get linked — unless a key is claimed by more than two items, which would make the link a guess.
no links — 17 of the 19 KPI items share
procedure_failures=17, and the ambiguity rule forbids linking when more than
two items claim a key. The inventory stays flat, and the investigation reads it as-is.
5.0 seconds, 204 traced phases across five tree nodes. Each phase is one
expand / execute / evaluate step of a LATS search
over the evidence inventory — the agent may inspect (re-read the
inventory) and may only end the search with a finalize whose citations name
inventory items exactly. Node 5 is the leaf where the winning episode grounded.
root cause — node.5’s finalize, grounded
“The missing UPF heartbeats caused the SMF to report no UPF available, triggering NAS cause 38 rejections that drove down the procedure success rate and inflated session latency.”
Tree structure from the LangSmith trace; step payloads live in the checkpoint. The dispatch-level Groq calls traced for this run:
| signature | calls | stage | what it produced |
|---|---|---|---|
| LogEvidenceSignature | 1 | log_agent | the 23 grounded evidence proposals, each citing log:<n> |
| ExpandSignature | 1 | investigate | next-action candidates for the search tree |
| EvaluateSignature | 2 | investigate | reward / status / reflection per explored node |
| ProposalSignature | 1 | propose | the remediation proposal below |
The proposal must pick one action from a fixed vocabulary
(restart_nf, scale_nf, drain_traffic,
rollback_config, no_op); the model argued
restart_nf upf — the exact box the scenario silenced.
The graph stops at the approval interrupt — 10:16:21, 2.8 minutes after
the alarm. Nothing runs until a human says so. The incident was then approved as a
dry-run; the command printed, never executed.
GraphInterrupt: {"pending": true}dispatch approve inc-kpi-06eebc61That is the whole loop: capture → detect → evidence → explain → propose → human gate. The pipeline never touched the running core — the restart command is exactly what a human would run, and the human is the one who runs it.