How it works
The attempt.repairs field
Inside your RunFn, attempt.repairs is an array of plain { role, content } JSON objects. Most chat-style providers accept this shape directly or with a small mapping step.
attempt.repairs looks like this:
role: "user" — they carry the failure text from your rule’s check (or the schema/parse error) so the model sees exactly what to fix on the next attempt.
repairs is empty. On subsequent attempts, it contains the failure messages from the previous attempt — one entry per rule or schema violation that fired.
Retry configuration
By default, Boundary retries up to 3 attempts with no delay between them.Failure categories
Every failed attempt is classified into one of 8 categories. Each category has a default repair strategy:Custom repair overrides
You can override or disable repair for specific categories:false stops retrying for that failure type. Providing a function lets you craft custom repair messages.
When repair fails
IfmaxAttempts is exhausted without a valid output, the contract returns { ok: false, error }. The full per-attempt history is on error.attempts — including the failure category, the raw model output, and the typed ruleIssues on RULE_ERROR attempts.
maxAttempts regularly, that’s a signal: the rule may be too strict, the prompt may be missing context, or the model may be wrong for the job. Local logs can show this while you build; the hosted SDK can aggregate it across production traffic. See Results for handling patterns.
Next steps
Results
The ContractResult type
Guarantees
What Boundary promises