Skip to main content
The capture policy is the first line of defense between your process and the ingest endpoint. It governs the three optional data buckets — inputs, outputs, and repairs. Everything else on a BoundaryLogEvent is structural and always sent, because Boundary can’t show you a run at all without it.

The three buckets

createBoundaryLogger({
  capture: {
    inputs:  false,  // raw LLM prompt you sent       (default: off)
    outputs: false,  // raw LLM response you received (default: off)
    repairs: true,   // repair messages on retry      (default: on)
  },
});
Defaults are conservative. Raw prompts and completions are the most sensitive payload in an LLM pipeline — they stay off until you explicitly opt in.

Always-on fields

These are sent on every event regardless of capture config. They’re the minimum Boundary needs to plot a run:
GroupFieldsWhy always on
IdentitycontractName, environment, timestamp, runIdRequired to coalesce per-attempt + terminal events into one run row.
Run metadataattempt, maxAttempts, durationMs, ok, finalThe shape of “what happened in this run.”
Contract metadatamodel, rulesCount, schema, rulesStamped so the dashboard can attribute failures to the right contract version.
Failure attribution (only on ok: false)category, issues, ruleFailuresWithout these, a failure event is just a flag — useless for triage.
SDK attributionsdk.name, sdk.version, sdk.runtimeUsed to debug version-specific behavior.

Field-to-bucket mapping

FieldGateDefault
inputcapture.inputsoff
outputcapture.outputsoff
repairscapture.repairson
Everything elsealways senton

Why raw input/output defaults to off

  • User prompts contain customer data, PII, and internal context.
  • Model completions contain proprietary business logic (lead scores, financial calcs, medical reasoning).
  • Both can contain credentials echoed back by the model.
Turning them on is a deliberate operational decision. When you do:
  1. Enable them in staging or development first and audit what actually flows through before flipping production.
  2. Pair with redaction rules that match your data shape.
  3. Or use beforeSend to hash or summarize the input before it leaves the process.

Opt-in recipe: debug staging traffic

const logger = createBoundaryLogger({
  apiKey: process.env.BOUNDARY_API_KEY,
  environment: "staging",
  capture: {
    inputs: true,
    outputs: true,
  },
  redact: {
    fields: ["email", "phone", "ssn"],
    patterns: [
      /\b\d{3}-\d{2}-\d{4}\b/,    // SSN
      /[\w.+-]+@[\w-]+\.[\w.-]+/, // email
    ],
  },
});

When you can’t capture failure context

Failure attribution (category, issues, ruleFailures) is always sent on a failed event — there is no flag to drop it. If a specific failure message would leak data because a rule interpolates record values into it, fix it at the source: rewrite the rule to return a generic message string, or use beforeSend to scrub issues[] before the event leaves the process.

Order of operations

Capture runs first — anything it strips cannot be resurrected downstream.

See also

Redaction

Fields, patterns, custom per-leaf scrubbing

beforeSend

Per-event transform or drop

BoundaryLogEvent

Full wire format