Guardrails & Safety Systems
Build guardrails around LLMs: input filtering, output validation against schemas and rules, content moderation, jailbreak defense and layered safety — deterministic controls in Java.
On this page
A language model is a probabilistic component; guardrails are the deterministic code that makes it safe to deploy. They wrap the model call — checking input on the way in and output on the way out — so that however the model behaves, harmful results are caught. This tutorial builds a layered guardrail system.
Key Takeaways
- Guardrails are deterministic code, not prompts — that is what makes them reliable.
- Validate input (before the model) and output (before the user or an action).
- Defense is layered: no single check is sufficient against adversarial input.
- Prompts steer; code enforces. Rely on code for anything that must not escape.
The guardrail architecture
Input filtering
Check input before spending a model call and before untrusted text reaches the prompt:
public InputCheck checkInput(String input) {
// Size bound — an oversized input is a cost and a potential DoS.
if (input.length() > MAX_INPUT_CHARS) {
return InputCheck.reject("input too long");
}
// Known malicious patterns (jailbreak signatures, injection markers).
if (jailbreakDetector.looksLikeAttack(input)) {
return InputCheck.flag("possible injection"); // flag, don't just pass
}
// Optional: a moderation model for disallowed content categories.
if (moderation.isDisallowed(input)) {
return InputCheck.reject("content policy");
}
return InputCheck.ok();
}Output validation
The most important layer, because it catches problems regardless of how they arose — jailbreak, injection, or the model simply going wrong:
public OutputCheck validateOutput(String output, Context context) {
// 1. Schema/shape — use structured output, then verify.
if (!matchesExpectedShape(output)) {
return OutputCheck.retry("malformed output");
}
// 2. Scope — did it stay on-topic and in-policy?
if (isOffScope(output, context)) {
return OutputCheck.block("out of scope");
}
// 3. Content — no disallowed material, no leaked secrets.
if (containsDisallowed(output) || leaksSecrets(output, context)) {
return OutputCheck.block("policy violation");
}
// 4. Business rules — domain-specific constraints.
if (!satisfiesBusinessRules(output, context)) {
return OutputCheck.block("business rule");
}
return OutputCheck.ok();
}Content moderation
For user-facing applications, a moderation layer screens both input and output for disallowed content categories:
// A moderation model (a dedicated classifier) checks content against policy
// categories. Cheaper and faster than the main model, run on both directions.
ModerationResult result = moderationModel.classify(text);
if (result.flagged()) {
return handlePolicyViolation(result.categories());
}This protects users from harmful output and protects you from generating it — both matter for a public product.
Jailbreak defense
Jailbreaks try to make the model ignore its instructions. Defend in layers, because any single layer is beatable:
- Input filtering — catch known jailbreak patterns.
- A firm system prompt — clear scope and refusal instructions steer the model. See prompt engineering.
- Output validation — catch violations regardless of how the input was crafted.
- Action gating — consequential actions authorized in code, immune to what the model says.
The key insight: you are not trying to make the model unjailbreakable (you cannot), but to make a successful jailbreak harmless — it produces output that your validation blocks and actions your code refuses.
Layered safety in practice
public Response handleSafely(String input, Context context) {
// Layer 1: input.
InputCheck in = checkInput(input);
if (in.rejected()) return Response.refused(in.reason());
// Layer 2: the model, with a firm system prompt.
String output = model.chat(SAFE_SYSTEM_PROMPT, input);
// Layer 3: output validation.
OutputCheck out = validateOutput(output, context);
if (out.blocked()) return Response.refused(out.reason());
if (out.needsRetry()) return handleSafely(input, context); // bounded retries
// Layer 4: actions (if any) are separately authorized in code.
return Response.ok(output);
}Balancing safety and usefulness
Guardrails that are too aggressive frustrate legitimate users — a support bot that refuses half of reasonable questions is useless, however safe. Tune the balance with your evaluation set: measure both the harmful-output rate (should be near zero) and the false-refusal rate (should be low), and adjust to keep both acceptable. Safety that destroys usefulness is its own kind of failure.
Next
Frequently Asked Questions
What are guardrails in an LLM application?
How do I validate LLM output?
What is a jailbreak and how do I defend against it?
Should guardrails be prompts or code?
Related tutorials
- Model Distillation & QuantizationMake models smaller and faster: quantization (GGUF, GPTQ, AWQ), knowledge distillation, the accuracy-vs-efficiency trade-off, and when self-hosting a compressed model makes sense.
- LLMOps & MLOps for Generative AIThe operational practice of running LLM features: prompt versioning, evaluation in CI/CD, model registries, A/B testing and canary rollouts of prompt and model changes — for Java teams.
- LLM Evaluation & BenchmarksHow to evaluate LLMs and LLM applications: what public benchmarks like MMLU and HumanEval measure, their limits, and building a custom evaluation suite that reflects your real task.
- GenAI on AWS, Azure & GCPRun generative AI on the major clouds from Java: Amazon Bedrock, Azure OpenAI and Google Vertex AI compared, with Spring AI and LangChain4j integration and how to choose.