Skip to content

Candy for AI: An Interview on Spec-Driven Development

Golo: Martin, you're the founder of Nebulit and the author of Understanding Eventsourcing, a book that deliberately refuses to treat Event Modeling, Event Sourcing, and Vertical Slice Architecture as three separate topics, and instead weaves them into a single, coherent way of building software. You also co-host the Event Modeling and Event Sourcing podcast, so you spend a lot of your time thinking out loud about this space. Over the last year, though, your attention has visibly shifted toward something new: getting AI agents to turn an event model into running, production-grade code, with as little human support as possible. Before we open the hood, take us back to the moment this clicked for you. What made you point your attention at autonomous code generation, and what convinced you it was more than the usual AI hype?

Martin: Honestly, I saw pretty early that using AI to build slices was an almost perfect match – the size and shape just fit. But the real "aha" moment happened during a workshop we ran in October 2025, a public online session for Nebulit where I was teaching Event Modeling and Event Sourcing, and how slices let you build software in a predictable way, AI included. After everyone left, I did what I always do: went in to clean up the model, adding a few comments here and there. What I hadn't realized was that the agent was still running in the background. Every change I'd made to the board had been translated into running code, essentially in real time. That was a real "eureka" moment for me. Most engineers still think about AI as: write the spec, hand it to an agent, review the output – basically what we always did, just with AI doing the typing. What I stumbled into was different. There was no handover at all. I was working with the agent in real time, and it kept up.

Golo: We've dabbled at the edges of this ourselves. We taught Claude to speak EventSourcingDB, and we've written about how Event Sourcing gives you a place to train AI on data you don't have yet. But there's a more fundamental claim hiding in your work: that it isn't enough to let an agent write any code, and that the architecture underneath matters enormously for how well an agent performs. Why Event Sourcing, and why slices? What is it about this particular shape of system that makes the difference between an agent that helps and an agent that quietly makes a mess?

Martin: Slices are decoupled – that's really the whole story. They're what microservices always should have been: small, isolated business capabilities, small enough to fit into a single head without any preparation. That size and that decoupling are what make the difference. An agent working on a slice needs to look at that slice, and nothing else. There's no shared understanding scattered across the codebase it has to reconstruct first, no hidden coupling it can accidentally trip over. Compare that to pointing an agent at a broad service or a sprawling aggregate: now it needs a mental model of everything that touches that aggregate, every implicit rule, every other consumer. That's exactly where agents start guessing, and guessing is where the mess starts.

And this isn't just a theoretical nicety, there's a real cost benefit behind it. The context you need to understand one slice can be laughably small. Which means you typically don't need frontier models for this work at all – small models, even local ones, are enough. That's what makes local AI a genuine game-changer in this approach: once the context is that small, you're no longer forced into paying frontier-model prices just to get a slice built correctly.

Why a Slice Is Candy for AI

Golo: You've put it memorably: a vertical slice is "candy for AI." That phrase has stuck with me, because it inverts the usual worry that AI can't handle real systems. Your point seems to be that the problem was never the AI, it was the size and shape of what we asked it to chew on. Can you unpack that? Why is the minimal scope of a single slice exactly the right bite for an agent, where a broad service or a sprawling aggregate is not?

Martin: Exactly that – the problem was never the model, it was the bite size. A slice is small enough that an agent doesn't need any prior context to reason about it correctly. No spelunking through the rest of the codebase, no reverse-engineering of "how did we do it three services over." The isolation is the point: change one slice, and nothing outside it needs to move. A broad service or a big aggregate doesn't give you that guarantee. The agent either has to hold the whole thing in its head – which is exactly what it's bad at – or it makes a local change that quietly breaks an assumption three files away that it never saw. Slices remove that risk almost by construction.

Golo: Part of what makes a slice tractable, I suspect, is that the vocabulary around it is precise. A command is an intent, an event is a fact, and we've argued before that commands aren't just events in reverse. We've also made the case that your aggregate is not a table. When an agent works against that kind of explicit, well-named structure rather than against a tangle of CRUD operations, what changes in practice? Does the rigor of the model actually constrain the AI in a helpful way?

