--- slug: contract type: pattern summary: "The explicit or implicit promise about what will happen across an interface, the agreement that holds components together." created: 2026-04-04 updated: 2026-04-05 related: boundary: relation: enforced-by note: "Contract violations are caught at boundaries." bounded-context: relation: enabled-by note: "Inter-context communication relies on explicit contracts." composition: relation: used-by note: "Parts compose through compatible interfaces." consumer: relation: relied-on-by note: "Consumers depend on contracts being honored." consumer-driven-contract-testing: relation: depended-on-by note: "CDCT makes an existing contract executable; without a contract concept there is nothing to test against." coupling: relation: supports note: "Explicit contracts let you manage coupling deliberately." deprecation: relation: used-by note: "You deprecate a feature because a contract needs to change, and the announcement is how you honor the old contract while it winds down." greenfield-and-brownfield: relation: related note: "Brownfield is where contracts rule; greenfield is where they're drafted." interface: relation: defines note: "A contract spells out the promises an interface makes." load-bearing: relation: related note: "Things become accidentally load-bearing when callers rely on behavior outside the contract." parallel-change: relation: used-by note: "Parallel change is the canonical way to evolve a contract without breaking it." strangler-fig: relation: used-by note: "The old system's behavior is the implicit contract the new system must honor." --- # Contract > **Pattern** > > A named solution to a recurring problem. ## Context When one part of a system uses another, both sides carry expectations. A **contract** is the explicit or implicit promise about what will happen across an [interface](interface.md). It operates at the **architectural** scale, governing the agreements that hold [components](component.md) together. Contracts can be formal (a typed function signature, an API schema, a service-level agreement) or informal, like the unwritten assumption that "this function never returns null." Formal contracts are enforceable by machines. Informal contracts live in developers' heads and break when someone new, human or agent, arrives who was never told the rules. ## Problem How do you ensure that the two sides of an [interface](interface.md) agree on what is expected — and stay in agreement as both sides evolve independently? ## Forces - Tight, detailed contracts are safe but restrictive. They limit how implementations can change. - Loose, vague contracts are flexible but dangerous. Misunderstandings cause silent failures. - Contracts that live only in documentation drift out of sync with the code. - Every consumer of an interface has its own interpretation of what the contract means. ## Solution Make contracts as explicit as the situation warrants. For internal [modules](module.md) that change frequently, typed function signatures and automated tests may suffice. For published APIs consumed by external parties, you need versioned schemas, clear error codes, and documented behavior for edge cases. A good contract specifies at minimum: - **Preconditions** — what must be true before calling. - **Postconditions** — what will be true after a successful call. - **Error behavior** — what happens when things go wrong. - **Invariants** — what is always true, regardless of inputs. In agentic coding, contracts matter even more. An AI agent can't ask clarifying questions mid-execution the way a human colleague can. If a tool's contract says it returns a list but sometimes returns `null`, the agent's downstream logic breaks. Clear contracts let agents plan multi-step workflows with confidence. ## How It Plays Out A team defines a REST API for user management. The contract specifies: POST to `/users` with a JSON body containing `email` and `name` returns a `201` with the created user, or a `409` if the email already exists. A frontend developer and a mobile developer both build clients independently. Because the contract is explicit and tested, both clients work correctly without coordination. An AI agent is given a `create_file` tool. The tool's contract states: "Creates a file at the given path. Returns the file path on success. Raises an error if the file already exists." The agent uses this contract to plan: it checks for existence first, then creates. If the contract had been silent on the "already exists" case, the agent would have learned about it only through a runtime failure, wasting a step and potentially corrupting state. > **⚠️ Warning** > > The most dangerous contracts are the ones nobody wrote down. If a behavior is relied upon, it is part of the contract — whether or not it is documented. When taking over a codebase, look for implicit contracts in the tests: what do the tests assume? > **💡 Example Prompt** > > "Define the contract for the POST /users endpoint: it accepts email and name in JSON, returns 201 with the created user on success, and returns 409 if the email already exists. Write contract tests that verify both cases." ## Consequences Explicit contracts reduce misunderstandings, enable independent development, and make automated testing straightforward (contract tests verify that implementations honor their promises). They are especially valuable in agentic workflows where the consumer cannot exercise judgment about ambiguous cases. The cost is maintenance. Contracts must be kept in sync with implementations. A contract that promises something the code no longer does is worse than no contract at all; it's an active source of misinformation. Automated contract testing (where tests verify the contract, not just the implementation) helps, but it requires discipline. --- - [Next: Boundary](boundary.md) - [Previous: Consumer](consumer.md)