Skip to main content
Runs a contract in a single call — schema, RunFn, and options in one shot. Returns a ContractResult<T>. Implemented on top of defineContract; behavior is identical.

Signature

function enforce<T>(
  schema: ContractSchema<T>,
  run: RunFn,
  options: ContractOptions<T> & { name: string },
): Promise<ContractResult<T>>;
ParamTypeDescription
schemaContractSchema<T>Zod v3 or v4 schema for the expected output
runRunFn(attempt) => Promise<string | null> — your LLM call
optionsContractOptions<T> & { name: string }Rules, retry, logger, etc. name is required.

options

Same shape as ContractConfig<T> minus schema.
FieldTypeDefaultDescription
namestringrequiredHuman-readable identifier for the run — appears in logs, traces, dashboard
rulesRule<T>[][]Domain correctness rules
retryRetryOptions{ maxAttempts: 3 }Retry behavior
repairsRepairOverridesCustom repair per category
instructions{ suffix?: string }Append text to the auto-generated prompt
onAttemptAttemptHookCalled after each attempt
loggerContractLogger<T>Lifecycle hooks (pass createBoundaryLogger(...) to ship events)
debugbooleanfalseShorthand for createConsoleLogger()
modelstringStamped onto BoundaryLogEvent.model for this run

Example

import { z } from "zod";
import { enforce } from "@withboundary/contract";

const schema = z.object({
  tier: z.enum(["hot", "warm", "cold"]),
  score: z.number().min(0).max(100),
});

const result = await enforce(schema, async (attempt) => {
  const response = await callYourLLM({
    messages: [
      {
        role: "user",
        content: [
          "Score this lead as JSON.",
          attempt.instructions,
          leadSummary,
        ].join("\n\n"),
      },
      ...attempt.repairs,
    ],
  });

  return response.text;
}, {
  name: "lead-scoring",
  rules: [
    {
      name: "hot_requires_high_score",
      description: "Hot leads must have a score of at least 70",
      fields: ["tier", "score"],
      check: (lead) =>
        lead.tier !== "hot" || lead.score >= 70
          || `tier is "hot" but score is ${lead.score} (minimum 70 for hot)`,
    },
  ],
  retry: { maxAttempts: 3 },
});

if (result.ok) {
  console.log(result.data);
}

When to use enforce vs defineContract

  • enforce — one-off, ad-hoc, experimental. Inline definition and execution.
  • defineContract — reusable, shared across endpoints, passed as a value.
See enforce vs defineContract for a full comparison.

See also

defineContract

Reusable contracts

Types

Full type reference