Guardrail Libraries: Guardrails.ai and Outlines
Guardrail libraries are frameworks that enforce constraints on LLM output at the generation level, not after. They work by steering the model toward valid tokens during decoding, dramatically reducing invalid outputs. Guardrails.ai and Outlines are the two industry leaders. Using guardrails, teams report 95%+ valid outputs on first attempt (Guardrails.ai, 2025).
This article compares the two libraries, teaches you how to use them, and shows when guardrails are worth the extra complexity.
What Are Guardrails?
A guardrail is a constraint applied during LLM token generation. Instead of generating freely and hoping for valid output, the model's token choices are restricted to only those that maintain validity. For example, if you want JSON output, the guardrail ensures the first token is { and subsequent tokens form valid JSON.
Guardrails reduce the need for retries. Valid outputs on first attempt increase from 50–80% (with good prompting) to 95%+ (with guardrails).
Guardrails.ai: Rule-Based Constraints
Guardrails.ai is a framework for defining validation rules and repairing invalid outputs. It supports schema validation, safety checks, and LLM-powered repair.
Installation
pip install guardrails-ai
Basic Usage: Schema Validation
from guardrails.hub import JsonSchema, ToxicLanguage
from guardrails import Guard
# Define schema
schema = {
"type": "object",
"properties": {
"sentiment": {"type": "string", "enum": ["positive", "negative", "neutral"]},
"confidence": {"type": "number", "minimum": 0, "maximum": 1}
},
"required": ["sentiment", "confidence"]
}
# Create guard with validators
guard = Guard.from_pydantic(
output_class=SentimentAnalysis, # Pydantic model
num_reasks=3 # Retry up to 3 times on failure
)
# Use guard with LLM
response = guard.validate(
llm_output=llm_response,
num_reasks=3
)
if response.validation_passed:
print(response.validated_output)
else:
print("Validation failed after retries:", response.error_message)
Custom Validators
Define custom business logic validators:
from guardrails import Validator, register_validator
from typing import Any
@register_validator("price_range", data_type="number")
class PriceValidator(Validator):
"""Ensure price is in valid range."""
def validate(self, value: Any, metadata: dict) -> Any:
min_price = metadata.get("min_price", 0)
max_price = metadata.get("max_price", 1000000)
if not (min_price <= value <= max_price):
raise ValueError(f"Price {value} must be between {min_price} and {max_price}")
return value
# Use in guard
guard = Guard.from_string_schema(
"""
{
"type": "object",
"properties": {
"price": {
"type": "number",
"validators": [
{
"name": "price_range",
"on_fail": "reask",
"min_price": 10,
"max_price": 10000
}
]
}
}
}
"""
)
LLM-Powered Repair
Guardrails.ai automatically retries with LLM-generated corrections:
guard = Guard.from_pydantic(
output_class=SentimentAnalysis,
num_reasks=3
)
# The guard will:
# 1. Parse and validate output
# 2. If invalid, send corrective prompt to LLM
# 3. Re-validate LLM's attempt
# 4. Repeat up to 3 times
response = guard.validate(
llm_output=llm_response,
num_reasks=3
)
Guardrails generates the repair prompts automatically, saving you from writing them manually.
Outlines: Constrained Generation
Outlines is a library for guided generation that constrains tokens during decoding. Unlike Guardrails.ai (post-processing repair), Outlines steers the model in real-time.
Installation
pip install outlines
JSON Generation
Generate JSON guaranteed to match a schema:
from outlines import models, generate
import json
# Load model with guided generation
model = models.transformers("mistral-7b-instruct")
# Define schema as Pydantic model
from pydantic import BaseModel
class SentimentAnalysis(BaseModel):
sentiment: str # Will be constrained to enum values
confidence: float
# Generate JSON matching schema
generator = generate.json(model, SentimentAnalysis)
output = generator("Analyze sentiment of: [text]", max_tokens=200)
# output is guaranteed valid JSON matching SentimentAnalysis
Regular Expression Constraints
Generate output matching a regex pattern:
from outlines import models, generate
model = models.transformers("mistral-7b-instruct")
# Generate email addresses matching regex
phone_pattern = r"^\+1-\d{3}-\d{3}-\d{4}$"
generator = generate.regex(model, phone_pattern)
output = generator("Extract phone number: [text]")
# output matches pattern: "+1-555-123-4567"
Choice Constraint
Force the model to choose from a set:
from outlines import models, generate
model = models.transformers("mistral-7b-instruct")
# Force choice between options
choices = ["positive", "negative", "neutral"]
generator = generate.choice(model, choices)
output = generator("Classify sentiment: [text]")
# output is one of: "positive", "negative", "neutral"
Comparing Guardrails.ai vs Outlines
| Aspect | Guardrails.ai | Outlines |
|---|---|---|
| Approach | Post-processing + LLM repair | Real-time token steering |
| Valid outputs | 85–95% after retries | 95%+ on first attempt |
| Setup time | Medium (define validators) | Low (schema + regex) |
| Cost | High (multiple LLM calls for repair) | Low (single generation) |
| Model support | Works with API models (OpenAI, Anthropic) | Local models only |
| Flexibility | Very high (custom validators) | Medium (schema/regex) |
| Best for | Cloud APIs, complex rules | Local models, simple schemas |
Hybrid Approach: Guardrails + Outlines
Combine both for maximum reliability:
- Use Outlines for local models to get valid JSON on first attempt.
- Use Guardrails.ai for cloud API models with retry/repair on failure.
- Add custom validators to Guardrails for business logic.
Example:
# For cloud API (OpenAI, Anthropic)
guard = Guard.from_pydantic(output_class=SentimentAnalysis)
response = guard.validate(llm_output, num_reasks=3)
# For local model with Outlines
generator = generate.json(model, SentimentAnalysis)
output = generator("Analyze sentiment", max_tokens=200)
Key Takeaways
- Guardrails.ai is post-processing validation with LLM-powered repair; best for cloud APIs.
- Outlines constrains tokens during decoding; best for local models and guaranteed valid outputs.
- Guardrails increase first-attempt validity from 50–80% to 95%+, eliminating most retries.
- Custom validators in Guardrails.ai enable domain-specific constraints.
- Hybrid approaches (Outlines for local, Guardrails for API) offer best of both worlds.
Frequently Asked Questions
Do guardrails reduce response quality?
No. By steering toward valid outputs, they often improve quality because the model doesn't waste tokens on malformed JSON.
What's the latency overhead?
Outlines adds minimal overhead (token steering is microseconds). Guardrails.ai's latency depends on how many reasks are needed; 1–2 retries add ~1–2 extra LLM calls.
Can I use guardrails with streaming?
Yes, but it's complex. Outlines works with streaming natively. Guardrails.ai requires buffering the entire response before validation.
Which is better for LLM safety (preventing harmful output)?
Guardrails.ai has built-in safety validators for toxicity, PII, and jailbreak detection. Outlines focuses on schema/format validity. Use Guardrails for comprehensive safety.