Intro0:00
In 2026, coding agents will quietly retire their first software platform. Not because it's bad, simply because the platform is unnecessary. I'm Dominik Tornow, I am founder and CEO of Resonate. Resonate is a durable execution platform built with minimalism and simplicity as its core technical values, and these properties will play a central role in this talk.
At Resonate, we have a working theory where software engineering is headed: general-purpose implementations will increasingly be replaced by bespoke implementations, generated on demand. Not as a new library, a new framework, or a new platform, but as a minimal extension of the infrastructure that is already in place.
The Vision0:32
If this theory holds true, reuse will move upstream. Instead of reusing a general-purpose implementation, we will reuse a specification, and we will derive a bespoke implementation from it.
In fact, we can build many bespoke implementations, tailor-made for the infrastructure that is already in place. We just have to ask the agent. At this point, the prompt is the platform.
Resonate is a durable execution platform. We have an implementation of the Resonate server. We have implementations of the Resonate SDK for TypeScript, Python, Rust, Go, and Java. So we have to ask: what does this new reality mean for us?
If implementations become generatable, where does our value live? And our answer: our value moves from implementation to specification.
Now, this changes how we think about Resonate. The product is no longer the implementation. The product is the specification, the protocol. And from that protocol, we want to derive multiple server implementations. One is the general-purpose Resonate server, our reference implementation.
Product Shift2:06
Others are implementations built with infrastructure partners. For customers and partners, this means durable executionright on top of their existing infrastructure, with minimal additional dependencies. So the question is no longer, can we build a server. The question is, can we repeatedly synthesize trusted servers from the same specification?
And if so, how?
When we talk about agentic engineering, we focus all of our attention on verification. How do we know the result is correct? But today, I want to focus on the specification instead. And more importantly, how can agents participate in specifying the system, not just building or verifying it?
Now, Resonate is partnering with multiple infrastructure providers to bring durable executions natively to their technology stack. One of them is Sunadia, the company behind NATS I/O, an open-source messaging system designed for building modern distributed systems. For the rest of this presentation, we will use Resonate on NATS I/O to explore our agentic engineering practices.
How do we go from specification to implementation? First, we need to level-set our mental model. This picture is a common view of agentic coding. There's an agent, there's a specification, and then there's an implementation. And for many applications, that is enough.
But it is not enough for what we are trying to do. Because we are not trying to generate one implementation from a specification.
We are trying to generate multiple target-specific implementations from the specification. So the specification must not take any aspect of an implementation into account. The specification must not assume a concrete database schema or concrete indices. The specification must not even assume a relational database with tables and transactions at all.
It must not assume a key-value store. It must not assume weak consistency. It must not assume strong consistency.
The specification must be abstract. Only the implementation must be concrete.
So we ask the agent to follow the abstract specification and generate a concrete implementation. Specifically, at first, we ask the agent, "Build a Resonate server in Rust on top of Postgres."
Trial & Error5:05
And the agent failed.
The gap between the abstract specification and the concrete implementation was too large. The agent generated a system that worked on the happy path. It passed the basic tests, but it was not correct. It broke on the concurrency. It broke on the process failure.
It broke on the network failure. The implementation was closer to a prototype, but not a production system.
So we amended the process. Instead of asking the agent to jump directly from abstract spec to concrete implementation, we inserted an intermediary artifact: the concrete specification. That concrete specification was derived interactively with the agent, but the human was the main driver.
For Postgres, that meant making target-specific decisions explicit: the data schema, the indices, the SQL queries, the transaction boundaries. Once those decisions were written down, the agent was indeed able to implement a production system. So this worked. But it also revealed the limitations.
The agent helped us build the system, but the agent did not help us design the system. And if the specification is a reusable product, then that's not enough. Now, the next step is obvious. Agents have to move upstream.
But how?
When we started building Resonate on NATS I/O, we changed the question. We did not ask, "Can the agent build the production system?" Instead, we asked, "What does the agent need in order to design the system first and build the system second?"
Simulated Design7:05
So we gave the agent access to a deterministic simulation environment. And we gave it a different task: do not build the production system. Build a simulated implementation. The simulated implementation is not the product. It is executable design. Its purpose is to discover the correct algorithm on the partial order, on the partial failure.
And once these algorithms are discovered, tested, and verified in simulation, then we ask the agent to write the concrete specification. And only then do we ask the agent to write the production implementation.
So the process becomes abstract specification, simulation implementation, concrete specification, and then concrete implementation. This is the point where the agent moves upstream. Humans are still involved in the design process, but now the agent is the driver.
Two ingredients make this possible: minimalism and simplicity. Unfortunately, minimalism and simplicity are not the starting point. They are the finish line. We spent three years making the protocol smaller and simpler. Every time we ran into a problem, we asked, "What can we take away?
What abstraction can we erase? What property can we remove? What relationship can we break?" The result is a very small protocol centered around two objects: a durable promise and a durable task. That simplicity matters because even simple concurrent distributed protocols have a complex state and behavior space.
Stale Reads9:13
So in other terms, implementing even simple protocols on top of a few simple primitives is tough.
Let's make this concrete with NATS. NATS gives us a small set of primitives we can build on: queues, a key-value store, and delayed or scheduled messages. These are not Resonate concepts. These are the concepts of the target platform.
So the design question becomes, how can we express the Resonate protocol using only these primitives?
Let's focus on the key-value store. The key-value store is versioned. We create a key with value full, then we update it to bar, then we update it to pass. So the latest value is pass at version 2. Most of the time, when we read the key, that is exactly what we get: a fresh read.
And if all reads were fresh, the design would be straightforward. But sometimes the read is stale. Here, the latest value is still pass at version 2, but the read returns full at version 0. That is not corruption. That is not a bug in the key-value store.
That is a valid read under the consistency model of the target platform.
And that matters because our implementation cannot be correct only when the target behaves conveniently. The implementation has to be correct when the target behaves legally.
So the simulation environment has to expose exactly this kind of behavior: fresh reads, stale reads, and the version information that tells us which world we are in.
Unfortunately, we do not know the read was stale simply by reading. We will find out later when we try to write. Here we read version 0, so we try to update version 0. But the key has already moved on.
The write fails. That is the moment the target tells us, "The world you saw is not the current world."
Building always-correct applications on top of a concurrency model that allows occasional stale reads is not simple. Not for humans, not for agents. So how do we set up our agent for success? What tools does our agent need to ace this task instead of falling flat on its face?
Agents thrive on feedback. Immediate, unambiguous feedback. Not just feedback that shows, "This went wrong." Feedback that shows why and how this went wrong.
What stale value was returned? What logic was triggered? What write failed? And which invariant broke because of that?
Agent Feedback12:28
So we built a deterministic simulation testing environment in Python. And inside that environment, we simulated the parts of NATS I/O we depend on. Here, for example, is the simulated key-value store. It keeps the full version history for every key.
On Get, the simulated store sometimes returned the latest version, but sometimes, controlled by the deterministic random generator, the store returns an older version. On Update, the store enforces optimistic concurrency. The write only succeeds if the version you read is still the latest version.
Otherwise, it erases.
This gives the agent a store that behaves like the real store in the ways that matter for correctness. But unlike the real target, the simulation is deterministic, it's repeatable, and it's inspectable. So when the agent writes the wrong algorithm, we can reproduce the exact execution that broke it.
And the agent can repair the algorithm against that trace.
But deterministic simulation does more than just inject stale reads.
It lets us expose facts the real platform hides. We call this the forbidden fruit. In production, when you read from the key-value store, you only get the value in the version you observed. You do not get to know whether that read was fresh or stale.
You do not get to see the latest value you missed. And you shouldn't get that information because real code cannot depend on it. But in simulation, we can record it. Here, every Get emits a trace event. If the read is fresh, the trace says, "This was fresh."
If the read is stale, the trace says, "This was stale. This is what you got, and this is what the latest value was." That information is forbidden to the algorithm, but it is incredibly useful to the agent. It lets us explore failures in terms the agent can act on.
Now, this is what a trace event looks like. The production code only receives the result. It sees the promise was pending. This is all the real platform would tell us. But the simulation also records the type of the read.
This read was a stale read. And it records the latest value that was hidden from the algorithm. The latest value says the same promise is already settled. That difference is exactly the kind of fact an agent needs when it's debugging a distributed algorithm.
Closing the Gap15:45
Not just the invariant failed, but the invariant failed because the algorithm made a decision from a stale view of the world. Again, the algorithm is not allowed to depend on this information, but the agent is allowed to use it to explain why the algorithm it designed was wrong.
Cause and effect becomes visible. The agent does not just learn that the system is wrong. It learns why the system is wrong.
And with this approach, the agent was able to close the gap. First, the agent built a proof of concept in the deterministic simulator, verified by first testing.
From the proof of concept, the agent derived the concrete specification, where we already knew the algorithm was correct.
And like before, from the concrete specification, the agent derived an implementation.
Deterministic simulation lets agents participate in the design, not just in the implementation.
Humans are still in the design process, but this time, the agent is the driver. From a single abstract specification, the agent designed and built the platform via simulation to concrete specification to concrete implementation. The prompt is the platform, and the specification is the product.
Thank you very much for watching. If you have any questions, please don't hesitate to reach out. You will find me in Resonate's Discord.