Martin: It does, and the mechanism is very concrete for us: every slice comes with its business rules expressed as Given-When-Then scenarios. Those aren't just documentation – they translate directly into executable specifications. So the vocabulary isn't just precise for the sake of precision; it defines the perfect guardrails. The agent isn't free-styling against a vague "update this record" instruction, it's building against a scenario that says exactly what facts go in and what fact must come out. That's a constraint an agent can't argue its way around, and it's also one it can verify itself against.

Inside the Loop

Golo: Let's get concrete, because I think people imagine "AI writes the code" as a single magic prompt, and that's not what you're doing at all. You've built a loop that keeps iterating until every slice in a model is implemented. Walk us through it step by step. What actually happens, from the moment a slice is marked as planned to the moment it's done and verified?

Martin: The first step is always modeling – extracting the domain knowledge and putting it on the board. Once a slice is modeled, you move it to status "planned." If an agent is connected to that board, that status change is literally what wakes it up and triggers the process. The agent then builds the slice using the skills we've provided for that stack. We maintain an ever-growing library of these skills, one set per supported stack, and quite often the people maintaining a given skill are the framework owners themselves. So the agent isn't inventing an approach from scratch – it's following a known, curated recipe for "how you build a slice in this stack," constrained by the Given-When-Then scenarios that came out of modeling.

Golo: Loops like this tend to teach you things you didn't expect, both delightful and painful. What surprised you most while building and running it? And just as importantly: where does it break? How does the loop know the difference between "this slice is genuinely finished" and "I'm stuck and going in circles," and what happens when it gets that judgment wrong?

Martin: The delightful surprise is that running this as a loop makes a real difference in practice – agents are effectively running 24/7, just waiting for the next slice to move to "planned." The agent works within its guardrails: the Given-When-Then scenarios, a hard rule against touching anything outside its own slice, and the skills for the stack it's building in. The result is that the code it produces is dead boring – which, for once, is exactly the compliment you want to pay generated code. As for knowing when it's done: in practice, a slice is usually implemented within one loop iteration, with tests sometimes following in a second. But by the second iteration at the latest, it's typically finished. The tests are the actual completion signal – not the agent's own sense of confidence.

Specifications as the Source of Truth

Golo: Underneath all of this sits a quieter but, I think, more radical idea: that the event model shouldn't just be a picture on a wall, but a machine-readable contract, a specification an agent and a human can both read without ambiguity. We've been chasing the same idea from our side with ESDM, short for Event-Sourced Domain Modeling, which describes an event-sourced domain – aggregates, events, commands, process managers, read models, right down to Given-When-Then specifications – as plain YAML, with the tooling to manage it. You arrived at a JSON-Schema spec; we landed on YAML. That two teams reached independently for a machine-readable contract feels like more than coincidence. What do you gain when the model becomes a contract rather than a drawing, and what did you have to get right for that contract to actually be trustworthy?

Martin: Having the model on a wall was always a good starting point for discovery – but it's horrible for everything that follows. Discovery alone simply isn't enough; you need more, and that "more" is a machine-readable contract. Concretely, the JSON-Schema spec is what lets me put guardrails on the agent's own output: I can verify that no additional tests were invented beyond what the model defines, and that every scenario the model does define has actually been implemented. That's not something you can check against a picture. The contract has to be exhaustive and unambiguous enough that "done" becomes a computable fact, not a judgment call.

Golo: One thing I love about this is that the specification isn't a separate artifact you maintain out of guilt; it can become the test. We've written about testing without mocks, where a test reads almost like a sentence in the domain language: given these events, when this command, then these events. When a Given-When-Then specification is the thing the agent builds against and the thing that proves it built the right thing, where does human judgment stay in the loop? What's the part you're not willing to hand over?

Martin: The part I keep is deciding what the scenarios are in the first place – the model itself is where the thinking happens, and that stays with the human and the modeling process, not the agent alone. Once that's fixed, the agent's job is verification against a boundary it didn't set: it can't sneak in extra tests, and it has to satisfy every one that's defined. That's the line for me – the agent becomes a tool, not a thinker.

Modernizing What You Can't See

Golo: So far we've talked about greenfield, where you start from a clean model. But most of the world's software is anything but clean, and you've made a point I keep quoting: you cannot modernize what you don't understand. You've experimented with pointing AI at large, legacy codebases to recover an event model from them, essentially reverse-engineering the intent that got buried over the years. How does that actually work, and just as importantly, how far can you trust the model that comes back out?

