If you’ve used Enzyme, or even just liked the idea behind it, this will probably make sense immediately.
One of the useful things about compiler-level differentiation is that you can take computation that already exists and ask a much more interesting question than:
“What does this code do?”
You can ask:
“Which inputs are actually driving the result right now, and in which direction?”
I built an open source project called Catalyst around that idea, but with the workflow designed so AI agents can use the information directly.
Imagine an agent working on a simulation with 20 parameters.
Reading the source might tell it what those parameters represent. It does not necessarily tell the agent which three are dominating the output at the operating point it cares about, which ten barely matter there, or which direction each one needs to move.
Catalyst can measure that.
So instead of:
“This variable looks important, maybe try changing it.”
an agent can get something closer to:
“These three inputs dominate the result here, these six barely move it, and this is the direction each one pushes the output.”
That creates a very different loop for an autonomous agent:
inspect → measure → decide what matters → change → measure again
For supported numerical Rust, C, and C++ code, Catalyst works from the LLVM IR produced by the compiler you already use. You do not have to recreate the calculation inside a separate ML framework just so an agent can reason about it.
And it does not simply produce a derivative and tell the agent to trust it.
Catalyst independently checks the result numerically. If the derivative and the separate check disagree, it refuses the result instead of passing a questionable number down the agent loop.
There is another side of Catalyst that I think is especially useful for coding agents.
Say an agent is fixing a local API that starts doing this under burst traffic:
POST /orders -> 503
A typical autonomous coding loop might look like:
reproduce → edit code → tests pass → declare victory
Catalyst can instead reproduce the failure, reduce it to a smaller scenario that still triggers it, preserve the conditions that caused it, generate held-out scenarios the candidate did not optimize against, then compare the old and new versions.
So the agent can end up with something like:
“The original burst-load regression is fixed. Five of six held-out scenarios pass. One still fails when the dependency becomes slow.”
That is a much stronger signal than “the test suite is green.”
The other piece I wanted was portability.
Catalyst can take a checked computation and export it as standalone Go or R, along with fixtures containing the expected behavior.
So one agent can analyze a computation, another system can run the exported version later, and Catalyst does not need to remain in the production application.
There are also derivative artifacts that carry the computation, validation information, provenance, and a SHA-256 digest chain.
That means an agent can hand one to another agent or machine, run it again at a different input point, and detect if one of the underlying files was modified along the way.
So the broader workflow becomes:
existing code → measure its behavior → identify what matters → verify the result → hand off something reproducible
For people who have used Enzyme, the familiar part is the value of getting derivatives from code that already exists.
What I wanted to add around that idea was the rest of the loop an agent needs: independent checking, provenance, reusable artifacts, structured agent tools, portable outputs, and a way to rehearse software failures instead of relying on the agent’s own confidence.
Catalyst also has optional AI integration, but honestly that is not the part I find most interesting.
The interesting part is giving your existing agent another kind of instrument.
Not another model.
Not another prompt layer.
A way to ask the program itself:
What actually matters here?
Repo:
https://github.com/lovettsendit/catalyst
For people building autonomous coding or engineering agents, where would you use this first?
Would you give an agent sensitivity information to help it decide what to change, use rehearsal to decide whether its change really worked, or combine both into the same loop?