You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The ai_guardrails filter's NeMo provider currently calls /v1/guardrail/checks. That endpoint evaluates all messages in a
single HTTP call and returns a per-rail breakdown, but it does not
expose redaction:
NeMo's /v1/checks endpoint is the supported path for content
transformation. It returns a slim schema:
{
"status": "passed | blocked | modified",
"content": "text after rails processing",
"rail": "blocking rail name or null"
}
That unlocks redaction support in ai_guardrails (tracked as praxis-proxy/ai#49),
The catch: /v1/checks evaluates only the last user message per call. To preserve
today's coverage - every user message in the conversation is checked -
the provider must make N sequential HTTP calls for N user
messages.
This discussion tracks whether and how praxis-ai should migrate.
Goals
Unblock redaction (modified + content) for ai_guardrails
without relying on undocumented guardrails_data fields.
Align with the endpoint NeMo is investing in; /v1/guardrail/checks
is expected to be deprecated.
Preserve equivalent guardrail coverage: every user message in a
request body is evaluated, not only the latest turn.
Split the work cleanly: a migration PR (endpoint, response
parsing, per-message calls) lands first; a follow-up PR wires
redaction enforcement praxis-proxy/ai#49).
Non-goals (for the initial migration PR)
Applying content back into the request/response body and all redaction part.
Why?
ai_guardrails was designed around three verdicts: pass, block, and
redact.
Operators who configure NeMo with PII-masking rails today get a false
sense of safety: the proxy may record "passed" and forward the
original, unmasked body. Fixing it requires the /v1/checks response shape.
/v1/checks checks one message per call. For a chat request with
history, the provider loops over user messages and POSTs a cumulative
slice for each (e.g. [system, user1], then [system, user1, assistant1, user2], …), stopping on the first blocked result.
Benchmarks I made from #433 (TrustyAI NeMo-Guardrails, develop branch, PII
rails, ~1 ms pod-to-pod RTT):
User messages
/v1/guardrail/checks (1 call)
/v1/checks (N calls)
Overhead
1
39 ms
26 ms
~0%
5
142 ms
133 ms
~0%
10
223 ms
309 ms
+39%
20
437 ms
597 ms
+37% (~160 ms)
Takeaways:
Short conversations (1-5 user turns): negligible difference.
Longer histories (10-20 turns): ~37-39% added latency on the
guardrail hop, plus higher variance from multiple HTTP round-trips.
The overhead is on the provider call only, not total end-to-end
LLM latency - but it sits on the request path before the upstream
model is reached.
There is an open upstream request for single-call multi-message evaluation: NVIDIA-NeMo/Guardrails#2277.
If NVIDIA decides to implement it, this migration will have zero latency effect.
User stories
As a proxy operator, I want PII-masking NeMo rails to actually
mask content at the proxy, so sensitive data does not reach the
upstream model unchanged.
As a proxy operator with long chat histories, I want guardrail
coverage on every user turn, not only the latest message, so
injected content in earlier turns is still caught.
As a Praxis maintainer, I want the NeMo provider on a supported
API surface, so we are not building redaction on a response shape
that upstream treats as legacy.
As a filter author, I want migration and redaction enforcement as
separate PRs, so endpoint migration can land and be tested before
body-rewrite logic (#579) is added.
Alternatives considered
Stay on /v1/guardrail/checks.
No migration cost, all messages checked in one call. Redaction
remains impossible without scraping guardrails_data.log internals.
Upstream deprecation risk.
Proposed implementation (if we proceed)
PR 1 - Migration (this discussion)
Update NemoProvider endpoint default/docs from /v1/guardrail/checks to /v1/checks (operator-configured endpoint URL is a breaking change for existing deployments).
area/aiAI and inference filtersarchitectureArchitectural design and evaluation
1 participant
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
What?
The
ai_guardrailsfilter's NeMo provider currently calls/v1/guardrail/checks. That endpoint evaluates all messages in asingle HTTP call and returns a per-rail breakdown, but it does not
expose redaction:
NeMo's
/v1/checksendpoint is the supported path for contenttransformation. It returns a slim schema:
{ "status": "passed | blocked | modified", "content": "text after rails processing", "rail": "blocking rail name or null" }That unlocks redaction support in
ai_guardrails(tracked aspraxis-proxy/ai#49),
The catch:
/v1/checksevaluates only the last user message per call. To preservetoday's coverage - every user message in the conversation is checked -
the provider must make N sequential HTTP calls for N user
messages.
This discussion tracks whether and how praxis-ai should migrate.
Goals
modified+content) forai_guardrailswithout relying on undocumented
guardrails_datafields./v1/guardrail/checksis expected to be deprecated.
request body is evaluated, not only the latest turn.
parsing, per-message calls) lands first; a follow-up PR wires
redaction enforcement praxis-proxy/ai#49).
Non-goals (for the initial migration PR)
contentback into the request/response body and all redaction part.Why?
ai_guardrailswas designed around three verdicts: pass, block, andredact.
Operators who configure NeMo with PII-masking rails today get a false
sense of safety: the proxy may record
"passed"and forward theoriginal, unmasked body. Fixing it requires the
/v1/checksresponse shape.The same trade-off was analyzed for the ODH payload-processing NeMo
plugins in
opendatahub-io/ai-gateway-payload-processing#433.
Praxis faces the identical upstream constraint.
Cost of migrating
/v1/checkschecks one message per call. For a chat request withhistory, the provider loops over user messages and POSTs a cumulative
slice for each (e.g.
[system, user1], then[system, user1, assistant1, user2], …), stopping on the firstblockedresult.Benchmarks I made from #433 (TrustyAI NeMo-Guardrails, develop branch, PII
rails, ~1 ms pod-to-pod RTT):
/v1/guardrail/checks(1 call)/v1/checks(N calls)Takeaways:
guardrail hop, plus higher variance from multiple HTTP round-trips.
LLM latency - but it sits on the request path before the upstream
model is reached.
There is an open upstream request for single-call multi-message evaluation:
NVIDIA-NeMo/Guardrails#2277.
If NVIDIA decides to implement it, this migration will have zero latency effect.
User stories
mask content at the proxy, so sensitive data does not reach the
upstream model unchanged.
coverage on every user turn, not only the latest message, so
injected content in earlier turns is still caught.
API surface, so we are not building redaction on a response shape
that upstream treats as legacy.
separate PRs, so endpoint migration can land and be tested before
body-rewrite logic (#579) is added.
Alternatives considered
Stay on
/v1/guardrail/checks.No migration cost, all messages checked in one call. Redaction
remains impossible without scraping
guardrails_data.loginternals.Upstream deprecation risk.
Proposed implementation (if we proceed)
PR 1 - Migration (this discussion)
NemoProviderendpoint default/docs from/v1/guardrail/checksto/v1/checks(operator-configuredendpointURL is a breaking change for existing deployments).passed/blocked/modified+content+railinstead ofsuccess/blocked/error+rails_status/guardrails_data.errorin JSON body to HTTP error handling (NeMo returns4xx/5xx instead).
message slices; fail-fast on first
blocked.mock-nemo.py, and generated filter docs.**PR 2 - Redaction **
contentback into the request/response JSON body.All reactions