Martin: You need to extract as much knowledge as possible, and you do it in layers. First, you look at the API endpoints and the persistence: how does data get into the system, how does it leave, and how is it actually stored. That gives you the skeleton. Then you add more sources of truth on top of that. What's worked exceptionally well for us is pointing an agent at an existing UI and having it explore the business concepts through the interface itself – the UI often reveals intent that the code alone has buried under years of implementation detail. It's not a single pass; it's discovery layered on discovery, each source correcting and enriching the last.

Keeping Control at AI Speed

Golo: Here's the worry I'd put to you bluntly. If agents can produce code this fast, the obvious risk is that we simply generate technical debt faster than ever, with architectural decisions made implicitly and at a pace no human is reviewing. How do you keep genuine architectural control at AI speed? What stops this from becoming a very efficient way to dig a very deep hole?

Martin: The slice approach already forces a certain structure before a single line of code gets written. AI is used to generate and fill in the templates that structure defines – the actual thinking happened before, during modeling. So the architectural decisions aren't being made implicitly at generation time at all; they were made explicitly, upstream, when the slice was modeled and its scenarios were written. By the time the agent is involved, there's no architecture left to improvise.

Golo: I want to push on one of your more contrarian positions, because it goes against everything most of us were taught. Within a slice, you deliberately reject DRY and shared abstraction; you'd rather copy and paste than couple two slices through a clever abstraction. To a lot of engineers that sounds like heresy. Make the case. Why is the reflex toward reuse actively harmful here, and how does an agent change that calculus, if at all?

Martin: Because the moment you introduce a shared abstraction between two slices, you've reintroduced exactly the coupling the whole approach exists to remove. The structure the slice model forces is the control mechanism – AI just fills in the templates that structure gives it, and the thinking already happened upstream. Reuse across slices means an agent working on slice A now has to understand slice B's abstraction too, which is precisely the "look at nothing else" guarantee I don't want to give up. Copy-paste keeps each slice boring and self-contained, and boring is what you want an agent building against.

Golo: And the flip side: what should never be delegated to an agent? Where, in your view, is the line that a human has to stay on the right side of, no matter how good the tooling gets?

Martin: Verification. You need static checks, and you cannot have an agent review an agent – that's not a control, that's theater. I use bash scripts or MCP servers for this; honestly, anything static and deterministic works. The line is: an agent can produce, but something non-agentic has to be the judge of whether what it produced is correct.

Where This Is Heading

Golo: We've written that great minds should not think alike, they should think together, and a lot of this conversation lives exactly at the seam between a model, a database, and an agent. Looking out two years or so: where do you think autonomous coding actually lands? And from where you sit, what does an event store need to bring to the table so that agents can build well on top of it, rather than fighting it?

Martin: Something I'm actively working toward is what I call "model as you speak": a conversation between two humans, parsed by AI in real time, building the event model and the system as they talk – running by the time the conversation ends. That's where I think this heads. On the event store side, we're already seeing a preview of what's needed: one client is running agents directly on top of anonymized event streams, and whenever something goes wrong, agents can act autonomously to figure out what happened just by reading the stream. It works exceptionally well. So event stores need to support that kind of direct, structured access for agents going forward – likely through something like MCP – rather than assuming a human is always the one querying.

Golo: Finally, the practical question. Suppose someone reads this and wants to try this for themselves tomorrow, not the whole vision, just a first honest experiment. Where would you tell them to start, and what's the smallest thing they could do that would actually teach them something?

Martin: Take your own system, use an agent, and model one single use case. You can literally load the skills, point the agent to the code base and have it modeling within less than 15 minutes. Just try it and see how it feels. This doesn't need to be a big commitment – fifteen minutes is enough to learn something real.

Golo: Martin, thank you so much for taking the time to walk us through this. I'm genuinely curious to see how far this goes, and I suspect we'll be revisiting it sooner than we think.

Martin Dilger is the founder and CEO of Nebulit GmbH and the author of Understanding Eventsourcing. For more information or to get in touch, visit the Understanding Eventsourcing website.