โ†
AI Agent Builders & Citizen Developers
Proficient ยท M15 ยท lesson 15 of 34 ยท queued
Preview โ€” browse every lesson free. Enroll to mark lessons complete, open partner links and save your progress. Login & enroll โ†’
Post-Call Guardrails with Guardrails AI or NeMo Guardrails
๐Ÿ“–
now learning

Post-Call Guardrails with Guardrails AI or NeMo Guardrails

15 min

The pre-call gate (Lesson 1) catches the cheap attacks before the model sees them. The indirect-injection defenses (Lesson 2) protect against payloads in retrieved content. This lesson covers the third layer: what you do after the model has spoken. Validate the structured output against a schema. Reject responses that mention competitors or specific policy clauses. Fail closed by default when validation fails. This is where Guardrails AI's validator library and NVIDIA NeMo Guardrails' Colang-based rails earn their keep โ€” and where the production stack pattern (NeMo for routing, LlamaGuard 3 for hazard classification, Guardrails AI for structured-output validation) emerges as the 2026 consensus.

Why a Post-Call Layer Is Still Necessary

Lesson 1 argued that post-call-only safety was a 2024 mistake. That argument was about relying on post-call checks as the primary defense. The post-call layer is still a critical part of defense in depth โ€” just not the primary one. The post-call layer handles things the pre-call gate structurally cannot:

  1. Output schema validation. The model said it would return JSON with specific fields and types. The post-call layer verifies it actually did. If the model emitted malformed JSON or skipped required fields, downstream parsers will fail unpredictably; the post-call layer catches this and either auto-fixes or rejects.
  2. Hallucination detection. The model cited a study, a URL, a customer name, a transaction ID. Did those things exist? The pre-call gate can't know; the post-call validator can check (against your database, against the citations available in retrieved content, against a known-good list).
  3. Policy compliance. The legal team forbids the agent from mentioning competitors by name. The compliance team forbids the agent from quoting specific policy clauses verbatim. The pre-call gate doesn't know what the model said; the post-call validator scans the output for these patterns.
  4. Toxic content / brand voice. The model said something the brand doesn't say. The model wrote in a tone the brand doesn't use. The post-call layer catches the output before it ships.
  5. Personally Identifiable Information leakage in outputs. Even with PII tokenization at the input layer, the model can synthesize new PII (a plausible-looking SSN, an inferred email address) in its output. The post-call layer scans for PII patterns in the final output.

The post-call layer is where compliance, legal, and brand requirements get enforced as code. It's the layer that turns "the policy team is uncomfortable with the agent" into "the policy team has a config file." When the policy changes, you change the config; you don't retrain the model.

Guardrails AI: The Validator Library

