Structured-Prompt-Driven Development: Making AI-Generated Code Governable
AI coding assistants demonstrably accelerate individual developers, but delivery speed is rarely constrained by typing speed. Across the full delivery lifecycle — from requirements through release — friction emerges in new places: ambiguous requirements become code quickly and misunderstandings scale; reviewers process larger volumes of change with more inconsistency; integration and testing issues surface because generated output isn't necessarily aligned output; and production risk becomes harder to reason about as change volume rises.
In other words, local speed gains don't automatically translate into system-level throughput. The critical question isn't how to generate more code, but how to make AI-generated changes governable, reviewable, and reusable. That question led Thoughtworks' internal IT organization (Global IT Services) to develop a method and workflow called Structured-Prompt-Driven Development (SPDD).
Prompts as First-Class Delivery Artifacts
SPDD is an engineering method that treats prompts as first-class delivery artifacts. Instead of relying on ad hoc chat sessions, SPDD converts prompts into assets that can be version controlled, reviewed, reused, and improved over time. Teams use structured prompts to capture requirements, domain language, design intent, constraints, and task breakdowns. The LLM then generates code within a defined boundary, producing output that is more predictable and easier to validate.
SPDD has two core components: the REASONS Canvas for prompt structure, and a workflow that brings prompts into the same discipline as code.
The REASONS Canvas
The REASONS Canvas is a seven-part structure guiding a prompt from intent through design to execution and governance.
A——stract parts (intent & design)
- R — Requirements: What problem are we solving, and what is the Definition of Done?
- E — Entities: Domain entities and relationships.
- A — Approach: The strategy for meeting the requirements.
- S — Structure: Where the change fits in the system; components and dependencies.
Specific parts (execution)
- O — Operations: Break the abstract strategy into concrete, testable implementation steps.
Common standards parts (governance)
- N — Norms: Cross-cutting engineering norms (naming, observability, defensive coding, etc.).
- S — Safeguards: Non-negotiable boundaries (invariants, performance limits, security rules, etc.).
The canvas forces clarity around requirements, domain model, solution approach, system structure, task decomposition, and reusable norms before any code is generated — aligning intent and boundaries early. Because the structured prompt captures the full specification, reviewers can reason about a single artifact rather than scattered chat logs and partial diffs. The consistent structure makes every prompt governable in the same way, and accumulated domain knowledge and design decisions compound individual expertise while reducing variability across the team.
The SPDD Workflow
The SPDD workflow brings prompts into the same discipline as code: commit history, review, and quality gates. It enforces a simple but powerful rule: when reality diverges, fix the prompt first, then update the code.
Over time, this shifts the nature of reviews from "spot the bug" toward "check the intent." Rework becomes more controlled, and successful patterns accumulate into a reusable prompt library supporting AI-First Software Delivery (AIFSD).
SPDD shares a starting point with Spec-Driven Development — write the spec clearly first, then let the model implement — but takes a different angle: it treats structured prompts as governed, reusable, versioned team assets (REASONS + workflow) that evolve alongside the code. This approach aligns with what Birgitta Böckeler categorizes as a spec-anchored approach.
The workflow's goal is to turn business input → abstraction → execution → validation → release into a closed loop, ensuring prompt assets and code evolve together rather than separately.
A one-way pipeline produces code and ends; any later adjustment happens only in code and the original intent drifts out of date. In SPDD the loop closes on two scales. Within an iteration, feedback flows back: logic corrections update the prompt before the code, and refactoring syncs from code back to the prompt — so neither side silently diverges. Across iterations, accumulated prompt assets — domain models, design decisions, norms — become the starting context for the next enhancement, allowing each cycle to build on a governed baseline.
The workflow anchors collaboration on the prompts, avoiding repeated alignment cycles between developers and product owners. The prompt sets an explicit boundary for code generation, reducing the randomness of the LLM's non-determinism and making output easier to govern.
In practice, these steps are carried out through commands provided by openspdd, a command-line tool that implements the SPDD workflow. The table below summarizes each command.
SPDD in action: from requirement to tested code
Walking through a complete SPDD cycle on a real enhancement makes the workflow concrete. The example below uses a small billing engine for LLM token usage — small enough to follow end-to-end, but covering every stage: requirements capture, analysis, prompt generation, code generation, verification and cleanup. The full starting codebase and SPDD artifacts are available on GitHub; you can reproduce the run locally with the openspdd tool.
The system and the enhancement
The existing system is a straightforward billing engine. It accepts a session's token usage via a single API endpoint and returns a bill computed from a flat global rate. The enhancement replaces that static model with plan- and model-aware pricing:
POST /api/usagenow requires amodelIdfield (e.g.fast-modelorreasoning-model).- Pricing is per model rather than a single rate.
- The Standard plan keeps its monthly quota; only overage is billed, at the model's rate. The Premium plan is new — no quota, and prompt and completion tokens are billed separately.
- The billing logic is reorganized behind an extensible pattern (Strategy or Factory) so future plans slot in cleanly.
The requirement mixes business goals with technical direction, so it would typically be drafted in a pairing session between a product owner (or BA) and a developer.
Step 1: Turn the idea into a story
The workflow starts with /spdd-story (or the equivalent openspdd generate spdd-story command), which decomposes a broad requirement into INVEST-compliant user stories of roughly one to five days each. Each story lands with business-language acceptance criteria.
Pointing the command at the enhancement description produced two initial stories: one for the Standard plan plus model-aware pricing, and one for Premium split-rate billing. They are detailed enough to use as-is, but for this walkthrough we consolidated them into a single simplified story. The consolidating instruction stripped implementation detail, kept only Background, Business Value, Scope In/Out and Acceptance Criteria, and enforced a Given/When/Then format with concrete numbers. Output varies run to run, so a brief human review pass is expected before accepting the final one-page story.
Step 2: Clarify scope and done criteria
Before generating anything, the developer reads the story for shared understanding. The core logic for this enhancement breaks down as:
- A required
modelIdon the API — this key selects the price. - Standard plan: existing quota logic stays; overage moves to model-specific rates (e.g. $0.01/1K for
fast-model, $0.03/1K forreasoning-model). - Premium plan: quota-free; prompt and completion tokens each have their own per-model rate; the bill sums the two charges.
- Routing logic chooses the formula by customer plan and must be easy to extend.
Explicitly out of scope: customer CRUD, historical billing queries, subscription management and model administration — only current-bill calculation.
The definition of done also captures the testable contracts the team will check against, including one the developer adds for end-to-end verification:
- Validation: missing
modelId, unknown customer, or negative tokens each return the appropriate HTTP error (400 or 404). - Standard plan: with a 100K quota and 90K used, a 30K
fast-modelsubmission bills 20K of overage at $0.01/1K = $0.20; the identical request onreasoning-modelbills $0.60. - Premium plan: 10K prompt + 20K completion on
reasoning-model(prompt $0.03/1K, completion $0.06/1K) yields $0.30 + $1.20 = $1.50. - Response contract: HTTP 201 with bill ID, customer ID, token counts, timestamp,
modelIdand the plan-appropriate charge breakdown.
Step 3: Analysis grounded in the codebase
With scope locked, /spdd-analysis extracts domain keywords from the story (e.g. billing, quota, plan) to scan only relevant parts of the codebase. The output — an analysis context document — deliberately stays at the level of what and why, covering domain concepts, strategic direction, edge cases and risks. The generated artifact runs through the existing vs. new domain vocabulary, proposed solution direction and trade-offs, and acceptance-criteria gaps.
The review pass checks intent alignment on architectural choices: whether the Strategy Pattern is appropriate, adherence to ISP and SRP in the existing code, and whether the plan for the new fields holds up. In this case the AI's analysis matched the team's intent — even surfacing a few extra edge cases — so the document was accepted as-is and the workflow moved on to the concrete design stage.
Step 4: Build the executable blueprint
/spdd-reasons-canvas consumes the analysis and the live codebase to generate a full seven-dimension design spec. The key difference from the analysis: this artifact is operational. It specifies method signatures, parameter types and execution sequences, not just strategic direction.
Reviewing the generated structured prompt is a check that the high-level intent survived translation into concrete architecture. Because this project already carries its architectural guidelines and OO principles in the codebase — and in the prior iteration's prompt — the output was highly consistent with expectations, and only minor issues appeared. With intent aligned at the design level, the next phase is code.
Step 5: Generate, verify and refine code
The workflow separates product code generation from feature-level verification.
Product code. /spdd-generate follows the Operations order in the REASONS Canvas, producing code task by task with no improvisation. The review consequently converges on three things: does the code respect the expected 3-tier architecture, does the Service layer implement the agreed business logic, and do changes stay inside the spec's boundaries? The generated code passed all three checks, retaining only some "magic numbers" flagged for later cleanup.
Feature verification. The optional /spdd-api-test command turns endpoint definitions into a cURL-based script with a structured test-case table — normal, boundary and error cases. Running it against the generated code:
sh scripts/test-api.sh
All functional tests passed on the first run.
Post-review fixes split into two kinds. The workflow distinguishes changes that alter observable behavior from those that are pure internal restructuring.
For behavior-affecting logic corrections, the structured prompt is updated first. In this example, a design decision had left the datastore modelId nullable to remain backward-compatible with legacy rows. Confirming with the business that every historical bill should default to fast-model turned that workaround into technical debt. The fix ran through /spdd-prompt-update, which edits only the affected REASONS dimensions while preserving the rest, followed by a targeted /spdd-generate that produces a diff rather than a full rewrite. The loop is: pinpoint the prompt snippet covering the outdated logic, state the new rule, regenerate.
private int calculateRemainingQuota(String customerId, PricingPlan plan) {
if (plan.getMonthlyQuota() == null || plan.getMonthlyQuota() == 0) {
return 0;
}
LocalDate currentDate = LocalDate.now(ZoneOffset.UTC);
LocalDateTime monthStart = currentDate.withDayOfMonth(1).atStartOfDay();
LocalDateTime monthEnd = currentDate.plusMonths(1).withDayOfMonth(1).atStartOfDay();
Integer currentMonthUsage = billRepository.sumIncludedTokensUsedForMonth(customerId, monthStart, monthEnd);
return plan.getMonthlyQuota() - currentMonthUsage;
}
Refactoring — clean-code and stylistic issues with no behavioral change — runs in the opposite direction. Here the AI refactors the code directly, e.g. extracting hardcoded values in BillingServiceImpl.calculateRemainingQuota into meaningful constants. Then /spdd-sync folds the updated code details back into the structured prompt so the spec never drifts from the implementation. The golden rule to keep both artifacts in lockstep; for deeper smells, repeat the cycle in small increments.
With all cleanup done, a final regression pass — restarting the service and rerunning the API test script — confirmed nothing broke.
Step 6: Unit tests behind the functional smoke test
The API test script validates the endpoint contract end-to-end but doesn't count toward coverage. Final sign-off on core logic comes from unit tests. The workflow's dedicated test commands aren't finalized yet, so the interim approach drives test generation with a template:
- A base test prompt is compiled from the implementation spec plus a standard test-scenarios template.
- The result is referenced against the existing test suite; duplicated scenarios are dropped, leaving only genuinely new cases.
- Generating from that refined test prompt produced the new unit tests, and all passed.
What a full cycle buys you
At the close of this SPDD cycle the billing enhancement shipped with several concrete gains: business logic with exceptionally high alignment to the original intent (around 99%), full engineering transparency about the path taken and trade-offs accepted, a structured prompt in sync with the codebase that future iterations build on, and a workflow that accumulates developer expertise and context through each collaborative pass with the AI. The full diffs for prompt and code are on GitHub, along with a bonus Enterprise plan story for hands-on practice of the same drill.
Core skills for structured-prompt development
SPDD demands a meaningful shift in how developers approach software construction. Through our work, we've isolated three capabilities that practitioners must cultivate, each pointing to where developer value now concentrates in an AI-assisted workflow.
Design before generation
Solidify the object model before asking for any code. You need to know what entities exist, how they interact, and where system boundaries lie. Skipping this step invites the AI to optimize implementation minutiae while the architecture erodes around it, yielding duplicated logic, inconsistent interfaces, and fuzzy responsibilities. The consequences surface as stalled reviews and costly rework downstream.



