All articles
January 25, 2025 6 min read

Guardrails: the line between an agent demo and one you can deploy

An agent with real tools and real users needs more than a clever prompt. Input and output guardrails are what keep it safe, on-topic, and out of trouble in production.

Written forEngineeringProduct
GuardrailsAI AgentsSafety

The gap between an agent that wows in a demo and one you'd actually put in front of customers is mostly guardrails. A demo trusts the model to behave. Production assumes it won't — and wraps every input and output in checks that keep a bad turn from becoming a bad incident.

User inputInput guardrailfailBlock / refusepassAgent · LLM + toolsOutput guardrailfailRedact / retrypassResponse
Guardrails wrap the agent on both sides: inputs are screened before the model sees them, outputs before the user does.

Two layers: input and output

  • Input guardrails — screen for prompt injection, PII, jailbreak attempts, and off-topic or abusive requests before the agent ever runs.
  • Output guardrails — validate the response against a schema, check for hallucinated facts and PII leakage, and catch toxic or off-brand content before it reaches the user.

Guardrail the tools, not just the text

The scariest thing an agent does isn't talk — it's act. Every tool is attack surface. Default tools to read-only, scope credentials narrowly, validate arguments before execution, and require human approval for anything irreversible. A guardrail on the language means nothing if the agent can still drop a table.

Fail safe, not silent

When a guardrail trips, it needs a defined next step — not a swallowed error. Depending on the case: block and refuse, redact and continue, regenerate with feedback, or hand off to a human. And log every trip, because your guardrail failures are your best early-warning signal.

The shape of a guarded agent
const clean = await inputGuards(userInput);   // injection, PII, topic
if (!clean.ok) return refuse(clean.reason);

const draft = await agent.run(clean.input, { tools: readOnlyByDefault });

const safe = await outputGuards(draft);        // schema, PII, grounding
return safe.ok ? safe.output : handoffToHuman(draft);
You don't earn trust with a better prompt. You earn it by assuming the model will fail and being ready when it does.
Building something with LLMs?
I help teams ship GenAI that’s reliable and cost-efficient.
Let’s talk