
Today, Mistral AI released Leanstral 1.5. It is a code agent model built for Lean 4. The release targets automated theorem proving and proof engineering. Weights are open under Apache 2.0. A free API endpoint, leanstral-1-5, is now live.
Leanstral 1.5 updates the earlier Leanstral-2603 model. It belongs to the Mistral Small 4 family.
What is Leanstral 1.5
Leanstral 1.5 is a code agent model for Lean 4, a proof assistant. A proof assistant checks every logical step mechanically. Lean 4 can express objects like perfectoid spaces and properties of Rust fragments.
The architecture is a mixture-of-experts, or MoE. An MoE routes each token to a few specialized sub-networks. This keeps compute low while total capacity stays large. Leanstral uses 128 experts, with 4 active per token.
Total size is 119B parameters, with 6.5B activated per token. Context length is 256k tokens. Input is multimodal, accepting text and image. Output is text only.
How Mistral Trained Leanstral 1.5
Training runs in three stages. These are mid-training, supervised fine-tuning, then reinforcement learning with CISPO. Two reinforcement-learning environments shaped the model’s agentic behavior.
In the multiturn environment, the model receives a theorem statement. It must prove or disprove it. It submits a proof, then reads Lean compiler feedback. It refines across attempts until it succeeds or exhausts its budget.
In the code agent environment, Leanstral works inside a raw filesystem. It edits files, runs bash commands, and uses the Lean language server. That server exposes goals, errors, and type information in real time.
This lets it complete partial proofs, build auxiliary lemmas, and persist through context compaction. Compaction compresses earlier context so long tasks still fit the window. Correctness is verified by Mistral’s fork of SafeVerify against target theorems.
Benchmarks and Performance
Mistral team reports that Leanstral 1.5 saturates miniF2F. It reaches 100% on both the validation and test sets. It solves 587 of 672 PutnamBench problems.
The model sets a new state-of-the-art on the FATE-H and FATE-X algebra benchmarks. Mistral lists 87% on FATE-H and 34% on FATE-X. On FLTEval, pass@1 rises from 21.9 to 28.9. Pass@8 rises from 31.9 to 43.2.
FLTEval is built from real pull requests to the Fermat’s Last Theorem repository. On it, Leanstral surpasses Opus 4.6’s 39.6 at one-seventh the cost. It also widens its lead over open-source models three to ten times larger. Pass@8 means eight attempts are allowed per problem.
| Benchmark | Leanstral 1.5 | Detail |
|---|---|---|
| miniF2F (val + test) | 100% | Saturated, per Mistral |
| PutnamBench | 587 / 672 | ~$4 per problem |
| FATE-H | 87% | New state-of-the-art |
| FATE-X | 34% | New state-of-the-art |
| FLTEval pass@1 | 28.9 | Up from 21.9 |
| FLTEval pass@8 | 43.2 | Beats Opus 4.6’s 39.6 |
On PutnamBench, Leanstral edges Seed-Prover 1.5 high by 7 problems. It does so at about $4 per problem. Mistral estimates Seed-Prover’s high setting near $300 or more per problem.
That setting runs a budget of 10 H20-days per problem. Mistral also compares against Goedel-Architect and AxProverBase. It notes Aleph Prover costs roughly $54 to $68 per problem.
Test-time scaling is the model’s defining behavior. Raising the token budget per attempt lifts PutnamBench Pass@8. Mistral team reports 44 solved at 50k, 244 at 200k, 493 at 1M, and 587 at 4M. The interactive explorer below lets you scrub across that same curve.
‘ + b.name + ‘
‘ +
‘
‘ + b.desc + ‘
‘ + b.score + ‘
‘ +
”;
bg.appendChild(el);
});
var benchAnimated = false;
function animateBench() {
root.querySelectorAll(‘#lsx-bench-grid .lsx-bar > i’).forEach(function (i) {
i.style.width = i.getAttribute(‘data-pct’) + ‘%’;
});
benchAnimated = true;
}
// —- Cost —-
var costs = [
{ who: ‘Leanstral 1.5’, sub: ‘~$4 / problem’, val: 4, cls: ‘lsx-hero’, label: ‘~$4’ },
{ who: ‘Aleph Prover’, sub: ‘$54–68 / problem’, val: 61, cls: ‘lsx-mid’, label: ‘~$61’ },
{ who: ‘Seed-Prover 1.5 high’, sub: ’10 H20-days / problem’, val: 300, cls: ‘lsx-high’, label: ‘$300+’ }
];
var cr = root.querySelector(‘#lsx-cost-rows’);
costs.forEach(function (c) {
var row = document.createElement(‘div’);
row.className=”lsx-cost-row”;
row.innerHTML = ‘
‘ + c.who + ‘‘ + c.sub + ‘
‘ +
” +
‘
‘ + c.label + ‘
‘;
cr.appendChild(row);
});
function animateCost() {
root.querySelectorAll(‘#lsx-cost-rows .lsx-cost-track > i’).forEach(function (i) {
var v = +i.getAttribute(‘data-val’);
var w = (Math.log10(v) / Math.log10(300)) * 100; // log scale, 300 = full
i.style.width = Math.max(w, 8) + ‘%’;
});
}
// —- Proof loop —-
var steps = [
{ t: ‘Theorem statement’, d: ‘The model receives a goal in Lean 4 and must prove or disprove it.’ },
{ t: ‘Model submits a proof’, d: ‘Leanstral drafts a candidate proof term or tactic block.’ },
{ t: ‘Lean compiler checks it’, d: ‘The proof is compiled. Errors, goals, and types are returned.’ },
{ t: ‘Refine and retry’, d: ‘If it fails, the model reads feedback and revises its approach.’ },
{ t: ‘Proof compiles’, d: ‘On success the loop ends. Otherwise it continues until budget runs out.’ }
];
var ls = root.querySelector(‘#lsx-loop-steps’);
steps.forEach(function (s, i) {
var el = document.createElement(‘div’);
el.className=”lsx-step”;
el.innerHTML = ‘
‘ + (i + 1) + ‘
‘;
ls.appendChild(el);
});
var stepEls = ls.querySelectorAll(‘.lsx-step’);
var attempt = 0, cur = -1, done = false;
var runBtn = root.querySelector(‘#lsx-loop-run’);
var statusEl = root.querySelector(‘#lsx-loop-status’);
function renderLoop() {
stepEls.forEach(function (e, i) { e.classList.toggle(‘on’, i === cur); });
}
runBtn.addEventListener(‘click’, function () {
if (done) return;
cur++;
if (cur === 2) attempt++;
if (cur >= steps.length – 1) {
// reaching “proof compiles” — succeed on attempt 3 for illustration
if (attempt >= 3) {
cur = steps.length – 1; done = true;
statusEl.innerHTML = ‘Proof compiled after ‘ + attempt + ‘ attempts. Verified by SafeVerify.’;
} else {
cur = 3; // refine and retry
statusEl.textContent=”Attempt ” + attempt + ‘ failed. Reading compiler feedback, refining…’;
}
} else {
statusEl.textContent=”Attempt ” + attempt + ‘ — step ‘ + (cur + 1) + ‘ of ‘ + steps.length + ‘.’;
}
renderLoop(); pushHeight();
});
root.querySelector(‘#lsx-loop-reset’).addEventListener(‘click’, function () {
attempt = 0; cur = -1; done = false;
statusEl.textContent=”Ready. Attempt 0 of budget.”;
renderLoop(); pushHeight();
});
// —- Auto-resize for WordPress —-
function pushHeight() {
var h = root.offsetHeight + 40;
if (window.parent) {
window.parent.postMessage({ type: ‘lsx-resize’, height: h }, ‘*’);
}
}
window.addEventListener(‘load’, function () { animateBench(); pushHeight(); });
window.addEventListener(‘resize’, pushHeight);
setTimeout(pushHeight, 300);
})();






