AI Engineer World's Fair 2026
Your Code Has Bugs. Lean4 Has Proofs: Formal Verification for Engineers — Varun Pant, AWS
Read the talk
Your Code Has Bugs. Lean Has Proofs.
Varun Pant explains how explicit specifications, machine-generated proofs, and a small trusted kernel can strengthen confidence in agent-written code—and where testing and human judgment still matter.
From a talk by Varun Pant
At a glance
Ideas worth remembering
A proof establishes that code satisfies its formal specification. Human ownership remains essential because the specification determines what the proof guarantees.
Lean separates proof construction from proof checking: tactics explore possible solutions, while a small trusted kernel checks the resulting proof.
The zlib example illustrates proof decomposition at scale: Pant reports roughly a week of AI work and 32,000 lines of proof supporting a compression round-trip property.
A verified model and a production implementation have a separate agreement problem. Cedar addresses that connection through approximately 100 million nightly differential random tests, which remain sampled checks rather than universal equivalence proof.
Adoption can begin with critical code and explicit contracts. The talk presents several routes: implementation directly in Lean, Rust contracts checked with Verus and Z3, translation into Lean, and Strata’s developing shared-core architecture.
What does it mean to know the code is correct?
Coding agents increase the amount of code engineers must assess. Varun Pant, who builds AI products and leads teams in formal verification at AWS, opens with builders generating hundreds and thousands of pull requests each week. A language model judging that code gives a probabilistic assessment. Tests check selected inputs. Human review struggles to match agent throughput. These checks do not establish that an implementation behaves correctly for every possible input.
Formal verification changes the question into a mathematical claim. First, write a specification that defines what correct means. Then prove that the implementation satisfies it. The resulting guarantee concerns the property expressed by that specification across its input domain. The specification is therefore part of the claim: proving that code satisfies a stated requirement does not independently establish that the requirement captures everything its users need.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Humans own the specification
Pant describes a development workflow centered on the specification, mentioning Kiro as an example. Engineers can write the specification formally, directly in Lean, or express it in natural language and ask an AI to formalize it. Either route produces the artifact that defines what the implementation must do.
The next step is to validate that artifact before building downstream from it. Pant proposes human review or checking that the specification holds on some inputs. Those checks help assess whether the specification expresses the intended behavior. This is why he calls it a living artifact that the builder interacts with: an error here can direct the entire implementation toward the wrong objective.
Once that definition is validated, the coding agent implements it and the verification tool proves that the implementation matches it. Pant assigns responsibility accordingly: humans own the specification; machines own the code and proof. Automation takes on implementation and proof construction while people remain responsible for deciding what behavior should count as correct.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
One language for definitions and proofs
Lean is both a programming language and a proof assistant. Its definitions and proofs use the same language, so this arrangement needs no separate translation layer between the program and its proof. Pant also emphasizes extensibility through Lean’s implementation in Lean, alongside a small trusted kernel. Proofs can be exported and checked independently.
His example is a function that reverses a list: reversing [1, 2, 3] produces [3, 2, 1]. The accompanying theorem states a general relationship: reversing the concatenation of lists A and B gives the reverse of B followed by the reverse of A. Written illustratively, reverse(A ++ B) = reverse(B) ++ reverse(A), where ++ means list concatenation. The concrete list demonstrates the function; the theorem establishes the stated relationship for every pair of lists in its domain.
Two mechanisms divide the work. Tactics help construct the proof, and the kernel checks the result. This distinction separates finding a way to establish a theorem from deciding whether the proposed proof actually establishes it.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Search for a proof, then check it
Pant uses chess to explain interactive proof construction. The theorem is the goal, analogous to checkmate, and tactics are the moves available to reach it. Trying tactics takes the prover through a tree of possibilities. If one branch leaves a goal that cannot be proved through that approach, the prover can backtrack and try another branch. The analogy captures why proof construction involves exploration rather than a single predetermined sequence.
A successful search still ends with a separate check by the small kernel. Pant describes an incorrect proof being rejected immediately: a proof-producing process cannot make its answer valid simply by presenting it confidently. Trust is concentrated in the checker. He points to independent kernel implementations in C++, Rust, and Lean, and notes that the open-source design allows someone to write another checker themselves.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
A compression property becomes 32,000 lines of proof
The first larger example keeps both specification and implementation in Lean. Pant reports that an AI converted zlib, a C compression library, to Lean over roughly a week. The requirement he presents is a round trip: decompressing the output of compression must return the original data. Illustratively, decompress(compress(data)) = data. That is the specific property at the center of this example; the presentation does not establish the scope of every other property of the converted library.
The workflow begins with that natural-language requirement, which an AI turns into a formal specification. Pant again stresses checking the specification before proceeding. The AI then writes the Lean implementation and generates helper lemmas: smaller claims that break the overall proof into manageable subgoals.
Each lemma is proved using tactics, and those results are assembled into the final theorem. The independent kernel checks the completed proof. Pant reports 32,000 lines of proof for this example, illustrating how a compact requirement can require a substantial body of supporting reasoning. The reported achievement is the construction and checking of that proof; its size alone does not tell us how broad the specification is.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Cedar connects a Lean model to production Rust
A second arrangement keeps production code in Rust and expresses its functional specification, or model, in Lean. Pant uses Cedar, an open-source authorization policy language, as the example. Its specification is written in Lean while its production implementation runs in Rust. The security property he highlights is that forbid takes precedence over permit: if any forbid policy is satisfied, the request must be denied.
Differential random testing connects these two implementations of the behavior. The same inputs are passed to the Rust production code and the Lean functional specification, and their outputs are compared. Pant says approximately 100 million such tests run nightly, with agreement required before a version ships. This allows the team to retain Rust in production while checking it against the Lean model. The connection described here is still testing over sampled inputs, so it does not constitute a proof that Rust and Lean agree for all inputs.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Verify Rust through contracts or translation
Pant next considers deductive verification of Rust using Lean or solvers. He distinguishes the interactive chessboard of Lean from a solver, which he compares to a powerful calculator: feed it a formula and it returns a satisfiable or unsatisfiable result. This introduces another way to handle verification obligations, with the solver performing the formula-solving work.
Verus is his concrete example of an open-source tool using the Z3 solver. Specifications appear alongside the code as preconditions and postconditions. A precondition states what must be true before the operation; a postcondition states what must be true afterward. This makes the assumptions part of the contract: the promised outcome is tied to the conditions under which the operation is verified.
These checks happen statically. The verifier enforces the specifications, and the specification code is erased at runtime—what Pant likens to ghost code. Its purpose is to support verification before execution rather than to remain as an executing runtime check.
He also describes a translation-based route from Rust to Lean. It takes Rust’s mid-level intermediate representation and produces a functional translation in Lean. Once that translation exists, the same Lean theorem prover can be used to reason about it. The mechanism provides a path into Lean’s proof environment, although the talk does not detail which Rust constructs the translation supports.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Read the complete timestamped transcript
- 0:01
[music]
- 0:12
>> Coding agents are generating more code
- 0:15
than ever.
- 0:16
Builders are generating hundreds and
- 0:18
thousands of PRs every week.
- 0:21
How do you know that this is correct?
- 0:24
Using LM as a judge for the code? Well,
- 0:26
that's probabilistic.
- 0:29
Tests?
- 0:30
They only check some inputs, not all.
- 0:33
Human code review doesn't scale to match
- 0:35
agent speed.
- 0:37
None of these can say for all inputs the
- 0:40
code is correct.
- 0:42
Formal verification can.
- 0:44
Hi, I'm Varun Pant. I build AI products
- 0:46
at AWS leading teams at in formal
- 0:49
verification.
- 0:51
Formal verification provides
- 0:53
mathematical proof that code is correct.
- 0:56
For all inputs.
- 0:57
You write what correct means, which is
- 0:59
the specification, and a formal
- 1:01
verification tool proves that your code
- 1:04
satisfies it.
- 1:05
If the proof passes, it holds for every
- 1:08
possible input.
- 1:11
How do you use this?
- 1:13
Well, one way is back driven
- 1:15
development, for example, with Kiro.
- 1:19
You write what the specification is,
- 1:21
which is what correct means.
- 1:23
Either you write it formally, for
- 1:25
example, directly in Lean, or you write
- 1:27
it in natural language, and you let the
- 1:29
AI auto formalize it.
- 1:32
Now, this is really important. You then
- 1:34
validate the specification. So, either
- 1:36
the human reviews it, or you test that
- 1:39
it holds on some inputs. And this is
- 1:41
important because the specification is
- 1:43
upstream. It's a living, breathing
- 1:45
artifact that the builder interacts
- 1:47
with. You want this to be correct.
- 1:49
Everything else is downstream from this.
- 1:52
The AI coding agent then goes and
- 1:54
implements from the specification.
- 1:57
And the formal verification tool proves
- 2:00
that the implementation matches the
- 2:01
specification.
- 2:04
So, humans own the specification and
- 2:06
machines own the code and proof.
- 2:10
Lean is a programming language and a
- 2:12
proof assistant.
- 2:14
It is the same language for the
- 2:16
definitions and proofs. There's no
- 2:18
translation layer.
- 2:20
It is implemented in Lean, which means
- 2:22
it's very extensible. And this is
- 2:24
important. It has a small trusted
- 2:26
kernel.
- 2:27
Proofs can be exported and independently
- 2:29
checked.
- 2:33
So, here's an example of a Lean file
- 2:36
which has both the code and proof in the
- 2:38
same language. At the top, you'll see
- 2:40
the code, which is a function that
- 2:42
reverses a list in Lean. So, reverse of
- 2:45
one, two, and three gives three, two,
- 2:46
and one.
- 2:47
And right in the middle, you'll see a
- 2:49
theorem. This is the proof.
- 2:52
And this theorem prover approves a
- 2:55
property which says that reverse of A
- 2:57
plus B is in fact reverse of B plus
- 2:59
reverse of A.
- 3:00
And this holds for every possible input.
- 3:04
How do you do this? You have something
- 3:06
called as tactics which do the work,
- 3:07
which we'll get to in a second. And the
- 3:09
kernel, remember the small trusted
- 3:11
kernel?
- 3:12
That checks the work.
- 3:16
A good analogy to understand the Lean
- 3:17
proof assistant is that of chess. So, in
- 3:20
chess, your goal is to checkmate the
- 3:22
opponent. And you make a bunch of moves.
- 3:24
You move the knight, you move the
- 3:26
bishop.
- 3:27
Similarly, in Lean, you have a bunch of
- 3:30
tactics which are your moves. And it's
- 3:33
the same chess board. It's interactive.
- 3:36
You want to prove the goal, the theorem,
- 3:38
checkmate. And you're kind of going down
- 3:41
a tree. So, you're traversing the tree,
- 3:43
you're trying different tactics. Maybe
- 3:45
for some goals, you're not able to prove
- 3:47
it, so you backtrack and then you try
- 3:49
another a branch of the tree. Very
- 3:51
similar to chess.
- 3:53
And finally, you get a goal that
- 3:55
hopefully proves the theorem, and then
- 3:57
that small independent kernel confirms
- 4:00
and checks it.
- 4:03
The kernel catches the mistake. So,
- 4:05
here's an example at the top where an
- 4:07
incor- incorrect proof is rejected
- 4:10
immediately. And you only need to trust
- 4:12
the small kernel.
- 4:14
The good thing is that you can have
- 4:16
multiple independent kernels. You
- 4:17
yourself can actually go write one. It's
- 4:19
completely open source. You have kernels
- 4:21
in C++, Rust, Lean. That's uh a link to
- 4:25
the Arena Lang where you can go and add
- 4:28
a kernel.
- 4:30
So, let's look at some examples where
- 4:32
you can put this to practice. The first
- 4:35
one is having the specification and code
- 4:38
both being in Lean.
- 4:41
Now, this is open source Andreo. AI
- 4:44
converted zlib, which is a C compression
- 4:46
library, to Lean. Now, granted this
- 4:48
happened over a week or so.
- 4:52
But, kind of going back to our
- 4:54
specification methodology that we
- 4:57
mentioned where you had specification at
- 4:58
the top and then verification for the
- 5:00
code, we'll kind of see the same thing
- 5:02
here. So, the natural language
- 5:04
specification says that you decompress
- 5:06
the output
- 5:08
of compress returning the original data.
- 5:11
And then, you have an AI that generates
- 5:13
the formal spec. Now, remember this is
- 5:15
important. Checking the specification is
- 5:17
key.
- 5:19
After you do that, the AI goes and
- 5:21
writes your code in Lean, and then
- 5:23
generates these helper lemma subgoals,
- 5:26
and proves the theorem.
- 5:28
And at the bottom, you can see that it's
- 5:30
verified with that small independent
- 5:32
kernel.
- 5:34
So, what you just saw was that AI
- 5:36
decomposed the problem into lemmas,
- 5:38
which are subgoals. It proved each of
- 5:40
them using tactics. Remember the chess
- 5:42
moves that we were making?
- 5:44
And it assembled it into a final
- 5:46
theorem.
- 5:47
Checkmate.
- 5:49
And the kernel checked it.
- 5:51
And this particular example had 32,000
- 5:54
lines of proof. So, it was
- 5:55
pretty big.
- 5:58
Let's take another example. What if you
- 6:00
have code in Rust? Well, you can write
- 6:02
the functional specification of it or
- 6:04
the model in Lean.
- 6:06
An example of that is Cedar.
- 6:08
Cedar is an open-source authorization
- 6:11
policy language, which is used by AWS
- 6:13
verified permissions and access.
- 6:15
The specification of Cedar is written in
- 6:18
Lean. The production code runs in Rust.
- 6:22
Why is this important? Because
- 6:24
let's take an example. You have forbid
- 6:26
Trump's permit. You want to make sure
- 6:28
that for any forbid policy being
- 6:30
satisfied, the request is always denied.
- 6:32
This is key.
- 6:36
Here you can see the example of what I
- 6:37
was talking about, which is you have the
- 6:39
Rust production code and you have the
- 6:41
functional specification in Lean, and
- 6:43
you run differential random testing to
- 6:45
check that both of those for the same
- 6:47
inputs give the same output.
- 6:50
And there's about 100 million
- 6:51
differential random tests uh run
- 6:53
nightly.
- 6:54
No version ships until this is
- 6:56
satisfied.
- 6:59
Let's take another example. What if you
- 7:01
have code in Rust and you want to
- 7:03
deductively verify with Lean or solvers?
- 7:07
Before we go there, let's quickly talk
- 7:09
about this new term solvers. So,
- 7:11
remember we spoke of Lean being this
- 7:13
chessboard interactive where you're
- 7:15
making a bunch of moves trying to
- 7:16
checkmate.
- 7:17
A solver is a calculator, a very
- 7:20
powerful one. You feed in a formula and
- 7:23
it returns an output. In this case,
- 7:26
satisfiable or unsatisfiable.
- 7:30
So, an example of this is Verus, also an
- 7:33
open-source tool.
- 7:35
It uses this solver, this very powerful
- 7:37
calculator, Z3.
- 7:39
And if folks are familiar with adding
- 7:42
annotations, it's kind of similar to
- 7:43
that where you can add specifications in
- 7:46
the form of that. And the code is in
- 7:49
line. So, you see these two requires and
- 7:52
ensure keywords, that's what we call a
- 7:54
pre and post condition. What must be
- 7:57
true before and what must be true after.
- 8:01
And this is a static check. It's
- 8:02
enforced by the verifier and erased at
- 8:05
runtime. So, almost like ghost code.
- 8:09
Another example of this is Eneus,
- 8:12
which uses the mid-level intermediate
- 8:14
representation for Rust and does a
- 8:16
functional translation to Lean. And
- 8:18
right after that, you use the same
- 8:20
theorem prover, the same chessboard that
- 8:21
we spoke of.
- 8:26
Now, you may be asking, well, what if I
- 8:28
have any programming language?
- 8:32
We at AWS have been working on an
- 8:34
open-source tool called Strata. This is
- 8:37
work in progress, but the idea is that
- 8:40
you can have any programming language
- 8:42
and you yourself can create what we call
- 8:44
a dialect.
- 8:46
Think of this like a compiler. You have
- 8:48
a high-level intermediate representation
- 8:50
and you lower it down to a low-level
- 8:51
intermediate representation, which is
- 8:53
what Strata core is. Now, this is
- 8:56
written in Lean.
- 8:58
After you have all of these programs
- 9:00
talking in the same language, which is
- 9:02
the Strata core, you can dispatch it to
- 9:04
any of the engines. For example, the
- 9:06
Lean proof, remember the chessboard, or
- 9:09
the very powerful calculator, SMT
- 9:11
solvers, or model checkers.
- 9:17
So, you can get started with this today.
- 9:19
You can go to Lean in in your browser
- 9:22
with the link I pasted, and you can pick
- 9:25
your most critical code,
- 9:27
write what correct means, which is the
- 9:28
specification, which is very important,
- 9:31
and then you can let your coding agent
- 9:32
implement it and your formal
- 9:34
verification tool prove it.
- 9:38
So, hopefully in this brave new world,
- 9:41
we have software and systems that are
- 9:43
not probably correct, but probably
- 9:45
correct. Thank you.
- 10:01
>> [music]