> ## Documentation Index
> Fetch the complete documentation index at: https://docs.withboundary.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Types

> All public types exported from @withboundary/contract and @withboundary/sdk

## Contract library types

All exported from `@withboundary/contract`.

```typescript theme={null}
import type {
  ContractResult,
  ContractAttempt,
  ContractError,
  AttemptDetail,
  FailureCategory,
  Rule,
  RunFn,
  Message,
  ContractConfig,
  ContractOptions,
  ContractSchema,
  DefinedContract,
  RetryOptions,
  RetryPolicy,
  ContractLogger,
  ConsoleLoggerOptions,
  BoundaryLogEvent,
  RuleDefinition,
  RuleIssue,
  SchemaField,
} from "@withboundary/contract";
```

### ContractResult\<T>

The return type of every contract call. Discriminated union on `ok`.

```typescript theme={null}
type ContractResult<T> =
  | {
      ok: true
      data: T              // typed, validated, all rules passed
      attempts: number     // total attempts made
      raw: string          // the raw LLM output that was accepted
      durationMS: number   // total wall-clock time
    }
  | {
      ok: false
      error: ContractError
    }
```

### ContractAttempt

Passed to your `RunFn` on each attempt.

```typescript theme={null}
type ContractAttempt = {
  attempt: number          // 1-indexed attempt number
  maxAttempts: number      // from retry config
  instructions: string     // auto-generated prompt from schema
  repairs: Message[]       // repair messages from prior failure (empty on first)
  previousError?: ContractError
  previousCategory?: FailureCategory
}
```

### ContractError

```typescript theme={null}
type ContractError = {
  message: string          // human-readable summary
  attempts: AttemptDetail[] // one entry per failed attempt
}
```

### AttemptDetail

```typescript theme={null}
type AttemptDetail = {
  raw: string              // raw LLM output
  cleaned: unknown         // parsed/cleaned output
  issues: string[]         // list of violations
  ruleIssues?: RuleIssue[] // structured rule failures, only on RULE_ERROR
  category: FailureCategory
}
```

### FailureCategory

```typescript theme={null}
type FailureCategory =
  | "EMPTY_RESPONSE"     // model returned nothing
  | "REFUSAL"            // model refused the task
  | "NO_JSON"            // response contained no JSON
  | "TRUNCATED"          // JSON was cut off
  | "PARSE_ERROR"        // malformed JSON
  | "VALIDATION_ERROR"   // valid JSON, failed schema
  | "RULE_ERROR"         // passed schema, failed rules
  | "RUN_ERROR"          // RunFn threw an error
```

### Rule\<T>

```typescript theme={null}
interface Rule<T> {
  name: string
  description?: string
  check: (data: T) => boolean | string
  message?: string
  fields?: string[]
}
```

Rules are named, synchronous checks. `check` returns `true` when the data is correct. It returns `false` or a string when the rule fails. A string return becomes the failure message for that specific attempt; otherwise Boundary uses `message` when provided.

Use stable `name` values for dashboards, metrics, and `ruleIssues`. Use `description` as the human label. Use `fields` when a rule maps cleanly to one or more output fields.

### RunFn

```typescript theme={null}
type RunFn = (attempt: ContractAttempt) => Promise<string | null>
```

Your LLM call function. Return the raw response as a string, or `null` if the model returned nothing.

### Message

```typescript theme={null}
type Message = {
  role: string
  content: string
}
```

Used in `attempt.repairs` and repair functions.

## Configuration types

### ContractConfig\<T>

```typescript theme={null}
type ContractConfig<T> = {
  name: string
  schema: ContractSchema<T>
  rules?: Rule<T>[]
  retry?: RetryOptions
  repairs?: RepairOverrides
  instructions?: { suffix?: string }
  onAttempt?: AttemptHook
  logger?: ContractLogger<T>
  debug?: boolean
  model?: string
}
```

### RetryOptions

```typescript theme={null}
type RetryOptions = {
  maxAttempts?: number     // default: 3
  backoff?: "none" | "linear" | "exponential"
  baseMs?: number          // default: 200
}
```

