AI Engineer World's Fair 2026

Your Code Has Bugs. Lean4 Has Proofs: Formal Verification for Engineers — Varun Pant, AWS

Varun Pant· AWS10:06

Read the talk

Your Code Has Bugs. Lean4 Has Proofs: Formal Verification for Engineers

Varun Pant explains how specifications, machine-generated proofs, and small independent checkers fit together—and how verification changes when production code lives in Rust rather than Lean.

From a talk by Varun Pant

At a glance

Ideas worth remembering

  • A proof establishes that code satisfies its specification. Validate what the specification means before generating implementation and proof.

  • Tactics construct proofs through search and backtracking; a small independent kernel checks the completed argument.

  • Cedar compares production Rust with a Lean model using about 100 million differential random tests nightly. Verus and Aeneas provide different routes toward deductive verification of Rust.

  • Start with critical code and a concrete property you can explain, then let the agent implement it and the verification tool prove it.

Define correctness before asking a machine to prove it

Coding agents can produce hundreds or thousands of pull requests a week. Checking that output creates a different bottleneck: an LLM judge gives a probabilistic assessment, tests exercise selected inputs, and human review struggles to keep pace. Varun Pant, who builds AI products and leads formal-verification teams at AWS, introduces formal verification as a way to prove that an implementation satisfies a specified property across every input covered by that property. 0:12

The first engineering task is to write what “correct” means. In the spec-driven workflow Pant introduces with Kiro, a human can write a formal specification directly in Lean or write natural-language requirements that an AI formalizes. The specification then needs validation: someone reviews it, or tests whether it describes the expected behavior on concrete inputs. A proof establishes agreement with the specification; a mistaken specification can therefore produce a proved implementation of the wrong requirement.

That order matters because the specification sits upstream of both implementation and verification. It remains a “living, breathing artifact” that the builder works with as requirements develop. Once its meaning is settled, the coding agent implements it and the verification tool proves the implementation matches it. Pant’s division of labor is compact: “humans own the specification, and machines own the code and proof.”

Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

0:12 · section reference included

One language holds the function and its theorem

Lean is both a programming language and a proof assistant. Definitions and proofs use the same language, so a Lean implementation does not need a separate translation into a proof language. Pant also emphasizes extensibility—Lean is implemented in Lean—and a small trusted kernel that checks proofs. Proofs can be exported for independent checking.

List reversal supplies the first concrete example. Reversing [1, 2, 3] produces [3, 2, 1]. The accompanying theorem describes how reversal interacts with concatenation: reversing A followed by B gives the reverse of B followed by the reverse of A. Here, the talk’s “plus” means joining lists, rather than adding their elements.

To see the change, split that same list into A = [1, 2] and B = [3]. Concatenation places the A block before the B block. Reversing the combined list moves the B block to the front and reverses the order inside A, yielding [3, 2, 1]. Reversing the blocks separately and joining them in the opposite order produces the same result: [3] ++ [2, 1]. This instance makes the property visible; the theorem expresses it for every pair of lists, rather than only these three elements.

Tactics construct the proof, and the kernel checks it. This separation provides a way to accept machine-generated proofs: the machine searches for an argument, while a much smaller component checks whether that argument establishes the theorem.

2:112:33
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

2:11 · section reference included

Search like chess, then check the result independently

Pant’s analogy is chess. The theorem is the goal, like checkmate; tactics are the moves used to reach it. Proof construction is interactive and branches into a search tree. A tactic may advance the proof, but a branch can also leave a goal unresolved. The prover then backtracks and tries another route. A plausible sequence of moves alone does not finish the job: the resulting proof must pass the kernel.

The kernel rejects an incorrect proof in Pant’s example. Confidence in the generator therefore does not substitute for checking its output. Pant describes open-source kernel implementations in C++, Rust, and Lean, and the possibility of writing an independent checker yourself. The trusted component remains the checker, even when proof search becomes large or complicated. 4:03

Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

3:16 · section reference included

A compression round trip becomes 32,000 lines of proof

The next example puts both specification and implementation in Lean. Pant describes an open-source project in which AI converted zlib, the C compression library, to Lean over about a week. Its natural-language requirement is easy to understand: decompressing compressed data should return the original data. Written as an intended property, the round trip is decompress(compress(data)) = data. The Lean theorem in Leo de Moura’s separate May 6, 2026 NFM presentation proves that round trip across compression levels for inputs satisfying data.size < 1024 * 1024 * 1024: strictly below 1 GiB. The proved claim therefore includes an input-size precondition that the plain-language requirement leaves unstated. 4:41

