Skip to content

Two Loops: Model-Driven Development with Agents

Section titled “Two Loops: Model-Driven Development with Agents”

Agents can work away from the keyboard only on what a human approved. A human can approve only what they can read. LLMs write Markdown faster than anyone can read it, so a spec written in prose ends up approved without being read, and agents take it as gospel.

This method puts a model at the center of the spec instead. Business flows, domain models and API contracts are written in structured languages that humans and agents can both read and validate. A human designs the system with them, in a loop with agents. Then agents implement it, in a loop of their own.

  1. The model is the spec. Business flows in ZFL, bounded contexts in ZDL, contracts in OpenAPI and AsyncAPI.
  2. Prose lives inside the model, not around it. Doc comments, business policies and ADRs explain the model. Free-standing documents (PRDs, research notes, generated Markdown specs) feed the design, never the implementation.
  3. Humans review projections, not prose. Diagrams, state machines, sequence diagrams per branch, API contracts and generated code are all projections of the same model, and they are faster to validate than any document.
  4. Approved means approved. Agents treat as decided only what is in the approved model baseline.
  5. Agents challenge the model; they never edit it. When implementation shows the model is wrong, agents stop and propose changes. A human decides.
  6. Agents make tests pass; they don’t decide what passing means. Expectations come from the model and from test data a human validated.
  7. Humans review evidence, not code. At the end of an autonomous run the human gets reports, test results and open proposals, not a diff to read line by line.
  8. Iterative, one batch at a time. Both loops run in parallel on different batches of flows.
  9. The generator is an accelerator, not the method. Deterministic code generation shrinks what agents have to write. The method works without it.
StageWho leadsProducesEnds whenZenWave tools
DiscoverHumans, assisted by agentsPRD, Event Storming findings, first ZFL draftA flow can be written as ZFLgrill-with-docs, Event Storming
Shape (HITL loop)Humans, assisted by agentsApproved models, ADRs, validated test data, task boardThe gate passesZFL, ZDL, OpenAPI, AsyncAPI, ZenWave Platform, ZenWave SDK, zfl-to-zdl, zenwave-test-data, zenwave-test-scenarios
Implement & Verify (AFK loop)AgentsWorking, tested code; review reports; model-change proposalsThe batch exit criteria passOrchestrator, implementer and reviewer subagents, zenwave-fill-gaps
NavigateHumans and agentsUnderstanding of the whole architectureNever: it runs alongsidezenwave-architecture, ZenWave Platform, MCP

The stages form a cycle: for an existing system, Navigate is the input to Discover.

Discovery comes before the loops. Ideally it starts with a PRD, which seeds an interview session with skills like grill-with-docs. It continues with an Event Storming session between technical experts and domain experts. The architect translates the findings into a first ZFL draft of each flow.

Prose is fine here. The PRD and research notes are inputs to the design; agents in the AFK loop never read them.

Ends when a flow can be written as a first ZFL draft.

The human drives the design; agents assist. The loop repeats until the gate passes:

  • Model. Write the business flow in ZFL and one ZDL per bounded context. The zfl-to-zdl skill drafts the ZDL from the ZFL. API contracts can be derived from the ZDL.
  • Project. Explore what the model derives in ZenWave Platform for IntelliJ and VS Code: the EventFlow diagram, sequence diagrams for every alternative branch of a ZFL flow, class diagrams and state machines for each aggregate, commands, domain events, OpenAPI and AsyncAPI.
  • Generate. If the stack matches, ZenWave SDK generates services, APIs, event handlers and a full set of tests. Generated code is one more projection. Early on, throw it away and generate again.
  • Probe. Generated tests have no proper test data or complete assertions yet. Use them as entry points: start a debug session, or write a few lines by hand, to check that what the model produces covers the requirements.
  • Challenge. Agents review the models looking for contradictions, missing outcomes and decisions nobody made. Answers change the model or become ADRs.
  • Prepare the handover. Generate test data for each use case and branch of the flow (zenwave-test-data, zenwave-test-scenarios) and validate it. Split the work into tasks.

Splitting is a discrete step at the end of Shape, not a loop, though it may take a few iterations. The human splits the work, assisted by an agent that derives a task list from the approved model: from the generated code when there is some, from a blank slate when there isn’t.

