# The Prompt is the Platform

Dominik Tornow · Resonate HQ · AI Engineer World's Fair 2026: Online Track

> Khi agent sinh được implementation, sản phẩm là specification: Resonate dùng deterministic simulation để agent tự design rồi build Resonate trên NATS.

Topics: Coding Agents, Distributed Systems, Software Factory

Canonical: https://homus.dev/talks/the-prompt-is-the-platform

## 1. Coding agent sẽ lặng lẽ cho "nghỉ hưu" software platform đầu tiên

Dominik mở đầu bằng một dự đoán khá mạnh: trong năm 2026, coding agent sẽ lặng lẽ cho "nghỉ hưu" software platform đầu tiên. Không phải vì platform đó tệ, mà đơn giản vì platform trở nên không còn cần thiết nữa. Câu này là sợi chỉ xuyên suốt cả talk, và tên talk cũng nói đúng điều đó: prompt chính là platform.

![Slide tiêu đề The Prompt is the Platform](https://homus.dev/photos/DqtmZE6Hl0g-0000.jpg)

Slide mở đầu với tên talk "The Prompt is the Platform" và dòng chữ cam "Resonating…", kiểu chỉ báo đang làm việc của một coding agent trên terminal. Dominik nói từ xa, hình anh ở góc phải.

Anh tự giới thiệu: anh là Dominik Tornow, founder và CEO của Resonate. Resonate là một durable execution platform, được xây dựng với hai giá trị kỹ thuật cốt lõi là minimalism (tối giản) và simplicity (đơn giản). Anh báo trước rằng hai thuộc tính này sẽ đóng vai trò trung tâm trong phần còn lại của talk, và đúng là cuối cùng chúng trở thành một trong hai điều kiện để agent làm được việc khó.

![Slide giới thiệu Dominik Tornow, Resonate HQ](https://homus.dev/photos/DqtmZE6Hl0g-0016.jpg)

Slide giới thiệu diễn giả: Dominik Tornow, Resonate HQ. Ngoài vai trò founder và CEO, anh là tác giả cuốn sách Think Distributed Systems và đã làm distributed systems hơn 20 năm.

Durable execution, nói ngắn gọn, là cách chạy một đoạn code (một function, một workflow) sao cho nó sống sót qua crash, restart và lỗi mạng: tiến trình chết giữa chừng thì lần chạy sau tiếp tục từ chỗ đã dừng thay vì làm lại từ đầu hoặc bỏ dở. Muốn làm được vậy, platform phải ghi lại trạng thái một cách bền vững và phối hợp đúng giữa nhiều process, nên đây đúng là loại phần mềm khó viết đúng, nơi lỗi concurrency và partial failure ẩn rất sâu.

## 2. Reuse dời lên thượng nguồn: dùng lại specification, không dùng lại implementation

Ở Resonate, đội của anh có một "working theory" về hướng đi của software engineering. Theo giả thuyết này, các general-purpose implementation (thư viện, framework, platform dùng chung cho mọi người) sẽ ngày càng bị thay thế bởi các bespoke implementation, tức implementation may đo, được sinh ra theo yêu cầu. Điểm quan trọng: implementation may đo đó không đến dưới dạng một library mới, một framework mới hay một platform mới, mà là một phần mở rộng tối thiểu (minimal extension) của chính hạ tầng đang có sẵn.

Nếu giả thuyết này đúng, reuse sẽ dời lên thượng nguồn (move upstream). Thay vì dùng lại một general-purpose implementation, ta sẽ dùng lại một specification, rồi từ specification đó suy ra (derive) một bespoke implementation. Thực ra ta còn có thể build nhiều bespoke implementation, mỗi cái được may đo riêng cho hạ tầng đang có. Cách làm chỉ đơn giản là: hỏi agent. Đến lúc đó, theo lời Dominik, prompt chính là platform.

Reuse dời lên thượng nguồn: thứ được dùng lại là specification. Mỗi implementation là một phần mở rộng tối thiểu trên hạ tầng sẵn có, do agent sinh ra theo yêu cầu.

## 3. Câu hỏi mới cho Resonate: giá trị nằm ở đâu khi implementation sinh ra được?

Lý thuyết này đặt chính Resonate vào thế khó. Resonate là một durable execution platform: công ty có một implementation của Resonate Server, và có các implementation của Resonate SDK cho TypeScript, Python, Rust, Go và Java. Vậy thực tế mới này có ý nghĩa gì với họ? Nếu implementation trở thành thứ có thể sinh ra (generatable), thì giá trị của công ty nằm ở đâu?

Câu trả lời của Resonate: giá trị dời từ implementation sang specification. Điều này thay đổi cách đội nghĩ về sản phẩm của mình. Sản phẩm không còn là implementation nữa. Sản phẩm là specification, là protocol. Từ protocol đó, họ muốn derive ra nhiều server implementation khác nhau:

- Một là Resonate Server general-purpose, đóng vai reference implementation.

- Những cái còn lại là các implementation được build cùng các infrastructure partner.

Với khách hàng và partner, điều này có nghĩa là họ có durable execution chạy ngay trên hạ tầng mình đang dùng, với rất ít dependency bổ sung. Vì thế câu hỏi không còn là "chúng ta có build được một server không?". Câu hỏi trở thành: liệu ta có thể lặp đi lặp lại việc tổng hợp (synthesize) ra những server đáng tin cậy (trusted) từ cùng một specification hay không? Và nếu được, thì bằng cách nào?

## 4. Đừng chỉ nói về verification: để agent tham gia specify, và Resonate trên NATS.io

Dominik nhận xét: mỗi khi nói về agentic engineering, chúng ta dồn toàn bộ sự chú ý vào verification, tức làm sao biết kết quả là đúng. Hôm nay anh muốn tập trung vào chiều ngược lại là specification, và quan trọng hơn: làm sao để agent tham gia vào việc specify hệ thống, chứ không chỉ build hay verify nó.

Bối cảnh cụ thể: Resonate đang hợp tác với nhiều infrastructure provider để đưa durable execution vào thẳng technology stack của họ một cách native. Một trong số đó là Synadia, công ty đứng sau [NATS.io](https://nats.io), một hệ thống messaging open source được thiết kế để xây các distributed system hiện đại. Trong phần còn lại của talk, anh dùng dự án Resonate trên NATS.io làm ví dụ để mổ xẻ các practice agentic engineering của đội.

![Slide Resonate Durable Execution on NATS.IO](https://homus.dev/photos/DqtmZE6Hl0g-0320.jpg)

"Resonate Durable Execution on NATS.IO": logo Resonate (hai con mắt tròn) đặt cạnh logo NATS. Đây là case study xuyên suốt talk: dựng Resonate trên các primitive có sẵn của NATS thay vì bắt khách hàng chạy thêm một server riêng.

## 5. Mô hình quen thuộc Spec, Agent, Impl, và vì sao specification phải abstract

Đi từ specification tới implementation bằng cách nào? Trước tiên, Dominik muốn mọi người cùng thống nhất mental model. Bức hình trên slide là cách nhìn phổ biến về agentic coding: có một agent, có một specification, và rồi có một implementation. Với rất nhiều ứng dụng, chừng đó là đủ.

![Sơ đồ ba khối Spec, Agent, Impl](https://homus.dev/photos/DqtmZE6Hl0g-0344.jpg)

Mental model phổ biến của agentic coding: Spec đi vào Agent, Agent sinh ra Impl. Đủ cho một implementation, nhưng chưa đủ khi cần nhiều implementation cho nhiều hạ tầng khác nhau từ cùng một spec.

Nhưng nó không đủ cho thứ Resonate đang cố làm, vì họ không sinh một implementation từ một specification. Họ đang cố sinh nhiều implementation, mỗi cái dành riêng cho một target, từ cùng một specification. Hệ quả là specification tuyệt đối không được tính đến bất kỳ khía cạnh nào của một implementation cụ thể:

- Specification không được giả định một database schema cụ thể hay các index cụ thể.

- Specification thậm chí không được giả định có một relational database với bảng và transaction.

- Nó không được giả định một key-value store.

- Nó không được giả định weak consistency, cũng không được giả định strong consistency.

Specification phải abstract. Chỉ có implementation mới được concrete.

## 6. Lần thử đầu: Resonate Server bằng Rust trên Postgres, và agent thất bại

Vậy họ yêu cầu agent đi theo abstract specification và sinh ra một concrete implementation. Cụ thể, lần đầu tiên họ ra lệnh cho agent:

```
Build a Resonate server in Rust on top of Postgres.
```

Và agent thất bại. Khoảng cách giữa abstract specification và concrete implementation quá lớn. Agent sinh ra một hệ thống chạy được trên happy path. Nó qua được các test cơ bản, nhưng nó không đúng (not correct):

- Nó vỡ dưới concurrency.

- Nó vỡ khi process bị lỗi (process failure).

- Nó vỡ khi mạng bị lỗi (network failure).

Implementation đó gần với một prototype hơn là một production system. Đây là bài học quen thuộc với ai từng làm distributed systems: "chạy được trong demo" và "đúng dưới mọi interleaving và mọi kiểu hỏng hóc" là hai chuyện cách nhau rất xa, và test cơ bản gần như không bao giờ chạm tới vùng thứ hai.

## 7. Chèn thêm concrete specification: agent build được, nhưng chưa design được

Vì vậy họ sửa lại quy trình. Thay vì để agent nhảy thẳng từ abstract spec sang concrete implementation, họ chèn vào giữa một artifact trung gian: concrete specification. Concrete specification này được soạn ra một cách tương tác cùng agent, nhưng con người là người lái chính (the human was the main driver).

Với Postgres, điều đó có nghĩa là viết ra tường minh mọi quyết định riêng cho target: data schema, các index, các câu SQL query, và ranh giới của transaction (transaction boundaries). Khi những quyết định đó đã được viết ra giấy, agent thực sự build được một production system. Cách này chạy.

Quy trình sau lần sửa đầu tiên cho bản Postgres: con người lái việc viết concrete specification, agent chỉ lo phần implementation.

Nhưng nó cũng phơi ra giới hạn. Agent giúp họ build hệ thống, nhưng agent không giúp họ design hệ thống. Và nếu specification là một sản phẩm để dùng lại, thì như vậy chưa đủ: mỗi target mới lại cần con người ngồi thiết kế concrete spec từ đầu. Bước tiếp theo vì thế khá hiển nhiên: agent phải dời lên thượng nguồn (agents have to move upstream). Câu hỏi là: bằng cách nào?

## 8. Đổi câu hỏi: simulated implementation là executable design

Khi bắt đầu build Resonate trên NATS.io, đội đổi câu hỏi. Họ không hỏi "agent có build được production system không?". Thay vào đó họ hỏi: "agent cần gì để có thể design hệ thống trước, rồi build hệ thống sau?"

Câu trả lời là họ cho agent quyền truy cập một deterministic simulation environment (môi trường mô phỏng tất định), và giao cho nó một nhiệm vụ khác hẳn:

```
Do not build the production system. Build a simulated implementation.
```

Simulated implementation không phải là sản phẩm. Nó là executable design, một bản thiết kế chạy được. Mục đích của nó là khám phá ra thuật toán đúng dưới partial order (thứ tự sự kiện chỉ xác định một phần) và dưới partial failure (một phần hệ thống hỏng trong khi phần khác vẫn chạy). Khi các thuật toán đó đã được tìm ra, test và verify trong simulation, lúc đó họ mới yêu cầu agent viết concrete specification. Và chỉ sau đó nữa mới yêu cầu agent viết production implementation.

![Sơ đồ Abstract Spec, Simulation Impl, Concrete Spec, Concrete Impl, mỗi bước qua một Agent](https://homus.dev/photos/DqtmZE6Hl0g-1616.jpg)

Quy trình mới: Abstract Spec đi qua Agent thành Simulation Impl (được tô đậm, đây là bước mới), rồi qua Agent thành Concrete Spec, rồi qua Agent thành Concrete Impl.

Như vậy quy trình trở thành: abstract specification, simulation implementation, concrete specification, rồi concrete implementation. Đây chính là điểm agent dời lên thượng nguồn. Con người vẫn tham gia vào quá trình design, nhưng giờ agent mới là người lái (driver).

## 9. Hai nguyên liệu: minimalism và simplicity, Durable Promise và Durable Task

Theo Dominik, có hai nguyên liệu làm cho việc này khả thi: minimalism và simplicity. Đáng tiếc là minimalism và simplicity không phải điểm xuất phát. Chúng là vạch đích. Đội đã mất ba năm để làm cho protocol nhỏ hơn và đơn giản hơn. Mỗi lần đụng một vấn đề, họ tự hỏi:

- Có thể bỏ đi cái gì?

- Abstraction nào có thể xoá?

- Property nào có thể loại bỏ?

- Relationship nào có thể cắt đứt?

Kết quả là một protocol rất nhỏ, xoay quanh hai object: Durable Promise và Durable Task.

Minimalism là vạch đích: ba năm liên tục hỏi "bỏ được gì" để protocol chỉ còn hai object.

Sự đơn giản đó quan trọng vì ngay cả một protocol distributed, concurrent đơn giản cũng có state space và behavior space rất phức tạp. Nói cách khác, implement ngay cả một protocol đơn giản trên một vài primitive đơn giản vẫn là việc khó. Protocol càng nhỏ, không gian mà agent phải khám phá trong simulation càng hẹp, và cơ hội tìm ra thuật toán đúng càng cao.

## 10. Primitive của NATS và key-value store có version: fresh read, stale read

Để cụ thể hoá, Dominik quay lại NATS. NATS cho họ một tập primitive nhỏ để xây lên: queue, một key-value store, và message được hoãn hoặc lên lịch (delayed hoặc scheduled message). Đây không phải là khái niệm của Resonate. Đây là khái niệm của target platform. Vì vậy câu hỏi design trở thành: làm sao diễn đạt protocol Resonate chỉ bằng những primitive này?

Anh tập trung vào key-value store. [Key-value store của NATS](https://docs.nats.io/nats-concepts/jetstream/key-value-store) có version. Ta tạo một key với giá trị foo, rồi update thành bar, rồi update thành baz. Giá trị mới nhất vì thế là baz ở version hai. Phần lớn thời gian, khi đọc key đó, ta nhận được đúng thứ đó: một fresh read. Nếu mọi lần đọc đều fresh, việc design sẽ khá thẳng thắn.

Một key có lịch sử version. Fresh read trả giá trị mới nhất; stale read trả một giá trị cũ hơn, kèm version của nó.

Nhưng đôi khi read bị stale. Lúc này giá trị mới nhất vẫn là baz ở version hai, nhưng lần đọc lại trả về foo ở version không. Đó không phải là dữ liệu hỏng (corruption). Đó cũng không phải bug của key-value store. Đó là một read hợp lệ theo consistency model của target platform.

Điều đó quan trọng vì implementation của họ không thể chỉ đúng khi target cư xử một cách tiện lợi. Implementation phải đúng khi target cư xử một cách hợp lệ. Dominik gói lại bằng một cặp từ: không phải "conveniently", mà là "legally". Vì vậy simulation environment phải phơi ra đúng kiểu hành vi này: fresh read, stale read, và thông tin version cho ta biết mình đang ở "thế giới" nào.

## 11. Stale read chỉ lộ ra khi write, và agent cần feedback như thế nào

Khó ở chỗ: chỉ bằng việc đọc, ta không biết read đó có stale hay không. Ta chỉ phát hiện ra sau này, khi thử write. Ví dụ ta đọc được version không, nên ta thử update dựa trên version không, nhưng key đã tiến lên version mới rồi. Lệnh write thất bại. Đó là khoảnh khắc target nói với ta: "Thế giới bạn đã thấy không phải là thế giới hiện tại."

Stale read không tự báo là stale. Nó chỉ lộ ra khi optimistic concurrency từ chối lệnh write dựa trên version cũ.

Xây ứng dụng luôn đúng (always correct) trên một concurrency model cho phép thỉnh thoảng có stale read là việc không đơn giản, không đơn giản cho con người và cũng không đơn giản cho agent. Vậy làm sao để agent thành công? Agent cần công cụ gì để làm tốt việc này thay vì "ngã sấp mặt" (fall flat on its face)?

Câu trả lời của Dominik: agent sống nhờ feedback. Feedback ngay lập tức và không mơ hồ. Không chỉ là feedback cho thấy "chỗ này sai", mà là feedback cho thấy sai vì sao và sai như thế nào:

- Giá trị stale nào đã được trả về?

- Logic nào đã được kích hoạt vì nó?

- Lệnh write nào đã thất bại?

- Và invariant nào bị vỡ vì chuỗi đó?

## 12. Deterministic simulation bằng Python: một key-value store giả lập

Vì thế họ build một deterministic simulation testing environment bằng Python. Bên trong môi trường đó, họ giả lập những phần của NATS.io mà Resonate phụ thuộc vào. Slide dưới đây là key-value store giả lập.

![Code Python của class KVStore giả lập](https://homus.dev/photos/DqtmZE6Hl0g-1208.jpg)

Class KVStore giả lập. Mỗi key giữ một list mọi version. get() với xác suất pro trả về một version ngẫu nhiên cũ hơn (stale), còn lại trả version mới nhất; kết quả luôn kèm index của version. update() chỉ thành công khi index truyền vào đúng là version mới nhất, nếu không thì raise.

Store giả lập giữ toàn bộ lịch sử version cho mỗi key. Khi get, store đôi khi trả về version mới nhất. Nhưng đôi khi, theo điều khiển của bộ sinh số ngẫu nhiên tất định (deterministic random generator), store trả về một version cũ hơn. Khi update, store áp optimistic concurrency: lệnh write chỉ thành công nếu version bạn đã đọc vẫn còn là version mới nhất. Ngược lại, nó raise lỗi. Đoạn code trên slide, chép lại để tiện dùng:

```
class KVStore:
def __init__(self, ctx, rng, pro):
self.ctx, self.rng, self.pro, self.store = ctx, rng, pro, {}

def get(self, key):
if self.rng.random()

## 13. "Forbidden fruit": trace ghi lại điều mà platform thật giấu đi

Nhưng deterministic simulation làm được nhiều hơn là chỉ tiêm stale read vào. Nó cho phép phơi ra những sự thật mà platform thật giấu đi. Đội gọi thứ này là "forbidden fruit", trái cấm.

Trong production, khi đọc từ key-value store, bạn chỉ nhận được giá trị và version mà bạn quan sát được. Bạn không được biết lần đọc đó là fresh hay stale. Bạn không được thấy giá trị mới nhất mà bạn đã bỏ lỡ. Và bạn cũng không nên có thông tin đó, vì code thật không được phép phụ thuộc vào nó.

Nhưng trong simulation, ta ghi lại được. Ở đây, mỗi lần get đều phát ra một trace event. Nếu read là fresh, trace ghi đây là fresh. Nếu read là stale, trace ghi đây là stale, đây là thứ bạn nhận được, và đây là giá trị mới nhất lúc đó.

![KVStore.get phát trace event Get với type STALE hoặc FRESH](https://homus.dev/photos/DqtmZE6Hl0g-1352.jpg)

Phiên bản get() có trace: nhánh stale gọi ctx.trace(Get(type=STALE, key, result, latest)) với cả giá trị mới nhất bị giấu; nhánh fresh gọi ctx.trace(Get(type=FRESH, key, result)). Giá trị trả về cho algorithm vẫn y như cũ.

```
class KVStore:

def get(self, key):
if self.rng.random()

## 14. Một trace event trông ra sao, và cause and effect hiện ra

Dominik mô tả một trace event cụ thể. Production code chỉ nhận được kết quả: nó thấy promise đang ở trạng thái pending. Đó là tất cả những gì platform thật sẽ cho ta biết. Nhưng simulation còn ghi lại loại của lần đọc: lần đọc này là stale read. Và nó ghi lại cả giá trị mới nhất đã bị giấu khỏi algorithm: giá trị mới nhất cho thấy chính promise đó đã settled rồi.

Cùng một lần đọc, hai góc nhìn. Phần nét đứt là "forbidden fruit": algorithm không được dùng, nhưng agent dùng nó để hiểu vì sao thuật toán sai.

Sự khác biệt đó chính xác là loại sự thật mà agent cần khi đang debug một distributed algorithm. Không chỉ là "invariant bị vỡ", mà là "invariant bị vỡ vì algorithm đã ra quyết định dựa trên một góc nhìn stale về thế giới". Một lần nữa: algorithm không được phép phụ thuộc vào thông tin này, nhưng agent được phép dùng nó để giải thích vì sao thuật toán mà chính nó thiết kế lại sai.

Cause and effect trở nên nhìn thấy được. Agent không chỉ biết là hệ thống sai, nó biết vì sao hệ thống sai.

## 15. Agent khép được khoảng cách: The prompt is the platform

Với cách tiếp cận này, agent đã khép được khoảng cách từng làm nó thất bại ở lần thử với Postgres. Trình tự diễn ra như sau:

- Đầu tiên, agent build một proof of concept trong deterministic simulator, được verify bằng fuzz testing.

- Từ proof of concept, agent derive ra concrete specification, ở thời điểm mà đội đã biết chắc thuật toán là đúng.

- Và giống như trước, từ concrete specification, agent derive ra implementation.

Deterministic simulation cho phép agent tham gia vào design, không chỉ vào implementation. Con người vẫn có mặt trong quá trình design, nhưng lần này agent là người lái. Từ một abstract specification duy nhất, agent đã design và build platform: đi qua simulation, tới concrete specification, tới concrete implementation.

Dominik khép lại bằng hai câu tóm cả talk: prompt là platform, và specification là sản phẩm ("The prompt is the platform, and the specification is the product"). Anh cảm ơn mọi người đã xem, và mời ai có câu hỏi cứ liên hệ; mọi người có thể tìm thấy anh trong Discord của Resonate.

![Slide kết Build Resonate on NATS.IO kèm link Discord](https://homus.dev/photos/DqtmZE6Hl0g-1720.jpg)

Slide kết "Build Resonate on NATS.IO", lại với dòng "Resonating…", và đường dẫn tới Discord của Resonate (resonatehq.io/discord) để hỏi trực tiếp Dominik.

## Nguồn và link

- [Trang talk chính thức trên ai.engineer](https://ai.engineer/talks/DqtmZE6Hl0g) · [Video gốc](https://www.youtube.com/watch?v=DqtmZE6Hl0g)

- Resonate, durable execution platform của Dominik: [resonatehq.io](https://www.resonatehq.io) · tài liệu: [docs.resonatehq.io](https://docs.resonatehq.io) · code: [github.com/resonatehq/resonate](https://github.com/resonatehq/resonate)

- Discord của Resonate, nơi Dominik mời đặt câu hỏi: [resonatehq.io/discord](https://resonatehq.io/discord)

- NATS, hệ thống messaging open source dùng làm target trong talk: [nats.io](https://nats.io) · NATS Key-Value Store: [docs.nats.io](https://docs.nats.io/nats-concepts/jetstream/key-value-store)

- Synadia, công ty đứng sau NATS: [synadia.com](https://www.synadia.com)

- Think Distributed Systems, sách của Dominik Tornow: [manning.com](https://www.manning.com/books/think-distributed-systems)

- Dominik Tornow trên GitHub: [github.com/dtornow](https://github.com/dtornow) · trên X: [x.com/DominikTornow](https://x.com/DominikTornow)
