Skip to content
How it worksVerificationAgentsBenchmarkBlogBlogReleasesReleasesStar

Deterministic replay and fix verification for journal-driven services.

Product

How it worksFix verificationFor coding agentsAgent benchmarkPerformanceRelease notes

Developers

SourceAgent skillsJournal formatAgent guidellms.txtContributing

Blog

All postsGuidesConceptsProductEngineeringRSS

Project

LicenseDCOReport a bugContact

Install Kavach CLI & Agent Skills

curl -fsSL https://www.thekavachlabs.com/install.sh | shnpx skills add kavachlabs/kavach
© 2026 Kavach LabsPre-alpha. Apache 2.0.
kavach
Blog/Guides/Deterministic Verification

What Invariants Should My Service Have?

This post is about state invariants, why developers find it hard to write them, and how we test if an invariant is actually doing its job.

KC

Koustav Chowdhury

FounderOctober 19, 20264 min read

Before I get into invariants, let me tell you why this question keeps coming up. I have worked in financial industry for about half-a-decade, and when I recently build HFT infrastructure from scratch, we had to check our state after every single event. While building that, I found certain patterns that are helpful for me, and also helpful for agents, to debug faster, to reproduce the issue exactly, and to verify the fixes.

An invariant12 is about checking the laws of your state machine after each transition. What is a state invariant, you may ask? A state invariant is a software's internal rule which determines whether the business state is still valid after an event takes place.

Why does an invariant help to catch a bug faster? Whenever we are stuck wondering if a code change broke something subtle, a good invariant lays out in bare bones what must always remain true in the state. Most of us grew up writing unit tests. Let's say you have a bank account. Your bank account is a summation of all the credits and debits of your money. Now imagine one day you go up to your bank, and it says that you have 10 dollars. When you checked last night, you had 100k. So you will demand the transaction ledger for this, right? You are not ready to accept a single unit test saying one deposit function worked.

From state-map.md to verified invariants in 61 microseconds. Without falsification, an agent writes a weak check that passes on the happy path and lets state corruption slip through. With /kavach-setup and /kavach-invariants, the agent writes .kavach/plan/state-map.md and invariants.md, injects a 1-line mutant for each invariant, verifies invariant_violated in 61.1 microseconds, and saves the kill table.
Checking every invariant against a planted bug in microseconds

A state invariant is kind of like that. It checks the transactional ledger after every state change, every state mutation that leads up to your current balance. In a way, it makes the correctness of an application auditable on every step.

Now, since I have worked in the finance industry, I see its applications everywhere. It helps to catch bad state transitions, to see which exact event broke the accounting, and so on.

Why deterministic replay matters for invariants#

Starting from a snapshot, if you keep replaying the events that are in the journal, your invariants should hold on every step up to the current state. That's the ultimate goal when you are verifying a service. What makes it challenging is that most people don't know which invariants to write first, or how to check if their invariants are actually working.

Having the ability to replay deterministically what happened in production, and to check your invariants in microseconds, is one of the key guarantees of Kavach3, and that is what makes this workflow so useful for coding agents.

Challenges of writing invariants with agents#

These challenges all come down to how agents test their own work. Writing invariants with an agent has several such traps.

Checks that do nothing. Can an agent tell if an invariant is actually good? Test every edge case? How does it know if the check is doing anything at all? If an invariant function just returns true without checking the state, the same 1,000 events in the journal will pass on replay. As a company, Kavach Labs is tackling this by forcing the agent to break the code and prove the invariant catches the bug.

State kept in multiple places. Software often keeps state in more than one map. Say you design a wallet service that keeps account balances in one map and net deposits in another variable. How does the agent know how they relate without a map of the state? With 1,000 events it may look fine, but on a transfer bug the two numbers drift apart. So our setup skill writes a state map file in the repo first, before touching the code.