The result is a list or a graph of tasks. Each task:

  • points at the model lines it implements and the test data that defines done;
  • states its difficulty, so it can be routed to a suitable model;
  • states its blockers, the tasks it depends on.

Tasks don’t describe behavior in prose; the model already does.

A batch of flows passes from Shape to Implement & Verify when it is:

  1. Valid. Models parse and references resolve: every ZFL service exists in a ZDL, every emitted event is declared, every API channel exists. Deterministic, no LLM.
  2. Reviewed. Agents have no open questions left, and the human has reviewed the projections.
  3. Covered by test data. Each use case and branch has test data with inputs and expected results, validated by the human.
  4. Split. The task board is approved.
  5. Approved. The human commits or tags the model as the baseline.
  6. Generated (when a generator exists). The last generation run compiles and runs. It becomes the AFK loop’s starting point.

The batch can be a single flow, a module or a whole system.

Implement & Verify: the Away-From-Keyboard loop

Section titled “Implement & Verify: the Away-From-Keyboard loop”

Agents implement the batch without a human at the keyboard. They read only the approved models, the ADRs, the validated test data, the task board and the generated code.

  1. Load. The orchestrator reads the whole approved spec.
  2. Pick. It takes the next task whose blockers are done.
  3. Route. It chooses a model according to the task’s difficulty.
  4. Implement. An implementer subagent works in its own worktree, reads the task and the model lines it points at, and runs only the focused tests for that task.
  5. Review, per batch. A reviewer subagent runs the entire suite, or the vertical slice of a module in a modular monolith, and checks the changes against the model and the test data. It writes a review report with the reviewed commit range (from..to). Optionally, it adds regression tests covered by the model.
  6. Integrate. The review report is always committed with the code. On a FIX FIRST verdict, the orchestrator redelivers the affected tasks to implementers.
  7. Repeat until the board is cleared or every remaining task is blocked.

Only the orchestrator writes to the board. Subagents report back to it.

An implementer or reviewer that finds a gap in the model does not work around it in code and does not edit the model. It:

  1. marks the task as blocked by the model;
  2. writes a proposal with one or more solutions, as changes in the modeling language, with the evidence (failing test, code location);
  3. hands it to the human, while the orchestrator continues with other ready tasks.

The human chooses or adjusts a solution in Shape, updates the model, regenerates and approves a new baseline. The orchestrator reconciles the regenerated code with the code already merged, and the blocked tasks become ready again.

A batch is done when:

  • every task of the approved board is done;
  • the batch review is clean (no FIX FIRST);
  • the full suite, or the vertical slices, are green;
  • structural assertions and approved test data have not changed since the baseline;
  • there are no open model-change proposals.

Advanced: once the board is cleared, the reviewer runs the task-list agent again over the result. An empty list means nothing is missing between the model and the code. It can also produce a traceability table: each ZFL step and ZDL operation, the code that implements it, and the test covering each branch.

The human then reviews the evidence: review reports, test results per branch, open proposals and the running application. Code review is by sampling, or for what the model does not cover.

The two loops connect in two places:

  • The gate, going forward: an approved batch of models, test data and tasks.
  • Model-change proposals, going back: written in the modeling language, so a human can review them in minutes.

Because the method is iterative, both loops run at the same time on different batches. When a later batch changes a shared ZDL, that is a new baseline: regenerate, approve, and let the orchestrator reconcile.

Navigate runs outside the loops. zenwave-architecture builds one graph from all the models and APIs listed in the architecture manifest, and ZenWave Platform and MCP make it explorable by humans and agents. It is how you understand the whole existing architecture and the blast radius of a change, and for an existing system it is where the next Discover begins.

The method does not depend on ZenWave SDK. Without a generator:

  • Shape still produces models, projections, test data and tasks, minus the generated code;
  • the task list starts from a blank slate;
  • the gate drops its last check;
  • the AFK loop writes all of the code instead of the remaining 20%.

Hard rules:

  • the model is the spec;
  • agents never edit the model;
  • agents never invent expected behavior;
  • nothing crosses into the AFK loop without passing the gate.

Optional practices: the code generator, the board backend (a Markdown list, a folder of task files, Jira, GitHub issues, Linear), routing by difficulty, reviewer regression tests, and the advanced exit check.