Chain Breaks
Chain breaks happen when the link between two consecutive events is missing or doesn't match. Most of the time, this is normal. Here's how to understand and resolve them.
How event chains work
Every event your SDK sends includes the fingerprint (SHA-256 hash) of the previous event. This creates a chain — like a receipt that says "this came right after that." If anyone deletes, inserts, or modifies an event, the chain breaks and the dashboard flags it.
Event 1 ──hash──→ Event 2 ──hash──→ Event 3 ──hash──→ Event 4
↑ ↑ ↑
prev_event_hash prev_event_hash prev_event_hash
= hash(Event 1) = hash(Event 2) = hash(Event 3)The first event in any chain has an empty hash — there's nothing before it. Every event after that carries the fingerprint of the one before.
Why chain breaks happen
A chain break means one event's "previous hash" doesn't match what the system expects. Here are the most common reasons, from most to least common:
1. SDK restart (most common)
This is the one you'll see most often, and it's completely normal.
The SDK keeps the chain in memory. When your script or app restarts — a new deployment, a server reboot, running your script again — the SDK starts fresh with an empty hash. But the platform still has the previous events. So the first event after a restart will show a break.
← Script run 1 → ← Script run 2 →
Event 1 ──hash──→ Event 2 ──hash──→ Event 3 Event 4 ──hash──→ Event 5
↑ ↑
hash(Event 2) (empty)
✓ ✗ BREAKIn the Verify page, this shows up as (empty) ≠ abc123... — the new event has no previous hash, but the platform expected one.
2. Multiple SDK clients with the same agent ID
If you run two instances of your agent at the same time with the same agent_id, each one maintains its own chain. Their events interleave in the database, breaking both chains.
Fix: give each instance a unique agent_id, or ensure only one instance runs at a time.
3. Signing key rotation
Rotating your signing key doesn't break the chain by itself — the chain uses SHA-256 hashes, not signatures. But if you rotate the key AND restart the SDK at the same time (which is typical), you'll see a break from the restart.
4. Actual tampering (rare)
If an event was modified after it was stored, or events were deleted from the database, the chain will break. This is what the chain is designed to detect.
Signs of real tampering vs. a normal restart:
| Signal | SDK Restart | Tampering |
|---|---|---|
| Break location | At the start of a new session | In the middle of a session |
| Actual hash | (empty) | A real hash that doesn't match |
| Number of breaks | Usually one per restart | Could be many in a row |
| Time gap | Gap between the two events | No gap — events were consecutive |
Using the Verify page
Go to Verify in the dashboard sidebar. The page shows every agent with a status card — green for valid chains, red for broken. Click an agent to see the details.
For each break, you'll see:
- The event where the break occurred
- The expected hash vs. the actual hash
- A timeline of events around the break point
Resolving a chain break
Every break starts with status Open. The resolution workflow is:
Open → Investigating → Resolved Resolution types: • SDK Restart — the agent was restarted (expected) • Approved — reviewed and accepted (e.g. planned maintenance) • False Positive — not a real break (e.g. ledger cache miss) • Other — custom reason (notes required)
Steps to resolve
- Click the break in the Verify page
- Click Investigate to move it to "Investigating"
- Review the events around the break — check timestamps and hashes
- Choose a resolution (e.g. "SDK Restart")
- Type a note explaining what happened
- Confirm with your account password
Once all breaks for an agent are resolved, its status changes from "Broken" to "All Resolved" — shown in blue on the Verify page. You can reopen a resolved break if needed.
Preventing unnecessary breaks
| Cause | Prevention |
|---|---|
| Script restarts | Expected — resolve as SDK Restart. A future SDK update will persist chain state across restarts. |
| Multiple instances | Use unique agent_id per instance (e.g. append hostname or instance ID) |
| Deployments | Expected — each deployment is a fresh process. Resolve as SDK Restart. |
| Serverless functions | Each cold start is a new instance. Use the function name + version as agent_id. |
Start verifying your audit chains today.
Start recording