Enterprises usually build input controls first, because sending sensitive data to a vendor feels like the obvious risk. But most user-visible AI incidents are output incidents: a confident wrong answer shown to a customer, an off-policy statement in a generated email, malformed JSON that corrupts a downstream record. Output controls are the mirror-image discipline — filter, structure, and log what the model produces before anyone or anything consumes it.
Structure first: constrain the shape of what can leave
Free-form text is the hardest output to police. Wherever the output feeds software rather than a human reader, request structured output — Claude's structured outputs feature constrains the response to a JSON schema you define, which turns "parse whatever came back and hope" into a validation step that either passes or fails loudly. Structured outputs are available across the platforms covered by this guide (in beta on Microsoft Foundry). A schema is itself a control: a response that can only contain summary, category, and confidence fields has far fewer ways to say something it shouldn't.
Even with a schema, validate in your own code. Check enum values, ranges, and referential validity (does the ticket ID in the response actually exist?). Schema conformance says the shape is right, not that the content is safe to act on — see the output validation pattern for a full treatment.
Handle refusals and stop reasons as first-class outcomes
Your application code should branch on why a response ended, not just take its text. The API reports this via stop_reason. In particular, Anthropic documents that Claude Fable 5 can return stop_reason: "refusal" from safety classifiers, with a stop_details.category field indicating the reason — documented categories include "cyber", "bio", and "reasoning_extraction". A governance-aware application treats a refusal as a signal to log and route (to a human, or to a safe fallback message), never as text to display raw or retry blindly. Refusal categories are also exactly the telemetry your incident playbook and misuse monitoring want to see.
Filter what humans will read
For customer-facing text, add a deterministic post-filter in your own pipeline: scan generated output for content that should never leave — internal hostnames, employee names, anything matching your credential or account-number patterns — and block or redact on match. This mirrors the input-side scanner and shares its limits: patterns catch tokens, not meaning. For higher-stakes surfaces, add a policy check step (a second, cheaper model call or a rules engine) and, above a risk threshold, a human approval step (see human-in-the-loop design). Which surfaces get which depth is a risk-tiering decision, not a per-team improvisation.
Log outputs deliberately, not accidentally
Output logging serves debugging, audit, and incident response — you cannot investigate a harmful-output report without knowing what was actually generated. But output logs are also a data store you now own: they may contain personal data that entered via the prompt and came back out in the response. Decide retention for your own logs explicitly (the subject of prompt and response log management) rather than letting a debug setting become an unbounded archive. Note that your logs are independent of the platform's: Anthropic's stated default on the Claude API is to delete inputs and outputs on its backend within 30 days, and on Bedrock and Google Cloud the cloud provider is the data processor — none of which shortens the lifetime of the copy sitting in your own logging bucket.
A minimal output-side log record: request ID, timestamp, model ID, workspace or project, schema-validation result, stop_reason (and category if refused), filter verdicts, and where the output was delivered. That last field — the destination — is the one teams forget and incident responders miss most.
Where to go next
Read the input-side companion at controlling what enters prompts, then log management for the retention decisions your output logs now require.