Skip to content

Contract

Accepted

A Contract is the abstract interface that Adapters or Modules with the same role share. Contracts are what enable substitution: any two Adapters declaring the same Contract are drop-in replaceable within a Slot requiring that Contract.

Contract Format

A Contract is identified by a namespaced slug with a mandatory version:

contract:<category>/<contract-name>/v<N>

Examples:

contract:persistence/repository/v1
contract:auth/identity-provider/v1
contract:llm/completion/v1
contract:llm/embedding/v1
contract:cache/key-value/v1
contract:messaging/event-publisher/v1

What a Contract Specifies

A Contract definition (stored in the platform’s Contract registry, referenced by Manifests) contains:

  • contract_id — the namespaced slug
  • category — broad category
  • abstract_operations — the operations the Contract guarantees, expressed as language-neutral signatures
  • semantics — natural-language description of what each operation must do
  • error_modes — how implementations must signal failure
  • required_capabilities — Capabilities that any implementor of this Contract must declare

A Contract is interface-shaped. It does not specify implementation; it specifies what code consuming a Contract-implementing Adapter can rely on.

How Adapters Declare Implementation

In an Adapter Manifest:

{
"interface_contracts": [
{
"contract_id": "contract:persistence/repository/v1",
"binding": "java",
"concrete_pattern": "interface {EntityName}Repository extends JpaRepository<{EntityName}, {IdType}>"
}
]
}
  • contract_id — which Contract this Adapter implements
  • binding — the language-specific binding (Java, TypeScript, Python)
  • concrete_pattern — the actual code shape the Adapter exposes for this Contract; used by the Stitcher to generate matching consumer code

The concrete_pattern is critical: it’s how the Stitcher knows what code to write against the resolved Adapter. Two Adapters implementing contract:persistence/repository/v1 will have different concrete_pattern values (Spring Data JPA uses JpaRepository; jOOQ uses a generated DSL), and the Stitcher generates differently-shaped code for each.

Contracts Enable Substitution

The substitution guarantee is this:

If two Adapters declare the same Contract, an Archetype’s Slot requiring that Contract can be filled by either Adapter, and the Stitcher will generate code that works with whichever was chosen.

The Stitcher reads the resolved Adapter’s concrete_pattern and generates accordingly. It does not need to know in advance which Adapter will fill the Slot.

Contract vs Capability

ContractCapability
Interface shapeDeclared feature
contract:persistence/repository/v1capability:persistence/transactions/v1
About the API surfaceAbout what the thing can do
Few per Adapter (often one)Many per Adapter
Required by a Slot to ensure substitutabilityRequired by a Slot to filter on features

Two Adapters with the same Contract are substitutable. Two Adapters with the same Capability might still have different APIs. A Slot typically requires both — for example, “any Adapter implementing the repository Contract that also declares transactions and pagination Capabilities.”

Contract Versioning

Like Capabilities, Contracts use integer versions:

  • contract:persistence/repository/v1
  • contract:persistence/repository/v2

A version bump indicates a breaking change to the interface. An Adapter implementing only v1 cannot satisfy a Slot requiring v2.

The platform team manages Contract evolution. Major version bumps require:

  • An ADR explaining why the change is necessary
  • A migration path for existing Adapters
  • A transition period during which both versions are supported

How Contracts Are Created

The Contract registry is governed centrally. New Contracts are proposed when:

  • A new category of building block enters the library (e.g., vector databases get contract:vector-search/v1 when the first vector DB Adapter is admitted)
  • An existing category needs a richer interface than current Contracts express
  • Multiple Adapters in a category exist without a shared Contract, and substitution becomes desirable

The proposal-and-admission process mirrors the Capability governance: drafted, reviewed, admitted, documented.

Language Bindings

A single Contract can have multiple language bindings. contract:llm/completion/v1 might have:

  • A Java binding (signatures, error types)
  • A TypeScript binding (matching signatures, idiomatic TS types)
  • A Python binding (Pythonic equivalents)

When an Archetype’s Slot requires this Contract and the surrounding code is Java, the Java binding is used; for TypeScript, the TS binding. The Stitcher generates code in the appropriate language using the appropriate binding.

This is how Almathal handles polyglot Archetypes: the same logical Contract spans multiple languages, and the language-specific Adapter implementations are matched per-language.

Contracts Are Reference Material for the Stitcher

When the Stitcher fills a Seam that consumes an Adapter, it reads:

  1. The Seam’s declared must_use_adapters
  2. Those Adapters’ Manifests
  3. Each Adapter’s interface_contracts entries
  4. The concrete_pattern for the Adapter’s language binding

From that, the Stitcher knows what code to write. The Contract is the structured input that makes the Stitcher’s task bounded rather than exploratory.

  • Capability — the feature-declaration counterpart
  • Slot — where Contracts are required
  • Manifest — where Contracts are declared
  • Adapter — what implements Contracts