Docs / Observability / Semantic loop
semantic_loop
The agent revisited the same canonical state 3+ times even though the surface text differs each step. Stuck in a logical loop. Operates on customer-emitted checkpoint events: the agent code calls mesedi.checkpoint(name, **state) at decision points; the detector canonicalizes the state, hashes it, and fires when the same hash recurs.
What this detector catches
For every checkpoint event, the backend reads the metadata field (the SDK helper mesedi.checkpoint(name, **state) serializes the kwargs under metadata on the wire — so when grepping raw events, look for metadata, not state). It then produces a byte-stable canonical form and hashes it with SHA-256. When 3+ checkpoints in one execution produce the same hash, fires under semantic_loop:<hash8> (the checkpoint name arg is NOT in the signature — same state under different names clusters together).
The deterministic canonicalization is load-bearing:
- JSON object keys are sorted alphabetically AND lowercased.
userIdandUSERIDcluster together. - String values are lowercased and trimmed. Whitespace + capitalization noise doesn't fragment the cluster.
- Floats are rounded to 2 decimals. Trivial floating-point drift across runs still clusters.
- Integer-valued floats render without a decimal.
step=5andstep=5.0cluster identically.
How it differs from the loops detector
semantic_loop operates on checkpoint events (customer-instrumented state snapshots); loops operates on llm_call events (repeated prompts). Both catch "stuck" behavior but from different vantage points. An agent that checkpoints once per planning iteration will surface as semantic_loop; an agent that re-asks the model the same question 3x will surface as loops/identical_call. Both can fire on the same execution by design.
Example failures it groups
- A planning agent re-derives the same plan structure each iteration because a downstream validator keeps rejecting it. Checkpoint sees the same canonical plan; semantic_loop fires.
- A search agent re-queries with the same canonical query string after lowercasing + trimming. Three identical-after-canonicalization checkpoints fire.
- A reasoning agent visits the same state node in a graph traversal because its visited-set isn't being persisted across iterations.
What to do when it fires
Open the failure-group detail page. The Playbook walks through the diagnostic: read the canonical state being revisited; identify the missing termination condition (the state IS being recomputed but no progress is being made); fix by either persisting a visited-set across iterations or adding a max-iteration cap. The signature carries the state hash, not the checkpoint name — but the affected executions all share the same checkpoint payload, so reading the metadata field on any one of them shows you which logical state is stuck.
When NOT to investigate
- Customers not calling checkpoint() — if your agent doesn't emit checkpoint events, this detector has nothing to detect. There will be no failure groups (no false positives, no signal). Instrument the agent to enable the detector.
- Intentional convergent computation — if your agent is supposed to repeatedly checkpoint the same state as part of a convergence check, the detector will fire. Tune revisit_threshold up or use severity routing.
Tunable thresholds + allowlist
revisit_threshold (default 3; bounds [2, 1000]) is per-project tunable via the Detector thresholds primitive. No tier cap (pure alerting sensitivity; raising fires later, no cost asymmetry). No allowlist support today.
Related docs
- loops — the llm_call sibling. semantic_loop operates on checkpoint events; loops operates on llm_call events.
- token_waste — the spend-side angle on the same kind of pattern.
- Detector thresholds — tune
revisit_threshold.