Skip to content

feat(ai): run external guardrails on the non-streaming response#556

Merged
rickcrawford merged 1 commit into
mainfrom
rickcrawford/wor-1529-output-guardrails
Jun 27, 2026
Merged

feat(ai): run external guardrails on the non-streaming response#556
rickcrawford merged 1 commit into
mainfrom
rickcrawford/wor-1529-output-guardrails

Conversation

@rickcrawford

Copy link
Copy Markdown
Contributor

What

Completes the external HTTP guardrail providers (shipped input-side in #551) on the output path. post_call / during_call entries in guardrails.external now inspect the materialized non-streaming response before it is cached or sent, blocking with the same 403 guardrail_violation envelope the built-in output guardrails use.

How

  • run_input_external_guardrails and a new run_output_external_guardrails now share one private run_external_guardrails(cfgs, content, on_input) driver, parameterized by phase (is_input() vs is_output()).
  • In relay_ai_response_with_cache, the output-guardrail block is now computed from the sync pipeline or the external providers, so an origin configured with only external output guardrails (no compiled output pipeline) is covered too. The external check runs only when the sync pipeline didn't already block, and only on 2xx response text. The existing block-handling (waste accounting, 403, cache-skip) is unchanged.

Tests

  • New runner tests use the unreachable-port fail-closed pattern (no mock server): run_output skips an input-only (pre_call) guardrail without any HTTP call, and evaluates a post_call one.
  • Full sbproxy-ai (973) and sbproxy-core (460) lib suites pass; clippy -D warnings and rustdoc -D warnings -D missing_docs clean. No config-schema change (the guardrails.external field already exists).

Scope

Non-streaming output only. Streaming-response external guardrails (per-chunk async is expensive) and AWS Bedrock (SigV4 ApplyGuardrail) remain follow-ups. As with the input side, CI can compile and unit-test the runner/decision logic but cannot validate against a live external guardrail endpoint.

Extends the external HTTP guardrail providers from the input path to the
output path. `post_call` / `during_call` entries in `guardrails.external`
now inspect the materialized non-streaming response before it is cached
or sent, blocking with the same 403 guardrail_violation envelope as the
built-in output guardrails.

The output block is now computed from the sync pipeline OR the external
providers, so an origin with only external output guardrails (no compiled
output pipeline) is covered too. The run_input/run_output runners share
one driver parameterized by phase. Streaming-response external guardrails
and AWS Bedrock (SigV4) remain follow-ups.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X19S6eQzKKExZ9RUPAHuGy
@rickcrawford rickcrawford merged commit 8f3178c into main Jun 27, 2026
4 checks passed
@rickcrawford rickcrawford deleted the rickcrawford/wor-1529-output-guardrails branch June 27, 2026 04:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant