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.
attempt object gives you everything you need:
| Field | Type | Description |
|---|---|---|
attempt | number | Current attempt number (1-indexed) |
maxAttempts | number | Maximum retries allowed |
instructions | string | Auto-generated prompt from your schema |
repairs | Message[] | Targeted fix messages from prior failures (empty on first attempt) |
The RunFn
Your function must match this signature:
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:
| Option | Type | Default | Description |
|---|---|---|---|
schema | ZodType<T> | required | Your Zod schema |
rules | Rule<T>[] | [] | Domain correctness rules |
retry | RetryOptions | { maxAttempts: 3 } | Retry behavior on failure |
repairs | RepairOverrides | — | Custom repair strategies per failure category |
instructions | { suffix?: string } | — | Append text to the auto-generated schema prompt |
logger | ContractLogger<T> | — | Hook into execution events |
debug | boolean | false | Enable console logging |
Next steps
Rules
Write domain correctness rules
The Repair Loop
How Boundary turns failures into fixes