### RepairOverrides

```typescript theme={null}
type RepairOverrides = Partial<Record<FailureCategory, RepairFn | false>>
type RepairFn = (detail: AttemptDetail) => Message[]
```

## ContractLogger\<T>

Hook into the execution lifecycle. All hooks are optional. Every context object includes `contractName` and `runHandle` so one logger can serve multiple contracts and correlate hooks from the same run.

```typescript theme={null}
type ContractLogger<T> = {
  onRunStart?: (ctx: {
    contractName: string
    runHandle: string
    maxAttempts: number
    rulesCount: number
    model?: string
    retry: RetryPolicy
    schema?: SchemaField[]
    rules?: RuleDefinition[]
  }) => void

  onAttemptStart?: (ctx: {
    contractName: string
    runHandle: string
    attempt: number
    maxAttempts: number
    instructions: string
    repairs: Array<unknown>
  }) => void

  onRawOutput?: (ctx: {
    contractName: string
    runHandle: string
    attempt: number
    raw: string
  }) => void

  onCleanedOutput?: (ctx: {
    contractName: string
    runHandle: string
    attempt: number
    cleaned: unknown
  }) => void

  onVerifySuccess?: (ctx: {
    contractName: string
    runHandle: string
    attempt: number
    data: T
    durationMs: number
  }) => void

  onVerifyFailure?: (ctx: {
    contractName: string
    runHandle: string
    attempt: number
    category: string
    issues: string[]
    ruleIssues?: RuleIssue[]
    durationMs: number
  }) => void

  onRepairGenerated?: (ctx: {
    contractName: string
    runHandle: string
    attempt: number
    category: string
    repairMessage: string
  }) => void

  onRetryScheduled?: (ctx: {
    contractName: string
    runHandle: string
    attempt: number
    nextAttempt: number
    category: string
    delayMs: number
  }) => void

  onRunSuccess?: (ctx: {
    contractName: string
    runHandle: string
    attempts: number
    data: T
    totalDurationMs: number
  }) => void

  onRunFailure?: (ctx: {
    contractName: string
    runHandle: string
    attempts: number
    category?: string
    message: string
    totalDurationMs: number
  }) => void
}
```

### ConsoleLoggerOptions

```typescript theme={null}
type ConsoleLoggerOptions = {
  prefix?: string
  showInstructions?: boolean
  showRepairs?: boolean
  showRawOutput?: boolean
  showCleanedOutput?: boolean
  showSuccessData?: boolean
  maxStringLength?: number
}
```