Guardrails AI (the open-source library, not the company's hosted product) is the Python-first approach to post-call validation. The library ships a catalog of validators โ€” small composable checks you wire onto your agent's output. Each validator has a clear signature: take a response, return PASS, FAIL, or FIX (a corrected version).

The shape:

from guardrails import Guard
from guardrails.hub import (
    ValidJSON,
    NoMentionOfCompetitors,
    NoPersonalIdentifiableInformation,
    BrandVoiceTone,
    NoToxicLanguage,
    ProvenancePresent,
)

guard = Guard().use_many(
    ValidJSON(schema=response_schema,),
    NoMentionOfCompetitors(competitors=["AcmeBank", "WidgetCorp"],),
    NoPersonalIdentifiableInformation(on_fail="exception"),
    BrandVoiceTone(target_tone="professional-friendly",),
    NoToxicLanguage(on_fail="exception"),
    ProvenancePresent(citation_required=True,),
)

result = guard(agent_response, metadata={"retrieved_chunks": chunks})
if result.validation_passed:
    deliver(result.validated_output)
else:
    handle_failure(result.error)

The on_fail mode is the lever. Three common modes:

  • exception โ€” raise; the agent run fails closed. Default for hard-stop violations (PII leak, policy violation, schema malformation).
  • fix โ€” apply a deterministic correction (redact the competitor name, mask the SSN, strip the disallowed phrase). Default for cosmetic violations where the corrected output is still useful.
  • reask โ€” send the response back to the model with a corrective prompt ("Your previous response mentioned competitor X. Please rewrite without naming competitors."). Used for nuanced violations that need the model's reasoning to fix.

Other modes exist (filter, noop, refrain). The choice is policy-driven: how badly do you want this output to never ship?

The validator catalog

Guardrails AI's hub ships 100+ validators as of 2026. The canonical ones every team uses:

  • ValidJSON / JsonSchema โ€” does the output match the declared schema?
  • NoMentionOfCompetitors โ€” does the output name companies on your competitor list?
  • NoPersonalIdentifiableInformation โ€” does the output contain PII patterns (emails, phones, SSNs, credit cards)?
  • NoSensitiveTopics โ€” does the output discuss topics on your blocklist (politics, religion, specific health conditions)?
  • NoToxicLanguage โ€” does the output contain language a moderation model flags as toxic?
  • ProvenancePresent โ€” does the output cite sources where citations are required?
  • RestrictToTopic โ€” is the output on-topic for the agent's role?
  • ResponseLengthRange โ€” is the output within the declared length range?
  • NoSecretLeak โ€” does the output contain API keys, tokens, credentials?
  • FactualConsistencyWithSources โ€” for retrieval-augmented responses, do the claims match the retrieved chunks?

The composability is the point. You stack the validators relevant to your use case. Adding a new policy ("never recommend a specific medication brand") becomes a new validator in your stack โ€” not a system-prompt change, not a model retraining.

NeMo Guardrails: The Orchestration and Routing

NVIDIA NeMo Guardrails plays a different role. Where Guardrails AI is a Python library of validators, NeMo Guardrails is an orchestration framework that wraps the entire agent conversation in a state machine. The framework's primary language is Colang โ€” a domain-specific language for describing conversational flows, guardrails, and the routing logic between them.

The Colang shape:

define user ask about competitor
    "tell me about AcmeBank"
    "what does WidgetCorp offer"
    "compare us to BigBox"

define bot deflect competitor
    "I can speak to our offerings but not directly compare to other companies."

define flow handle competitor question
    user ask about competitor
    bot deflect competitor

define rail check input
    if user message matches "ignore previous instructions"
        bot say "I can't help with that."
        stop

define rail check output
    if bot response contains pii pattern
        bot say "I cannot share that information."
        log incident

The rails โ€” Colang's term for guardrails โ€” can fire on input (before the model sees the message), on output (after the model speaks), on retrieval (when external content arrives), and on tool execution (when the agent is about to call a tool). NeMo's value is that all four checkpoints live in one declarative spec.

The routing aspect: NeMo can route different intents to different models. "Compliance question" routes to a more cautious model with stricter guardrails. "Code generation" routes to a code-tuned model with different guardrails. The state machine handles the routing logic, the guardrails attach to each branch.

NeMo Guardrails is open-source, ships with NVIDIA AI Enterprise, and has been the de facto orchestration layer for enterprise agents that need formal conversational structure. The trade-off: the Colang DSL has a learning curve and the state-machine model can feel heavyweight for simple agents.

The Production Stack Pattern

By May 2026, the production stack pattern for guardrails has converged for serious enterprise agents:

  1. NeMo Guardrails for routing and conversation-level structure. The agent's overall flow, intent classification, and routing between specialized sub-agents are described in Colang. NeMo enforces the conversation-level rails.
  2. LlamaGuard 3 8B for hazard classification. NeMo's input and output rails delegate hazard checks to LlamaGuard 3, which returns MLCommons category labels (violence, privacy, IP, weapons, etc.). The Colang rail decides what to do based on the category.
  3. Guardrails AI for structured-output validation. When the agent emits a structured response (JSON for a tool call, structured form data, an itemized list), Guardrails AI's validators enforce the schema, brand voice, and policy compliance.

The three tools are complementary, not competing. NeMo handles the conversational state machine and high-level routing. LlamaGuard handles category-level hazard detection. Guardrails AI handles fine-grained structured-output checks. You don't need all three for every agent โ€” but for agents in regulated domains (finance, health, legal, B2B enterprise), all three layers are common.

How teams pick: if your agent is conversational with branching flows, lean on NeMo. If your agent emits structured outputs (JSON for downstream systems), lean on Guardrails AI. If your agent is in a regulated domain, expect to use both plus LlamaGuard for hazard classification.

Fail-Closed by Default

The single most important design principle for the post-call layer is fail closed by default. When validation fails, the default action is to not ship the output. The agent's response to the user is "I couldn't complete that request" or "Let me try again" โ€” not the unvalidated content.

Three reasons:

  1. The cost of false positive (block a valid output) is recoverable. The user retries, gets a different output, validation passes, the response ships. Mild UX friction.
  2. The cost of false negative (ship an invalid output) can be catastrophic. A leaked competitor name in a customer email goes to the customer. A leaked SSN goes to whoever was on the other end. The agent's invalid output became a real-world event.
  3. The blame model is clean. "The validator blocked the response" is a clear cause. "The validator was off because someone changed the config in March" is a clear forensic trail. Failing closed makes the system's behavior auditable.

The exception to fail-closed: low-stakes informational outputs. If the agent is summarizing a meeting and one validator's borderline fail would cost the user minor friction, you can fail open with a warning logged. But the default for anything user-facing in a regulated context is fail closed.

A Real Failure Mode: The Competitor Leak

A 600-person SaaS company in late 2025 ran a sales-enablement agent. The agent drafted emails to prospects based on call transcripts. Marketing had a policy: never mention competitors by name in customer-facing emails.

The agent, running on a frontier model with the system prompt "never mention competitors," routinely produced emails that did mention competitors. The pattern: a sales rep would discuss a competitor in the call transcript ("they're currently evaluating WidgetCorp"), the agent would summarize the call and draft the follow-up, and the follow-up would say something like "I understand you're considering WidgetCorp for this use case."

The agent was technically compliant with the instruction โ€” it was paraphrasing the rep's mention, not introducing the competitor. But the resulting email shipped to the prospect with the competitor name, sometimes drawing comparisons the marketing team wouldn't have made. Three prospects forwarded the emails to their procurement teams as "evidence" of who was being considered. Two deals stalled.

The team installed Guardrails AI's NoMentionOfCompetitors validator with on_fail="reask". The validator scanned the draft email for any of 14 competitor names. If found, it sent the response back to the model with: "Your draft contained the competitor name 'X.' Please rewrite the email without naming any competitor companies. You may reference 'other vendors' or 'similar products' if needed."

After deployment: zero competitor-name slips in the next 4,400 emails. The reask flow added an average of 1.8 seconds to the 8% of emails that needed correction. Sales reps did not perceive a slowdown.

The general principle: declarative validators beat system-prompt instructions for policy enforcement. The model treats system-prompt instructions as preferences. The validator treats the policy as an enforcement check.

Schema Validation and the Tool-Call Trust Boundary

The most underrated post-call validator is the simplest: verify the output matches the schema. When the agent emits a tool call, the model produces JSON. JSON has a structure โ€” field names, types, required vs optional, value ranges, enums. Models are pretty good at this. They are not perfect.

What can go wrong:

  • Wrong type โ€” string where an integer was expected. "amount": "100" instead of "amount": 100.
  • Missing required field. The schema requires customer_id; the model omitted it.
  • Out-of-range value. "refund_amount": 99999999 when the schema says max 10000.
  • Enum violation. "priority": "URGENT_NOW" when the schema enums to {low, medium, high}.
  • Extra fields the schema didn't declare. The model added a "note" field that downstream parsers will silently drop โ€” or, worse, that downstream parsers will silently accept and act on.

The schema validator catches all of these before the tool call executes. The agent gets an immediate error: "Your tool call had X validation failure. Please fix and retry." The model usually retries successfully โ€” the schema violation is feedback the model can act on.

For high-stakes tool calls (anything in the refuse-to-act category from Lesson 4), the schema validator is the last line of defense before a side effect happens. A wrong amount, a wrong recipient, a wrong action โ€” caught here, fixed cheaply. Not caught here, paid for later.

Hallucination Detection: The Hardest Validator

The validator that everyone wants and nobody perfectly delivers: does the agent's claim match reality? Specifically, for retrieval-augmented responses, do the agent's specific claims match what's actually in the retrieved chunks?

The 2026 state of the art:

  1. Claim extraction. A small LLM extracts atomic claims from the agent's response. "Customer X has 47 active subscriptions." "The next payment is due on 2026-06-12." Each claim is a discrete factual assertion.
  2. Source matching. Each claim is searched against the retrieved chunks (or a structured database). Does any chunk support the claim? An entailment model judges support.
  3. Confidence scoring. The validator returns a per-claim confidence. Claims below threshold are flagged.
  4. Action on failure. Reask with the unsupported claims highlighted. Or hard-block if the agent shouldn't be guessing.

Guardrails AI's FactualConsistencyWithSources validator (and equivalent in NeMo) implements this pattern. The precision is good (~85-92%) but not perfect; some legitimate inferences are flagged as unsupported, some hallucinations slip through. The validator is useful but it's not a guarantee โ€” it's a layer in the defense.

The other approach: structural constraints that make hallucination impossible. If the agent must answer with a citation, and the citation must point to a specific chunk index that the validator confirms exists in the retrieved set, the agent can't fabricate the citation. The model has to ground every claim. This is the design pattern for high-stakes informational agents (legal, medical, financial advisory).

The Config-as-Policy Pattern

The post-call layer's deepest organizational value is that it makes policy declarative. The compliance team can read the Guardrails AI config and see exactly what's enforced. The marketing team can read the competitor list and update it without involving engineering. The legal team can read the policy-clause blocklist and adjust it.

The pattern in practice:

  • A validators.yaml (or equivalent) lives in the agent's repo. Comp / legal / brand all have review access.
  • Changes to the config go through code review. Engineering reviews for technical correctness; the originating team reviews for policy correctness.
  • The config is the source of truth โ€” not the system prompt, not a doc somewhere, not the model's training. When in doubt, the config wins.
  • The config is versioned. When a policy change ships, the diff is auditable. When a regulator asks "what was your policy on date X," you have the file at that commit.

This is what "guardrails without lawyers" actually means. The lawyers' work is upstream โ€” they tell you what the policy is. The config encodes the policy. The validator enforces it on every output. The lawyers don't review every agent response; they review the config periodically and the audit logs when something goes wrong.

Performance Cost of the Post-Call Layer

The post-call layer adds latency. Honest accounting:

  • Schema validation โ€” sub-millisecond. Free.
  • Regex / lexical validators (competitor names, PII patterns, profanity) โ€” single-digit milliseconds. Effectively free.
  • LLM-based validators (brand voice, toxicity classification, fact-consistency) โ€” 50-500ms per validator depending on model. Real cost.
  • Reask flows โ€” full model round-trip. Multi-second cost when triggered.

The latency budget for the post-call layer: typically 100-300ms in the 95% case (cheap validators only), 1-3 seconds in the 5% case where a reask fires. For most agents this is acceptable; the user is waiting for an LLM response anyway and the extra 100-300ms is hidden in streaming.

The token cost: LLM-based validators are 0.1-0.5x the cost of the original generation (smaller / specialized models, narrower task). Reasks double the generation cost when they fire. Across an enterprise deployment, this is typically 5-15% on top of base model costs โ€” meaningful but small compared to the cost of an unmitigated policy violation.

What to NOT Validate Post-Call

Two anti-patterns to avoid:

Don't validate things the model should have prevented

If your agent is leaking SSNs on average once every 1000 outputs, the answer is not "add a stronger PII validator at the post-call layer." The answer is to fix the input layer (Lesson 1 PII tokenization), the model (better-grounded prompt, retrieval that doesn't include PII), and the tools (don't pass PII to the model in the first place). The post-call validator is the safety net, not the primary defense.

Don't pile on validators without measurement

Every validator costs latency, tokens, and false-positive UX friction. Each one needs a measurable harm it prevents. "We added 14 validators because we could" is a recipe for an agent that's slow, blocks legitimate requests, and that nobody trusts. The disciplined approach: every validator has a documented policy reason and a measured incidence rate. If no validator has fired in 60 days, ask whether it's still needed.

The Output Side of the Perimeter

The post-call layer is the output side of the agent's safety perimeter. The pre-call gate (Lesson 1) is the input side. The indirect-injection defenses (Lesson 2) cover the side door of retrieved content. The refuse-to-act pattern (Lesson 4) covers the irreversible-action edge. The eval and red-team platforms (Lesson 5) are the continuous verification that the perimeter still holds.

None of these is a "security feature." Together, they're an architecture. Production agents in 2026 ship all four sides of the perimeter as default โ€” the way production web apps ship HTTPS, authentication, input sanitization, and audit logging. Without all four, the agent is a prototype. With all four, the agent is a system you can put in front of customers.

Key Takeaways

  • The post-call layer handles output schema validation, hallucination detection, policy compliance, brand voice, and PII synthesized in outputs - things the pre-call gate structurally cannot catch.
  • Guardrails AI is the Python-first validator library; 100+ validators in the hub. Modes: exception (fail closed), fix (deterministic correction), reask (model rewrites).
  • NeMo Guardrails is the orchestration framework with Colang DSL. Rails fire on input, output, retrieval, and tool execution; routing logic in one declarative spec.
  • The 2026 production stack pattern: NeMo for routing + LlamaGuard 3 for hazard classification + Guardrails AI for structured-output validation.
  • Fail closed by default. FP cost is recoverable (user retries). FN cost can be catastrophic. Blame model stays clean.
  • The SaaS competitor-leak story: declarative NoMentionOfCompetitors validator with reask mode produced zero competitor-name slips in 4,400 emails after deployment.
  • Schema validation is the most underrated validator - catches wrong type, missing required, out-of-range, enum violation, extra fields before the tool call executes.
  • Hallucination detection (FactualConsistencyWithSources): extract claims, search retrieved chunks, entailment-score. 85-92% precision in practice.
  • Config-as-policy pattern: validators.yaml in the repo; comp/legal/brand teams review; versioned for audit. "Guardrails without lawyers" = lawyers review config, not every output.
  • Performance cost typically 5-15% of base model cost. Latency 100-300ms p95 cheap path, 1-3s p99 reask path.
  • Don't validate what the model should have prevented; don't pile on validators without measurement.