The AI first turns that requirement into a formal specification. After the specification is checked, it writes the Lean code and breaks the proof into helper lemmas—smaller claims that serve as subgoals. Tactics prove those claims, the claims assemble into the final theorem, and the independent kernel checks the result. Pant reports 32,000 lines of proof for this example. That quantity describes the proof artifact, rather than a count of test cases.

How does one readable requirement lead to such a large proof? The flow below separates the initial decision about meaning from the generated implementation and proof. Specification validation comes first. The AI then expands the problem into code and lemmas, and the kernel checks the assembled argument. The checker’s position at the end explains why validating the requirement cannot be delegated to proof checking.

How it fits togetherFrom round-trip requirement to checked theorem

Decompressing compressed data returns the original data.

Validation precedes implementation. Helper lemmas divide the proof into manageable claims; the kernel checks their assembled result. The theorem in Leo de Moura’s separate NFM presentation, rather than one shown in Pant’s recording, covers inputs strictly below 1 GiB across compression levels.

Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

4:30 · section reference included

Cedar connects Lean semantics to production Rust

Production code can stay in Rust while Lean supplies its functional specification. Cedar, an open-source authorization policy language, illustrates this arrangement: its specification is written in Lean and its production implementation runs in Rust. The critical example is “forbid trumps permit.” Whenever a forbid policy is satisfied, the request must be denied, even when permission would otherwise be available. 5:58

The connection between the two implementations uses differential random testing. Each generated input goes to both the Rust production code and the Lean model, and their outputs are compared. Pant reports about 100 million such tests nightly and says no version ships until the agreement requirement is satisfied. This checks the Rust implementation against the formal model on sampled inputs; it does not establish a deductive proof that the Rust code agrees with the model for every input.

The practical choice is to keep a shipping implementation in Rust and use a Lean model as the reference for its behavior. For the forbid example, agreement means both paths return denial for the same request and policies. A difference exposes a disagreement that must be resolved before release. The model gives testing a precise expected result, rather than requiring each test author to invent one.

Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

5:58 · section reference included

Two routes from Rust to deductive verification

Deductive verification offers another way to work with Rust. Before introducing the tools, Pant distinguishes a solver from Lean’s interactive proof search. Lean resembles a chessboard on which tactics advance a goal. A solver resembles a powerful calculator: it receives a formula and answers whether that formula is satisfiable or unsatisfiable—whether its constraints can hold together. 6:59

  • Verus: specifications alongside code. Verus uses Z3 to verify Rust code with annotations expressing preconditions and postconditions. A precondition states what must hold before the operation; a postcondition states what must hold afterward. These specifications are checked statically by the verifier and erased at runtime, so they do not become runtime assertions.

  • Aeneas: translate Rust into Lean. Aeneas starts from Rust’s mid-level intermediate representation and translates it into a functional form in Lean. The translated program can then use the theorem-proving approach introduced earlier: goals, tactics, and checked proofs.

These paths place the specification in different working environments. Verus keeps it close to the Rust code and uses a solver; Aeneas brings a functional translation into Lean for theorem proving. Both differ from Cedar’s differential-testing arrangement, where the production program and model are run on matching inputs and their outputs compared.

Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

6:59 · section reference included

Lower different languages into a shared verification core

The final technical proposal extends the compiler idea beyond Rust. Pant describes Strata, an open-source AWS tool. A language-specific dialect represents a program at a high level, then lowers it into Strata Core, a common low-level representation written in Lean. The intended architecture lets that representation feed different verification engines: Lean proofs, SMT solvers, or model checkers. The architecture documentation describes the implemented analysis as a verification-condition generator with an SMT interface; broader Lean reasoning and other engine integrations remain architectural goals. Support for arbitrary languages is likewise the intention of this work in progress, rather than a claim that every language is already supported. 8:26

What does a shared core buy? The diagram shows where language-specific work ends and analysis begins, distinguishing the implemented SMT route from proposed engine choices. Each language needs a dialect and lowering path, but the resulting program reaches the same core. That common representation allows an analysis to be reused across languages, with additional engines intended to extend the choice of verification method.

The closing recommendation starts smaller than that infrastructure: pick your most critical code and write what correct means. Pant points to using Lean in a browser, then having a coding agent implement the specification and a verification tool prove the result. A useful first target is a property whose meaning you can inspect and care about—a compression round trip or a denial rule—before asking a machine to expand it into a proof. That is the route toward the ending’s ambition of software that is “provably correct.” 9:17

How it fits togetherA shared core supports reusable analysis

Represents a source program in a high-level intermediate form.

Language-specific translation precedes Strata Core. The documented implementation generates verification conditions and interfaces with SMT solvers; broader Lean reasoning and model-checker routes are architectural goals.

Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

8:26 · section reference included

Resources

From the talk

  • The project README provides prerequisites, build commands, and an example verification invocation for experimenting with Strata. This is a practical next step for the shared-core proposal, separate from the talk’s invitation to try Lean in a browser.

  • Explains dialect definitions, composition, transformations, and Strata Core. It distinguishes the broader engine architecture from the implemented verification-condition generator and SMT interface.

Read the complete timestamped transcript
  1. 0:01

    [music]

  2. 0:12

    >> Coding agents are generating more code

  3. 0:15

    than ever.

  4. 0:16

    Builders are generating hundreds and

  5. 0:18

    thousands of PRs every week.

  6. 0:21

    How do you know that this is correct?

  7. 0:24

    Using LM as a judge for the code? Well,

  8. 0:26

    that's probabilistic.

  9. 0:29

    Tests?

  10. 0:30

    They only check some inputs, not all.

  11. 0:33

    Human code review doesn't scale to match

  12. 0:35

    agent speed.

  13. 0:37

    None of these can say for all inputs the

  14. 0:40

    code is correct.

  15. 0:42

    Formal verification can.

  16. 0:44

    Hi, I'm Varun Pant. I build AI products

  17. 0:46

    at AWS leading teams at in formal

  18. 0:49

    verification.

  19. 0:51

    Formal verification provides

  20. 0:53

    mathematical proof that code is correct.

  21. 0:56

    For all inputs.

  22. 0:57

    You write what correct means, which is

  23. 0:59

    the specification, and a formal

  24. 1:01

    verification tool proves that your code

  25. 1:04

    satisfies it.

  26. 1:05

    If the proof passes, it holds for every

  27. 1:08

    possible input.

  28. 1:11

    How do you use this?

  29. 1:13

    Well, one way is back driven

  30. 1:15

    development, for example, with Kiro.

  31. 1:19

    You write what the specification is,

  32. 1:21

    which is what correct means.

  33. 1:23

    Either you write it formally, for

  34. 1:25

    example, directly in Lean, or you write

  35. 1:27

    it in natural language, and you let the

  36. 1:29

    AI auto formalize it.

  37. 1:32

    Now, this is really important. You then

  38. 1:34

    validate the specification. So, either

  39. 1:36

    the human reviews it, or you test that

  40. 1:39

    it holds on some inputs. And this is

  41. 1:41

    important because the specification is

  42. 1:43

    upstream. It's a living, breathing

  43. 1:45

    artifact that the builder interacts

  44. 1:47

    with. You want this to be correct.

  45. 1:49

    Everything else is downstream from this.

  46. 1:52

    The AI coding agent then goes and

  47. 1:54

    implements from the specification.

  48. 1:57

    And the formal verification tool proves

  49. 2:00

    that the implementation matches the

  50. 2:01

    specification.

  51. 2:04

    So, humans own the specification and

  52. 2:06

    machines own the code and proof.

  53. 2:10

    Lean is a programming language and a

  54. 2:12

    proof assistant.

  55. 2:14

    It is the same language for the

  56. 2:16

    definitions and proofs. There's no

  57. 2:18

    translation layer.

  58. 2:20

    It is implemented in Lean, which means

  59. 2:22

    it's very extensible. And this is

  60. 2:24

    important. It has a small trusted

  61. 2:26

    kernel.

  62. 2:27

    Proofs can be exported and independently

  63. 2:29

    checked.

  64. 2:33

    So, here's an example of a Lean file

  65. 2:36

    which has both the code and proof in the

  66. 2:38

    same language. At the top, you'll see

  67. 2:40

    the code, which is a function that

  68. 2:42

    reverses a list in Lean. So, reverse of

  69. 2:45

    one, two, and three gives three, two,

  70. 2:46

    and one.

  71. 2:47

    And right in the middle, you'll see a

  72. 2:49

    theorem. This is the proof.

  73. 2:52

    And this theorem prover approves a

  74. 2:55

    property which says that reverse of A

  75. 2:57

    plus B is in fact reverse of B plus

  76. 2:59

    reverse of A.

  77. 3:00

    And this holds for every possible input.

  78. 3:04

    How do you do this? You have something

  79. 3:06

    called as tactics which do the work,

  80. 3:07

    which we'll get to in a second. And the

  81. 3:09

    kernel, remember the small trusted

  82. 3:11

    kernel?

  83. 3:12

    That checks the work.

  84. 3:16

    A good analogy to understand the Lean

  85. 3:17

    proof assistant is that of chess. So, in

  86. 3:20

    chess, your goal is to checkmate the

  87. 3:22

    opponent. And you make a bunch of moves.

  88. 3:24

    You move the knight, you move the

  89. 3:26

    bishop.

  90. 3:27

    Similarly, in Lean, you have a bunch of

  91. 3:30

    tactics which are your moves. And it's

  92. 3:33

    the same chess board. It's interactive.

  93. 3:36

    You want to prove the goal, the theorem,

  94. 3:38

    checkmate. And you're kind of going down

  95. 3:41

    a tree. So, you're traversing the tree,

  96. 3:43

    you're trying different tactics. Maybe

  97. 3:45

    for some goals, you're not able to prove

  98. 3:47

    it, so you backtrack and then you try

  99. 3:49

    another a branch of the tree. Very

  100. 3:51

    similar to chess.

  101. 3:53

    And finally, you get a goal that

  102. 3:55

    hopefully proves the theorem, and then

  103. 3:57

    that small independent kernel confirms

  104. 4:00

    and checks it.

  105. 4:03

    The kernel catches the mistake. So,

  106. 4:05

    here's an example at the top where an

  107. 4:07

    incor- incorrect proof is rejected

  108. 4:10

    immediately. And you only need to trust

  109. 4:12

    the small kernel.

  110. 4:14

    The good thing is that you can have

  111. 4:16

    multiple independent kernels. You

  112. 4:17

    yourself can actually go write one. It's

  113. 4:19

    completely open source. You have kernels

  114. 4:21

    in C++, Rust, Lean. That's uh a link to

  115. 4:25

    the Arena Lang where you can go and add

  116. 4:28

    a kernel.

  117. 4:30

    So, let's look at some examples where

  118. 4:32

    you can put this to practice. The first

  119. 4:35

    one is having the specification and code

  120. 4:38

    both being in Lean.

  121. 4:41

    Now, this is open source Andreo. AI

  122. 4:44

    converted zlib, which is a C compression

  123. 4:46

    library, to Lean. Now, granted this

  124. 4:48

    happened over a week or so.

  125. 4:52

    But, kind of going back to our

  126. 4:54

    specification methodology that we

  127. 4:57

    mentioned where you had specification at

  128. 4:58

    the top and then verification for the

  129. 5:00

    code, we'll kind of see the same thing

  130. 5:02

    here. So, the natural language

  131. 5:04

    specification says that you decompress

  132. 5:06

    the output

  133. 5:08

    of compress returning the original data.

  134. 5:11

    And then, you have an AI that generates

  135. 5:13

    the formal spec. Now, remember this is

  136. 5:15

    important. Checking the specification is

  137. 5:17

    key.

  138. 5:19

    After you do that, the AI goes and

  139. 5:21

    writes your code in Lean, and then

  140. 5:23

    generates these helper lemma subgoals,

  141. 5:26

    and proves the theorem.

  142. 5:28

    And at the bottom, you can see that it's

  143. 5:30

    verified with that small independent

  144. 5:32

    kernel.

  145. 5:34

    So, what you just saw was that AI

  146. 5:36

    decomposed the problem into lemmas,

  147. 5:38

    which are subgoals. It proved each of

  148. 5:40

    them using tactics. Remember the chess

  149. 5:42

    moves that we were making?

  150. 5:44

    And it assembled it into a final

  151. 5:46

    theorem.

  152. 5:47

    Checkmate.

  153. 5:49

    And the kernel checked it.

  154. 5:51

    And this particular example had 32,000

  155. 5:54

    lines of proof. So, it was

  156. 5:55

    pretty big.

  157. 5:58

    Let's take another example. What if you

  158. 6:00

    have code in Rust? Well, you can write

  159. 6:02

    the functional specification of it or

  160. 6:04

    the model in Lean.

  161. 6:06

    An example of that is Cedar.

  162. 6:08

    Cedar is an open-source authorization

  163. 6:11

    policy language, which is used by AWS

  164. 6:13

    verified permissions and access.

  165. 6:15

    The specification of Cedar is written in

  166. 6:18

    Lean. The production code runs in Rust.

  167. 6:22

    Why is this important? Because

  168. 6:24

    let's take an example. You have forbid

  169. 6:26

    Trump's permit. You want to make sure

  170. 6:28

    that for any forbid policy being

  171. 6:30

    satisfied, the request is always denied.

  172. 6:32

    This is key.

  173. 6:36

    Here you can see the example of what I

  174. 6:37

    was talking about, which is you have the

  175. 6:39

    Rust production code and you have the

  176. 6:41

    functional specification in Lean, and

  177. 6:43

    you run differential random testing to

  178. 6:45

    check that both of those for the same

  179. 6:47

    inputs give the same output.

  180. 6:50

    And there's about 100 million

  181. 6:51

    differential random tests uh run

  182. 6:53

    nightly.

  183. 6:54

    No version ships until this is

  184. 6:56

    satisfied.

  185. 6:59

    Let's take another example. What if you

  186. 7:01

    have code in Rust and you want to

  187. 7:03

    deductively verify with Lean or solvers?

  188. 7:07

    Before we go there, let's quickly talk

  189. 7:09

    about this new term solvers. So,

  190. 7:11

    remember we spoke of Lean being this

  191. 7:13

    chessboard interactive where you're

  192. 7:15

    making a bunch of moves trying to

  193. 7:16

    checkmate.

  194. 7:17

    A solver is a calculator, a very

  195. 7:20

    powerful one. You feed in a formula and

  196. 7:23

    it returns an output. In this case,

  197. 7:26

    satisfiable or unsatisfiable.

  198. 7:30

    So, an example of this is Verus, also an

  199. 7:33

    open-source tool.

  200. 7:35

    It uses this solver, this very powerful

  201. 7:37

    calculator, Z3.

  202. 7:39

    And if folks are familiar with adding

  203. 7:42

    annotations, it's kind of similar to

  204. 7:43

    that where you can add specifications in

  205. 7:46

    the form of that. And the code is in

  206. 7:49

    line. So, you see these two requires and

  207. 7:52

    ensure keywords, that's what we call a

  208. 7:54

    pre and post condition. What must be

  209. 7:57

    true before and what must be true after.

  210. 8:01

    And this is a static check. It's

  211. 8:02

    enforced by the verifier and erased at

  212. 8:05

    runtime. So, almost like ghost code.

  213. 8:09

    Another example of this is Eneus,

  214. 8:12

    which uses the mid-level intermediate

  215. 8:14

    representation for Rust and does a

  216. 8:16

    functional translation to Lean. And

  217. 8:18

    right after that, you use the same

  218. 8:20

    theorem prover, the same chessboard that

  219. 8:21

    we spoke of.

  220. 8:26

    Now, you may be asking, well, what if I

  221. 8:28

    have any programming language?

  222. 8:32

    We at AWS have been working on an

  223. 8:34

    open-source tool called Strata. This is

  224. 8:37

    work in progress, but the idea is that

  225. 8:40

    you can have any programming language

  226. 8:42

    and you yourself can create what we call

  227. 8:44

    a dialect.

  228. 8:46

    Think of this like a compiler. You have

  229. 8:48

    a high-level intermediate representation

  230. 8:50

    and you lower it down to a low-level

  231. 8:51

    intermediate representation, which is

  232. 8:53

    what Strata core is. Now, this is

  233. 8:56

    written in Lean.

  234. 8:58

    After you have all of these programs

  235. 9:00

    talking in the same language, which is

  236. 9:02

    the Strata core, you can dispatch it to

  237. 9:04

    any of the engines. For example, the

  238. 9:06

    Lean proof, remember the chessboard, or

  239. 9:09

    the very powerful calculator, SMT

  240. 9:11

    solvers, or model checkers.

  241. 9:17

    So, you can get started with this today.

  242. 9:19

    You can go to Lean in in your browser

  243. 9:22

    with the link I pasted, and you can pick

  244. 9:25

    your most critical code,

  245. 9:27

    write what correct means, which is the

  246. 9:28

    specification, which is very important,

  247. 9:31

    and then you can let your coding agent

  248. 9:32

    implement it and your formal

  249. 9:34

    verification tool prove it.

  250. 9:38

    So, hopefully in this brave new world,

  251. 9:41

    we have software and systems that are

  252. 9:43

    not probably correct, but probably

  253. 9:45

    correct. Thank you.

  254. 10:01

    >> [music]