Skip to main content
A contract is the core abstraction in Boundary. It pairs a schema (what the data looks like) with rules (whether the data can be trusted). Together, they form the acceptance boundary between your LLM and your application.

Defining a contract

defineContract returns a DefinedContract<T> — a reusable object you call .accept() on whenever you want to run an LLM call through this contract.

Using a contract

The .accept() method takes your LLM call as a function. You own the LLM call. Boundary owns the validation.
The attempt object gives you everything you need:

The RunFn

Your function must match this signature:
Return the raw LLM response as a string. Boundary handles parsing, validation, and repair. Return null if the LLM returned nothing.
The RunFn must return a string, not a parsed object. Extract the text content from your provider’s response object before returning.

Your existing Zod schemas work

Boundary uses Zod for schema validation. If you already have Zod schemas in your codebase, pass them directly — no migration, no rewrite, no Boundary-specific DSL.

Configuration options

defineContract accepts these options:

Next steps

Rules

Write domain correctness rules

The Repair Loop

How Boundary turns failures into fixes

Observability

Start with local development logging while you are writing a contract. When the contract is running in production, add production observability to track acceptance rate, failure categories, retries, and failing rules across real traffic.