Guardrails for Customer-Facing AI: Defense in Depth, Not a Safety Prompt

Carson Rodrigues

Carson Rodrigues / December 29, 2025

8 min read––– views

fdesecurityai-agents

There's a moment in every customer-facing AI deployment where someone on the customer's side asks: "What stops it from saying something terrible to our users?" If your answer is "we told it not to in the system prompt," you don't have a guardrail. You have a suggestion.

Real guardrails are layered, and — this is the part that took me longest to internalize — the most important layer isn't a filter at all. Let me walk through the stack from the outside in, the way a request actually flows.


Layer one: input filters, the cheap bouncer

Before user input reaches your main model, a fast, cheap pass should catch the obvious:

  • Off-topic and abuse classification. A small model or classifier that flags inputs wildly outside the agent's scope. A dental-booking agent doesn't need to engage with requests for investment advice — deflecting early is cheaper and safer than letting the main model improvise.
  • Injection heuristics. Patterns like "ignore your previous instructions," attempts to extract the system prompt, roleplay framings. You won't catch everything (more on that honesty below), but you'll catch the low-effort majority.
  • PII you don't want. If a user pastes a full card number, you want it caught and masked before it enters your context window and your logs, not after.

Keep this layer fast — tens of milliseconds, not a second. For voice agents it has to run on streaming transcripts, which is its own engineering problem: you're classifying a sentence that isn't finished yet, so you flag provisionally and confirm at end-of-utterance. And keep it humble: input filters are a coarse sieve. Their job is volume reduction, not security.


Layer two: the real guardrail is what the agent can't do

Here's the thesis of this post: filters constrain what the agent says; tool scoping constrains what it can do. Only the second one is load-bearing.

A customer-facing agent that can only call get_appointment_slots, book_appointment, and cancel_appointment(confirmation_required=true) has a small, enumerable worst case. It doesn't matter how creative the jailbreak is — the blast radius is bounded by the tool surface. Compare that with an agent holding a generic query_database tool and a "please be careful" paragraph in the prompt. One of these systems is safe by construction; the other is safe by vibes.

The design rules I hold to:

  • Tools take the narrowest arguments that do the job. get_orders(customer_id) where customer_id comes from the authenticated session, never from the model. The model should not be able to name whose data it touches.
  • Reads are free, writes are gated. Any state-changing tool gets validation at the tool boundary, hard business-rule limits enforced in code (refund caps, booking windows), and for the risky ones, explicit user confirmation before execution.
  • Permissions live in the backend, not the prompt. "Only discuss topics X and Y" in a prompt is a preference. A tool API that only exposes X and Y is a fact.
  • The worst case is written down. For every tool, someone has answered: if the model calls this with the most adversarial arguments it can produce, what happens? If the answer is unacceptable, the fix is in the tool, not the prompt.

When a customer asks me what stops the agent from doing something terrible, the answer I want to give is: "It has no tool that can do that." Everything else in this post is refinement on top of that.


Layer three: output checks, the last look

Between the model's response and the user's screen (or ear), one more pass:

  • Groundedness checks for factual claims — does the stated balance match what the tool returned? This catches the model "improving" on tool output, one of the classic silent failure modes.
  • Policy filters for content that must never ship: medical or legal advice from an agent not authorized to give it, commitments the business can't honor ("we'll refund you, guaranteed"), competitor disparagement.
  • Format and leakage checks — no system prompt fragments, no internal tool names, no raw stack traces reaching the user.

For voice, output checking competes directly with latency, since you're checking a stream you're already speaking. The compromise that works: fast deterministic checks inline on the stream, heavier checks on the complete response with the ability to interrupt — plus the knowledge that layer two already bounded the real damage.

The jailbreak reality check

Time for honesty, because customers ask and deserve a straight answer: a sufficiently motivated user will get your model to say something off-script. Prompt injection and jailbreaking are unsolved. Filters raise the effort; they don't eliminate the outcome. Anyone selling you a jailbreak-proof wrapper is selling you a warm feeling.

The mature framing is to separate two risks:

  1. The agent says something embarrassing. Real, bounded, survivable. If a user spends twenty minutes engineering your dental assistant into writing a poem about pirates, the harm is a screenshot. Design layers one and three to make this hard, monitor for it, and keep perspective.
  2. The agent does something harmful. Leaks another user's data, issues an unauthorized refund, executes a destructive action. This is the risk that actually matters — and it's exactly the one that tool scoping eliminates by construction rather than by filtering.

Security budget should follow that asymmetry. I've seen teams spend weeks hardening the system prompt against extraction while the same agent held a tool that could query any customer's records. The prompt is not the crown jewels. The tools are.

One genuinely dangerous variant deserves its own callout: injection through tool output. If your agent reads web pages, emails, or documents, those are attacker-controlled inputs arriving with the trust level of "data." Treat retrieved content as untrusted, never let it override instructions, and never let it trigger a write-action without the same gates user input faces.


Refusal UX: decline without insulting anyone

Guardrails fire on legitimate users far more often than on attackers — someone phrases a normal request oddly, or asks something adjacent to a blocked topic. If the response is a stiff "I cannot assist with that request," you've turned a false positive into a lost customer.

What good refusal design looks like:

  • Redirect rather than reject. "That's not something I can help with here — but I can check your booking or connect you with the clinic. Which would help?" Every refusal names what the agent can do.
  • Never lecture. No implication the user did something wrong; usually they didn't.
  • Escalate on repeat. Two or three guardrail hits in one session means the agent isn't serving this user — hand off to a human gracefully instead of looping refusals. Rage-inducing refusal loops show up in transcripts as users repeating themselves louder, and on voice calls you can literally hear it.
  • Track refusals as a product metric. A refusal spike usually means a guardrail broke or drifted, and users are paying for it.

What regulated industries add

Deploying into healthcare, finance, or insurance changes the posture from "best effort" to "demonstrable":

  • Auditability. Every guardrail decision — what fired, on which turn, what the user saw instead — logged and retrievable. Regulators ask "show me," not "reassure me."
  • Disclosure. In many jurisdictions users must be told they're talking to an AI, up front, with a path to a human. Build it in from day one; retrofitting disclosure flows is miserable.
  • Human oversight for consequential actions. Decisions affecting coverage, credit, or care don't get fully delegated to the model — the agent gathers and prepares, a human authorizes. This is increasingly a legal requirement, not just prudence.
  • Data handling as contract. Where transcripts live, retention windows, redaction standards, and which model providers may see what — negotiated and written down before launch.

The pattern across all of it: regulated customers don't ask you to be perfect. They ask you to show your controls, prove they fire, and demonstrate what happens when they do. Which — conveniently — is exactly what an eval suite with a never-do set at 100% is for.


The takeaway

Filters on the way in, scoped tools at the core, checks on the way out, honesty about jailbreaks, refusals that keep the customer, and an audit trail for the industries that need one. Rank the layers by what they actually bound: the prompt persuades, filters discourage, but the tool surface is the only guardrail the model can't talk its way past.


Related reading

Available for senior AI / contract / FDE work

Building something with AI?

Voice agents, MCP servers, LLM pipelines, agentic workflows — pick a slot, drop a message, or send your email and I'll reply within a day.

or leave your email

Replies within ~24 hours · Remote-first · global · open to relocation