.kavach/plan/state-map.md — Wallet Ledger (examples/ledger)
1. Integration Mode
  • Mode: Direct Handler Instrumentation (Production kavach-recorder + kavach-host Replay)
  • Language & SDK: Go (github.com/kavachlabs/kavach/sdk/go)
  • Host Command (--bin): ./ledger
2. State Root & Mutable Structures
Structure / Field Location (file:line) Role & Consistency Requirement
Ledger.Balances (map[string]int64) sdk/ledger.go:40 Primary per-account balance map; every account balance must remain >= 0.
Ledger.Net (int64) sdk/ledger.go:41 Running net total of deposits - withdrawals; must always equal sum(Balances).

Invariants that aren't falsified. One requirement for trusting an invariant is that a broken build should make it fail. Most teams never test their assertions against broken builds because container simulations take half an hour, so quite a few chunks of software have weak checks. How do you test those fast? In Kavach, replay runs in 61 microseconds in memory, so our invariant skill injects a one-line bug, replays the journal, and checks that the invariant fails. These are the uncomfortable parts of verification that we want to tackle.

.kavach/plan/invariants.md — Wallet Ledger (examples/ledger)
1. balances_non_negative (Bounds & Non-Negativity)
  • State inspected: Ledger.Balances (sdk/ledger.go:114-121)
  • Law: For every account a in Ledger.Balances, l.Balances[a] >= 0 after every step.
  • Planned falsification mutant: sdk/ledger.go:68 — omit the l.Balances[ev.Account] < amount guard in withdraw so overdraft event evt-005 (seq 19) debits bob below zero.
2. money_conserved (Conservation Law)
  • State inspected: Ledger.Balances and Ledger.Net (sdk/ledger.go:122-131)
  • Law: sum(l.Balances) == l.Net after every step.
  • Planned falsification mutant: sdk/ledger.go:77 — skip the sender debit l.post(env, ev, ev.Account, -amount, at) during transfer so evt-003 (seq 9) credits bob without debiting alice.
Falsification Results (Millisecond Mutation Sweep)
Invariant 1-Line Mutant Injected (file:line) Verdict Replay Time
balances_non_negative sdk/ledger.go:68: skip balance < amount on withdraw invariant_violated(balances_non_negative)@19 61.1 µs
money_conserved sdk/ledger.go:77: skip sender debit on transfer invariant_violated(money_conserved)@9 61.1 µs

We're building Kavach Labs to tackle this problem head-on. We love deterministic verification as an architectural concept, and we want agentic software to be written and deployed so that it's easy to map your state, falsify your invariants, fix the code, and deploy with more confidence.

curl -fsSL https://www.thekavachlabs.com/install.sh | sh
npx skills add kavachlabs/kavach

References

  1. ArticleAntithesis skills for agentsantithesis.com↩
  2. CodeKavach Agent Skillsgithub.com↩
  3. DocsWallet Ledger state-map.md and invariants.mdgithub.com↩
Series · Part 5 of 6

Deterministic Verification

  1. 1Event Sourcing
  2. 281.2 Nanoseconds: Designing an Always-On Production Flight Recorder
  3. 3Why Coding Agents Write Narrow Fixes (And Why Logs Won't Save Them)
  4. 4The Hidden Tests Pass. The Contract Doesn't.
  5. 5What Invariants Should My Service Have?
  6. 6How to Read a Kavach Strip Chart
← Part 4Part 6 →
  • invariants
  • coding agents
  • mutation testing
  • replay

On this page

  1. Why deterministic replay matters for invariants
  2. Challenges of writing invariants with agents

Quick links

  • 1Antithesis skills for agents
  • 2Kavach Agent Skills
  • 3Wallet Ledger state-map.md and invariants.md
Ask ChatGPTAsk ClaudeStar on GitHub

Keep reading

  • How to Read a Kavach Strip ChartGuides4 minOct 19, 2026
  • The Hidden Tests Pass. The Contract Doesn't.Product4 minOct 18, 2026
  • Why Coding Agents Write Narrow Fixes (And Why Logs Won't Save Them)Engineering4 minOct 16, 2026