See [`createConsoleLogger`](/api-reference/engine#createconsolelogger).

## Engine primitives

Lower-level functions for advanced use cases. All pure and side-effect-free.

| Function              | Signature                                                                               | Description                                              |
| --------------------- | --------------------------------------------------------------------------------------- | -------------------------------------------------------- |
| `clean`               | `(raw: string \| null \| undefined) => unknown`                                         | Extract and normalize JSON from raw LLM output           |
| `verify`              | `<T>(data: unknown, schema: ContractSchema<T>, rules?: Rule<T>[]) => ContractResult<T>` | Validate data against schema and rules. No LLM involved. |
| `classify`            | `(raw: string, cleaned: unknown) => FailureCategory`                                    | Categorize a failed response                             |
| `repair`              | `(detail: AttemptDetail, overrides?) => Message[] \| false`                             | Generate repair messages for a failed attempt            |
| `instructions`        | `(schema: ContractSchema<unknown>) => string`                                           | Generate prompt text from a Zod schema                   |
| `createConsoleLogger` | `(options?) => ContractLogger<T>`                                                       | Create a logger that prints to console                   |

Full reference: [Engine primitives](/api-reference/engine).

***

## SDK types

All exported from `@withboundary/sdk`.

```typescript theme={null}
import type {
  BoundaryLogger,
  BoundaryLoggerOptions,
  BoundaryLogEvent,
  BoundaryEnvironment,
  CapturePolicy,
  RedactionOptions,
  Transport,
} from "@withboundary/sdk";
```

`@withboundary/contract` also exports a `BoundaryLogEvent` type for contract-level logger integrations. The SDK's `BoundaryLogEvent` below is the hosted ingest event used by `createBoundaryLogger`, `beforeSend`, and custom `write` sinks.

### BoundaryLogger\<T>

The object returned by `createBoundaryLogger`. Implements every `ContractLogger<T>` hook and adds drain controls.

```typescript theme={null}
type BoundaryLogger<T = unknown> = ContractLogger<T> & {
  flush: (timeoutMs?: number) => Promise<void>
  shutdown: (timeoutMs?: number) => Promise<void>
}
```

### BoundaryLoggerOptions

Full options shape for `createBoundaryLogger`. See [createBoundaryLogger](/api-reference/create-boundary-logger) for a per-field table with defaults.

```typescript theme={null}
interface BoundaryLoggerOptions {
  apiKey?: string
  environment?: BoundaryEnvironment
  endpoint?: string
  model?: string
  capture?: Partial<CapturePolicy>
  redact?: RedactionOptions
  batch?: {
    size?: number
    intervalMs?: number
    maxQueueSize?: number
  }
  beforeSend?: (event: BoundaryLogEvent) => BoundaryLogEvent | null
  write?: (events: BoundaryLogEvent[]) => void | Promise<void>
  flushOnExit?: boolean
  onError?: (err: unknown) => void
  fetch?: typeof fetch
}
```

### BoundaryLogEvent

The wire format shipped to the ingest endpoint. A tagged union on `ok` — `AcceptedEvent` (always terminal) or `FailedEvent` (one per non-terminal attempt plus the terminal one). See [BoundaryLogEvent](/sdk/boundary-log-event) for examples and lifecycle.

```typescript theme={null}
interface BoundaryLogEventBase {
  // identity (always sent)
  contractName: string
  environment?: string
  timestamp: string
  runId: string

  // run metadata (always sent)
  attempt: number
  maxAttempts: number
  durationMs: number
  model?: string
  rulesCount?: number
  schema?: SchemaField[]
  rules?: RuleDefinition[]

  // SDK attribution (always sent)
  sdk?: { name: string; version: string; runtime?: string }

  // resolved capture policy stamped on every event
  capture?: CapturePolicy & { redactedFields?: string[] }

  // raw data — gated by capture.inputs / capture.outputs (default off)
  input?: unknown
  output?: unknown
}

interface AcceptedEvent extends BoundaryLogEventBase {
  ok: true
  final: true
}

interface FailedEvent extends BoundaryLogEventBase {
  ok: false
  final: boolean
  // failure attribution — always sent on FailedEvent (no capture flag)
  category: string
  issues: string[]
  ruleFailures?: string[]
  // gated by capture.repairs (default on)
  repairs?: Array<{ role: string; content: string }>
}

type BoundaryLogEvent = AcceptedEvent | FailedEvent
```

### CapturePolicy

```typescript theme={null}
interface CapturePolicy {
  inputs: boolean   // user → model data        (default off)
  outputs: boolean  // model → boundary data    (default off)
  repairs: boolean  // boundary → model retries (default on)
}

const DEFAULT_CAPTURE: CapturePolicy = {
  inputs: false,
  outputs: false,
  repairs: true,
}
```

Failure attribution (`category`, `issues`, `ruleFailures`) and run metadata are always sent on the wire — they are not gated by a capture flag.

### RedactionOptions

```typescript theme={null}
interface RedactionOptions {
  fields?: string[]
  patterns?: RegExp[]
  custom?: (value: unknown, path: string[]) => unknown
}
```

### BoundaryEnvironment

```typescript theme={null}
type BoundaryEnvironment = "production" | "staging" | "development"
```

The wire format (`BoundaryLogEvent.environment`) is `string` so the server accepts future names without an SDK bump; the SDK's input type is the narrow union to prevent typos like `"prod"` or `"stg"` that would fragment dashboards.

### Transport

Low-level extension point. Typical users don't implement this — they pass `write` instead.

```typescript theme={null}
interface Transport {
  send(events: BoundaryLogEvent[]): Promise<void>
}
```
