Part 3 of 6

Contracts: declarative style, types and capabilities

Declare the result instead of every step: typed structures between stages, contracts per module, and explicit permission boundaries.

Sections 07–10
07 · Declarative programming

Declare the result, not every step

Imperative prompt
1First inspect the page.
2Then identify the components.
3Then choose a layout.
4Then check responsiveness.
5Then repair accessibility issues.

The instruction attempts to prescribe the execution path.

Declarative specification
goal:
Create a modern service-business website
constraints:
responsive: true accessible: WCAG-AA use_design_system: true placeholder_links: none
success:
visual_score ≥ 0.85 functional_tests: pass broken_links: 0

The system declares what must be true. The runtime selects the execution strategy.

Separate the desired state from the method used to reach it.
What this means for the business
Declare the outcome so a model upgrade is not a rewrite

A prompt that scripts every step encodes assumptions about one specific model and becomes obsolete the moment that model changes. A specification that declares the required outcome, the constraints and the acceptance criteria survives the change, because switching models turns into a re-verification exercise rather than a rebuild. Given how often models are replaced now, this difference decides whether each upgrade costs your team days or a quarter.

Decision Require specifications written as acceptance criteria, and check that a model swap can be validated without touching the feature logic.
08 · Type systems

Natural language in, typed structures between stages

Prose should not pass unchanged between internal modules. Extract it once into a validated object, then route on facts, not phrasing.

User language

“Our site feels dated. Can you make it more premium, and maybe rethink the start page?”

Intent
extraction
WebsiteIntent validated
kind: redesign first_build ongoing_edit module_config question
confidence: 0.82
missing_information: ["target pages", "budget"]
Reliable
routing
Types reduce ambiguity and give the workflow reliable boundaries around probabilistic output.
What this means for the business
Fuzzy handoffs cannot be debugged

When prose is passed unchanged from one internal stage to the next, small differences in wording cascade into different behaviour further down, and nobody can point at where the result went wrong. Extracting the request once into a validated structure converts that fuzzy handoff into an inspectable one: you can log it, diff it, replay it, and route on facts instead of phrasing. It also lets stages be tested independently, which is what makes incremental improvement possible.

Decision Mandate a validated schema at every module boundary, and treat schema violations as build failures rather than warnings.
09 · Design by contract

Every prompt module should have a contract

Preconditions

What must already be true

·Repository is available
·User request has been classified
·Tenant is identified
·Required context is present
Postconditions

What the module must produce

·A valid implementation plan exists
·Every planned change references a file
·Required risks are identified
·No code was modified during planning
Invariants

Never violated, at any point

Never publish without approval
Never access another tenant
Never silently remove user content
Never mark an unverified result as ready
What this means for the business
A definition of done that a machine can check

Preconditions, postconditions and invariants turn a vague quality discussion into an automatic decision. Without them, whether a module is finished is settled in review meetings, which is slow, inconsistent and easy to relitigate. With them, the system itself refuses to hand on a result that violates the contract. This also draws clean lines of responsibility between your teams and any external partner, because the contract states what each side owes the other.

Decision Do not allow a prompt module into production without a written contract and automated postcondition checks.
10 · Effect systems & capabilities

Declare what each component is allowed to change

Permission is part of the program, never something the model infers for itself.

effects:
read_repositoryallowed
write_repositoryallowed
access_networkdenied
send_emaildenied
publish_websiterequires_approval
charge_paymentrequires_approval
Component
Read
Write
Network
Publish
Payment
Planner
·
·
·
·
Website builder
restricted
·
·
Crawler
limited
·
read-only
·
·
Publisher
deploy only
restricted
·
Billing agent
limited
billing records
restricted
·
allowed ·no access restricted approval required
What this means for the business
The costly incidents are actions, not sentences

Serious AI incidents are rarely a badly worded answer. They are a plausible-looking result combined with an action the component was never meant to take: publishing, spending, deleting, changing permissions, or writing to customers. Permission must therefore be part of the program, never something the model infers about itself. An explicit capability matrix per component makes the blast radius of any component visible before it ships, and reviewable when it changes.

Decision Require a capability matrix per component and treat every widening of it like granting production database access.
Series

Continue the engineering guide

This is one part of a six-part guide on turning prompts into specification-driven probabilistic software.

Back to the series overview →

App & Cloud Architecture · Book a Product Discovery Call

More articles