Principle 04 / 09
Architecture enables bounded understanding
On this page
A good contract lets an engineer—or an agent—work on one capability without needing the internals of everything around it.
The problem
The difficulty of changing a system is not just its size. It is how much of that system someone must hold in mind to make a safe change. When responsibilities are tangled, a small feature may require understanding storage, security, business rules, messaging, interfaces and unrelated workflows.
This problem becomes conspicuous with AI agents. Loading the entire repository into context is costly and noisy. Supplying a fragment without its real dependencies is risky. The answer is not simply better summarisation; it is better boundaries.
How boundaries reduce context
Separate capabilities by responsibility and expose behavioural contracts. A consumer should know what an operation does, what inputs it accepts, what failures it reports, what it guarantees and what invariants must be preserved. It should not need to know how the provider stores data or which library it uses.
A common pattern is to separate:
- Stable mechanics or infrastructure capabilities.
- Integrations that combine those mechanics into useful services.
- Product-specific orchestration that expresses the business rules or user experience.
This is one possible architecture, not a required number of layers. The test is whether dependencies and responsibilities are intentional.
With stable contracts, work can be divided safely. The change agent receives the consumer-facing contract and the component it is changing; contract tests verify its assumptions. If a contract needs to change, that is elevated to an architectural decision.
Illustrative example
A reporting feature needs maintenance-request status. If a request store exposes get_request(id) and guarantees a documented set of states and version semantics, the reporting component does not need to know SQL tables or write paths. The request store can later be refactored without rewriting reports if the contract remains valid.
This also supports faster product experimentation. New orchestration can assemble existing capabilities rather than repeatedly rebuilding storage and notification systems.
What to verify
- Dependency direction and forbidden imports.
- Schema compatibility, error semantics and behavioural invariants.
- Contract tests run from the consumer’s point of view.
- Integration tests at boundaries that matter.
Limits
Too many layers and abstractions can be worse than a straightforward module. Contracts that specify only types but omit meaningful semantics create false confidence. Some product decisions legitimately cross boundaries; those changes need a broader context and deliberate coordination. The goal is the smallest sufficient context, not artificial isolation.
See the worked example: layered architecture, contracts, and the executable intake slice.