AI Engineer World's Fair 2026
The Prompt is the Platform
Read the talk
The Prompt Is the Platform
Generating infrastructure from a specification requires more than passing basic tests: agents need a way to explore distributed algorithms, reproduce failures, and turn tested designs into concrete implementations.
From a talk by Dominik and Dominik Tornow
Before you start: Familiarity with key-value stores, versioned writes, and basic concurrency will help you follow the simulation example.
What happens when the implementation becomes unnecessary?
What would make a software platform unnecessary even if it worked well? Dominik Tornow opens with a prediction: in 2026, coding agents will retire the first platform by making its implementation unnecessary. This is a forecast about how software gets built, not a report of a platform already displaced. Tornow introduces himself as founder and CEO of Resonate, a durable execution platform whose technical values are minimalism and simplicity.
The proposed change is from adopting a general-purpose implementation to generating a bespoke extension of infrastructure already in place. Instead of installing another library, framework, or platform, a team could ask an agent to implement the required behavior on its existing stack. Reuse moves upstream: the reusable artifact becomes the specification, from which many target-specific implementations can be derived. In that sense, the prompt becomes the platform.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
A protocol that can produce many servers
For Resonate, this possibility changes where the product's value lives. Tornow describes an existing server and SDK implementations for TypeScript, Python, Rust, Go, and Java. If agents can generate implementations, owning those implementations is no longer the whole proposition. The durable asset becomes the specification that connects one protocol to multiple servers.
The general-purpose Resonate Server remains a reference implementation. Other implementations, built with infrastructure partners, can provide durable execution directly on customers' existing infrastructure with minimal additional dependencies. The engineering question therefore changes from whether a server can be built to whether trusted servers can be synthesized repeatedly from the same specification.
Verification asks whether the generated result is correct. There is an earlier question too: how can the agent help specify the system it will build? The case study is Resonate's partnership with Synadia, the company behind NATS, an open-source messaging system for distributed applications. Bringing Resonate to that infrastructure provides a concrete test of the path from specification to implementation.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Keep the reusable specification abstract
The familiar agentic coding workflow has three parts: a specification, an agent, and an implementation. For many applications, that is enough. But generating several implementations for different infrastructure targets introduces another requirement: the shared specification must survive a change of target.
That rules out embedding a concrete database schema or index layout in the reusable specification. It also rules out assuming relational tables and transactions, a key-value store, or a weakly or strongly consistent storage substrate. Those are implementation decisions. The specification describes the required behavior; the implementation must realize it using the target's actual capabilities. Abstract does not mean that correctness is optional—it means the contract cannot depend on one convenient way of achieving it.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
The first attempt exposed a design gap
The initial request was direct: build a Resonate server in Rust on top of Postgres, following the abstract specification. The agent produced a system that worked on the happy path and passed basic tests. But it broke under concurrency, process failure, and network failure. The distance from the abstract contract to a correct concrete implementation was too large; the result was a prototype rather than a production system.
The next attempt inserted a concrete specification between the abstract specification and the code. A human drove an interactive design process with the agent, making the Postgres decisions explicit: the schema, indices, SQL queries, and transaction boundaries. Tornow reports that, once those decisions were written down, the agent could implement a production system.
This solved the implementation problem while exposing a limitation in the workflow. The agent helped build the system, but the human still supplied its design. If specifications are themselves reusable products, helping only after the design decisions have been made leaves a substantial part of the work untouched.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Design in simulation before building for production
For NATS, the team changed the agent's first assignment. Rather than immediately requesting a production system, they asked what the agent needed to design the system first and build it second. They supplied a deterministic simulation environment and requested a simulated implementation.
The simulated implementation is executable design. Its purpose is to discover algorithms that work under partial order and partial failure: operations need not unfold in one convenient sequence, and parts of the system can fail independently. Once the algorithms have been explored and tested in simulation, the agent can describe the target-specific design and then implement it. The sequence becomes:
- Start with the abstract specification.
- Build a simulated implementation to explore the algorithm.
- Derive a concrete specification from the tested design.
- Build the concrete implementation from that specification.
Humans remain involved, but the agent now drives part of the design process instead of merely translating a human design into code.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
A small protocol still has a large behavior space
Minimalism and simplicity make this approach more tractable, but they are the result of design work, not an initial condition. Tornow reports three years spent making the protocol smaller and simpler. When a problem appeared, the recurring questions were what abstraction could be erased, what property could be removed, and what relationship could be broken. The resulting protocol centers on two objects: a Durable Promise and a Durable Task. Even with that small conceptual surface, concurrency and distribution produce a complex space of possible states and behaviors.
For the NATS design, Tornow identifies three available building blocks: queues, a key-value store, and delayed or scheduled messages. These belong to the target infrastructure, not to the Resonate protocol. The task is to express the behavior of Durable Promises and Durable Tasks using those primitives, while preserving correctness when the primitives behave in inconvenient but permitted ways.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
A legal read can describe an outdated world
Consider a key whose values progress from foo to bar to baz. In the demonstration's numbering, the latest value is baz at version 2. A fresh read returns that pair. A stale read instead returns foo at version 0, even though the current value remains baz.
| Read | Returned value | Returned version | Current value |
|---|---|---|---|
| Fresh | baz | 2 | baz |
| Stale | foo | 0 | baz |
Under the target behavior modeled in the talk, the stale result is neither corruption nor a store bug. These zero-based versions are illustrative simulator labels: actual NATS revisions are bucket-wide sequence numbers, with the first stored write starting at 1. The example should not be read as a guarantee that every production read path may return any arbitrary historical value.
Correctness must cover legal target behavior, not only convenient behavior. A simulator therefore needs to expose fresh reads, stale reads, and their associated versions. But receiving a version does not itself reveal whether the read is fresh: the client does not know the current version merely from seeing an observed one.
The conflict becomes visible when the client attempts a write. Having read version 0, it requests an update conditional on version 0 still being current. The key has already advanced, so the update fails. That failed write establishes that the world the client observed is no longer current. Designing an algorithm that remains correct through such observations and failures is difficult for humans and agents alike.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Make the failure repeatable and inspectable
The agent needs immediate, unambiguous feedback that explains a failure's cause: which stale value was returned, which logic it triggered, which write failed, and which invariant broke. To provide that feedback, the team built a deterministic simulation environment in Python, modeling the parts of NATS on which its implementation depended.
The simulated key-value store retains a full version history for each key. On get, a deterministic random generator controls whether the returned entry is current or older. On update, the store enforces optimistic concurrency: the write succeeds only when the supplied version is still current; otherwise it raises. Keeping full history is a simulation choice—production NATS retains a configured, bounded history.
The essential behavior fits in a small Python model:
python
from random import Random
class KVStore:
def __init__(self, seed: int):
self.rng = Random(seed)
self.history: dict[str, list[str]] = {}
def create(self, key: str, value: str) -> int:
if key in self.history:
raise KeyError(key)
self.history[key] = [value]
return 0
def get(self, key: str) -> tuple[str, int]:
versions = self.history[key]
index = self.rng.randrange(len(versions))
return versions[index], index
def update(self, key: str, value: str, version: int) -> int:
versions = self.history[key]
if version != len(versions) - 1:
raise KeyError("version conflict")
versions.append(value)
return len(versions) - 1
store = KVStore(seed=7)
version = store.create("example", "foo")
version = store.update("example", "bar", version)
version = store.update("example", "baz", version)
observed_value, observed_version = store.get("example")
Here get can select any retained entry, including the latest. An update carrying version 0 would fail once baz occupies version 2; the failed update would leave the history unchanged.
The model reproduces the target behaviors that matter to this correctness problem while making their execution deterministic, repeatable, and inspectable. With the same inputs and random choices, the failing execution can be reproduced. The agent can then repair its algorithm against that particular trace instead of trying to infer what happened from an intermittent failure.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Let the debugger see what the algorithm cannot
Deterministic simulation can do more than inject stale reads. It can expose facts that the real platform hides. Tornow calls this the “forbidden fruit”: in production, a read provides the observed value and version, but not a freshness label or the latest value the client missed. The algorithm cannot depend on information unavailable through the real interface.
The simulator can nevertheless record that information for diagnosis. Every simulated get emits a trace event identifying whether the read was fresh or stale and recording both the observed value and the latest value. The runtime algorithm and the agent inspecting its trace have different information privileges. The extra facts help the agent understand a failure without becoming inputs to the algorithm it is designing.
The displayed KVStoreGet trace makes the distinction concrete. For the promise identified by foo-1, the result says pending. That is what the algorithm receives. The trace also labels the read STALE and records that the latest state of the same promise is settled.
| Information | Algorithm receives it | Diagnostic trace records it |
|---|---|---|
Observed state: pending | Yes | Yes |
Read type: STALE | No | Yes |
Latest state: settled | No | Yes |
The trace exposes a disagreement between an observation and current state; it does not turn the stale observation into a fresh read.
That difference makes a failure actionable. Instead of learning only that an invariant failed, the agent can identify a decision made from a stale view of the promise. It can use the hidden state to explain why its algorithm was wrong, while repairing the algorithm using only information that production code can actually obtain. Cause and effect become visible without granting the implementation unrealistic powers.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
From a tested algorithm to a reusable product
Tornow reports that this process closed the design gap. The agent first built a proof of concept inside the deterministic simulator and tested it through fuzzing. It then derived a concrete specification from that simulated design. He describes the algorithm as correct at this point; fuzz testing supplies evidence from the executions it explores, rather than an exhaustive proof of every possible execution.
From the concrete specification, the agent derived an implementation. The additional simulation stage changed its role: it could participate in discovering the design, not merely implementing decisions already made by a human. Humans remained involved, but the agent drove the progression from an abstract contract through executable design to a concrete specification and implementation. That is the practical basis for the closing product thesis: the prompt is the platform, and the specification is the product.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Resources
Further reading
Examples explaining revision numbers, retained history, and compare-and-swap updates that reject conflicting writes.
Explains oracle comparison, controlled time, invariant checks, and fault testing, including which conformance tools are publicly available.
Updates since the talk
A Go implementation of Resonate using NATS JetStream for transport and storage, with build instructions and deterministic testing endpoints. Production use requires a commercial license.
- Implementing the Distributed Async Await protocolDocumentation
A guide to the protocol's abstract machine, atomic transitions, implementation boundaries, and server implementations on different storage systems.
- Resonate server provider capabilitiesDocumentation
Current provider compatibility, licensing, test coverage, and deployment limitations for NATS and other infrastructure targets.
Read the complete timestamped transcript
- 0:02
In 2026, coding agents will quietly retire the first software platform.
- 0:09
Not because it's bad, simply because the platform is unnecessary.
- 0:15
I am 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.
- 0:31
At Resonate, we have a working theory where software engineering is headed.
- 0:37
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.
- 0:57
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.
- 1:16
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.
- 1:33
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,
- 1:47
what does this new reality mean for us?
- 1:51
If implementations become generatable, where does our value live? And our answer, our value moves from implementation to specification.
- 2:05
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.
- 2:22
One is the general-purpose Resonate Server, our reference implementation.
- 2:26
Others are implementations built with infrastructure partners. For customers and partners, this means durable execution right on top of their existing infrastructure with minimal additional dependencies. So the question is no longer can we build a server?
- 2:44
The question is, can we repeatedly synthesize trusted servers from the same specification? And if so, how?
- 2:58
When we talk about agentic engineering, we focus all of our attention on verification. How do we know the result is correct?
- 3:07
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?
- 3:23
Now, Resonate is partnering with multiple infrastructure providers to bring durable executions natively to their technology stack. One of them is Synadia, the company behind NATS.io, an open source messaging system designed for building modern distributed systems.
- 3:41
For the rest of this presentation, we will use Resonate on NATS.io to explore our agentic engineering practices. How do we go from specification to implementation?
- 3:53
First, we need to level set our mental model.
- 3:58
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.
- 4:11
But it is not enough for what we are trying to do
- 4:15
because we are not trying to generate one implementation from a specification.
- 4:23
We are trying to generate multiple target-specific implementations from the specification.
- 4:30
So the specification must not take any aspect of an implementation into account.
- 4:36
The specification must not assume a concrete database schema or concrete indices.
- 4:42
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.
- 4:56
The specification must be abstract. Only the implementation must be concrete.
- 5:04
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."
- 5:20
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.
- 5:35
It passed the basic tests, but it was not correct. It broke under concurrency. It broke under process failure. It broke under network failure. The implementation was closer to a prototype, but not a production system.
- 5:52
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
- 6:07
That concrete specification was derived interactively with the agent, but the human was the main driver.
- 6:16
For Postgres, that meant making target-specific decisions explicit, the data schema, the indices, the SQL queries, the transaction boundaries.
- 6:28
Once those decisions were written down, the agent was indeed able to implement a production system, so this worked.
- 6:37
But it also revealed the limitations. The agent helped us build the system,
- 6:43
but the agent did not help us design the system.
- 6:48
And if the specification is a reusable product, then that's not enough.
- 6:54
Now, the next step is obvious. Agents have to move upstream.
- 7:00
But how? When we started building Resonate on NATS IO, we changed the question.
- 7:09
We did not ask, "Can the agent build the production system?" Instead, we ask, "What does the agent need in order to design the system first and build the system second?"
- 7:23
So we gave the agent access to a deterministic simulation environment,
- 7:28
and we gave it a different task. Do not build the production system.
- 7:35
Build a simulated implementation. The simulated implementation is not the product.
- 7:42
It is executable design. Its purpose is to discover the correct algorithm under partial order, under 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.
- 8:06
So the process becomes abstract specification, simulation implementation, concrete specification, and then concrete implementation.
- 8:17
This is a point where the agent moves upstream. Humans are still involved in the design process, but now the agent is a driver.
- 8:29
Two ingredients make this possible, minimalism and simplicity.
- 8:35
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 ask, "What can we take away?
- 8:49
What abstraction can we erase? What property can we remove? What relationship can we break?"
- 8:56
The result is a very small protocol centered around two objects, a Durable Promise and a Durable Task.
- 9:05
That simplicity matters because even simple concurrent distributed protocol have a complex state and behavior space. So in other terms, implementing even simpler protocols on top of a few simple primitives is tough.
- 9:24
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.
- 9:38
These are not Resonate concepts. These are the concepts of the target platform.
- 9:44
So the design question becomes, how can we express the Resonate protocol using only these primitives?
- 9:54
Let's focus on the key-value store. The key-value store is versioned. We create a key with value foo, then we update it to bar, then we update it to baz.
- 10:06
So the latest value is baz at version two.
- 10:11
Most of the time, when we read the key, that is exactly what we get,
- 10:17
a fresh read. And if all reads were fresh, the design would be straightforward.
- 10:23
But sometimes the read is stale. Here, the latest value is still baz at version two,
- 10:33
but the read returns foo at version zero.
- 10:38
That is not corruption. That is not a bug in the key-value store.
- 10:44
That is a valid read under the consistency model of the target platform.
- 10:52
And that matters because our implementation cannot be correct only when the target behaves conveniently.
- 10:59
The implementation has to be correct when the target behaves legally.
- 11:06
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.
- 11:21
Unfortunately, we do not know the read was stale simply by reading. We will find out later when we try to write.
- 11:29
Here we read version zero, so we try to update version zero,
- 11:35
but the key has already moved on. The write fails.
- 11:39
That is the moment the target tells us, "The world you saw is not the current world."
- 11:48
Building always correct applications on top of a concurrency model that allows occasional stale reads is not simple,
- 11:57
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?
- 12:11
Agents thrive on feedback. Immediate, unambiguous feedback. Not just feedback that shows this went wrong. Feedback that shows why and how this went wrong.
- 12:27
What stale value was returned? What logic was triggered? What write failed? And which invariant broke because of that?
- 12:38
So we built a deterministic simulation testing environment in Python. And inside that environment, we simulated the parts of NATS.io we depend on.
- 12:48
Here, for example, is the simulated key-value store.
- 12:53
It keeps a full version history for every key.
- 12:57
On get, the simulated store sometimes return the latest version. But sometimes, controlled by the deterministic random generator, the store returns an older version. On update, the store enforces optimistic concurrency.
- 13:14
The write only succeeds if the version you read is still the latest version. Otherwise, it raises.
- 13:23
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.
- 13:37
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.
- 13:53
But deterministic simulation does more than just inject stale reads.
- 14:02
It lets us expose facts the real platform hides.
- 14:07
We call this the forbidden fruit. In production, when you read from the key-value store, you only get the value and the version you observed. You do not get to know whether that read was fresh or stale.
- 14:20
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.
- 14:30
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.
- 14:44
This is what you got, and this is what the latest value was.
- 14:49
That information is forbidden to the algorithm, but it is incredibly useful to the agent.
- 14:57
It lets us explore failures in terms the agent can act on.
- 15:05
Now, this is what a trace event looks like.
- 15:09
The production code only receives the result. It sees the promise was pending.
- 15:17
This is all the real platform would tell us.
- 15:21
But the simulation also records the type of the read. This read was a stale read,
- 15:28
and it records the latest value that was hidden from the algorithm. The latest value says the same promise is already settled.
- 15:38
That difference is exactly the kind of fact an agent needs when it's debugging a distributed algorithm.
- 15:45
Not just the invariant failed, but the invariant failed because the algorithm made a decision from a stale view of the world.
- 15:54
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.
- 16:04
Cause and effect becomes visible. The agent does not just learn that the system is wrong, it learns why the system is wrong.
- 16:16
And with this approach, the agent was able to close the gap.
- 16:22
First, the agent built a proof of concept in the deterministic simulator
- 16:29
verified by fuzz testing. From the proof of concept, the agent derived the concrete specification where we already knew the algorithm was correct.
- 16:45
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.
- 17:03
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.
- 17:18
The prompt is the platform, and the specification is the product.
- 17:24
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.