AWS Builder Center
Amazon Bedrock Guardrails — Complete Setup Guide

Amazon Bedrock Guardrails — Complete Setup Guide

Block harmful content, redact PII, and stop hallucinations in any Bedrock app. Step-by-step guide with code for content filters, denied topics, and grounding checks

How to Add Guardrails to Any Amazon Bedrock App — Block Harmful Content, Redact PII, and Stop Hallucinations

TL;DR: Amazon Bedrock Guardrails lets you apply content filtering, PII redaction, topic blocking, and grounding checks to any model — in under 30 lines of config. Here's how to set it up, test it, and deploy it in production.



Why Every Production AI App Needs This

Most Bedrock tutorials show you how to call a model. Almost none show you what happens when a user asks your AI something they shouldn't.
At STC, the first question every enterprise client asks before go-live is: "What stops the AI from saying something that gets us sued?"
The answer is Bedrock Guardrails. It's AWS's managed layer that sits between your app and the model — and it works on every model in the Bedrock catalogue.
Here's how to build it properly.



What Guardrails Can Do

Feature
What it blocks
Content filters
Hate speech, violence, sexual content, self-harm, insults
Denied topics
Any subject you define (e.g. "competitor products", "legal advice")
Word filters
Specific words or phrases
PII redaction
Names, emails, phone numbers, SSNs, credit card numbers, and more
Grounding check
Detects hallucinations — flags responses not supported by your context
Sensitive info filter
Custom regex patterns for your own data formats



Step 1: Create a Guardrail

You can create a Guardrail via the console or programmatically. Here's the full config in Python:
Python
import boto3
bedrock = boto3.client('bedrock', region_name='us-east-1')
response = bedrock.create_guardrail(
name='production-guardrail',
description='Content safety and PII protection for customer-facing AI',
# Block harmful content categories
contentPolicyConfig={
'filtersConfig': [
{'type': 'SEXUAL', 'inputStrength': 'HIGH', 'outputStrength': 'HIGH'},
{'type': 'VIOLENCE', 'inputStrength': 'MEDIUM', 'outputStrength': 'HIGH'},
{'type': 'HATE', 'inputStrength': 'HIGH', 'outputStrength': 'HIGH'},
{'type': 'INSULTS', 'inputStrength': 'MEDIUM', 'outputStrength': 'MEDIUM'},
{'type': 'MISCONDUCT', 'inputStrength': 'HIGH', 'outputStrength': 'HIGH'},
{'type': 'PROMPT_ATTACK', 'inputStrength': 'HIGH', 'outputStrength': 'NONE'}
]
},
# Block specific topics your app should never discuss
topicPolicyConfig={
'topicsConfig': [
{
'name': 'Legal advice',
'definition': 'Providing specific legal advice, interpreting contracts, or recommending legal action',
'examples': [
'Should I sue my employer?',
'Is this contract enforceable?',
'What are my legal rights here?'
],
'type': 'DENY'
},
{
'name': 'Competitor products',
'definition': 'Discussion of specific competitor products or services in comparison to ours',
'examples': [
'How does your product compare to Salesforce?',
'Why should I use you instead of ServiceNow?'
],
'type': 'DENY'
}
]
},
# Redact PII from both inputs and outputs
sensitiveInformationPolicyConfig={
'piiEntitiesConfig': [
{'type': 'NAME', 'action': 'ANONYMIZE'},
{'type': 'EMAIL', 'action': 'ANONYMIZE'},
{'type': 'PHONE', 'action': 'ANONYMIZE'},
{'type': 'UK_NHS_NUMBER', 'action': 'BLOCK'},
{'type': 'CREDIT_DEBIT_CARD_NUMBER', 'action': 'BLOCK'},
{'type': 'AWS_ACCESS_KEY', 'action': 'BLOCK'},
{'type': 'PASSWORD', 'action': 'BLOCK'}
],
# Block custom patterns — e.g. your internal employee IDs
'regexesConfig': [
{
'name': 'EmployeeID',
'description': 'Internal employee ID format EMP-XXXXX',
'pattern': r'EMP-\d{5}',
'action': 'ANONYMIZE'
}
]
},
# What to say when guardrail blocks something
blockedInputMessaging='I cannot process that request. Please rephrase or contact support.',
blockedOutputsMessaging='I cannot provide that response. Please contact support for assistance.',
)
guardrail_id = response['guardrailId']
guardrail_version = response['version']
print(f"Guardrail created: {guardrail_id} (version {guardrail_version})")



Step 2: Apply the Guardrail to Model Calls

Adding a Guardrail to any Bedrock call is two extra parameters:
Python
import boto3
import json
bedrock_runtime = boto3.client('bedrock-runtime', region_name='us-east-1')
GUARDRAIL_ID = 'your-guardrail-id'
GUARDRAIL_VERSION = '1'
def invoke_with_guardrail(prompt: str) -> dict:
response = bedrock_runtime.invoke_model(
modelId='anthropic.claude-3-haiku-20240307-v1:0',
body=json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 500,
"messages": [{"role": "user", "content": prompt}]
}),
contentType='application/json',
accept='application/json',
# Add these two lines to any existing Bedrock call
guardrailIdentifier=GUARDRAIL_ID,
guardrailVersion=GUARDRAIL_VERSION,
trace='ENABLED' # Returns details on what was filtered
)
result = json.loads(response['body'].read())
# Check if guardrail intervened
headers = response['ResponseMetadata']['HTTPHeaders']
guardrail_action = headers.get('x-amzn-bedrock-guardrail-action', 'NONE')
return {
'text': result['content'][0]['text'],
'guardrail_action': guardrail_action,
'blocked': guardrail_action == 'GUARDRAIL_INTERVENED'
}
# Test it
result = invoke_with_guardrail("What is our refund policy?")
print(result['text'])
# Try a blocked topic
result = invoke_with_guardrail("Should I sue my employer for unfair dismissal?")
print(result['blocked']) # True
print(result['text']) # "I cannot process that request..."



Step 3: Apply Guardrails to Knowledge Bases (RAG)

Guardrails work with  retrieve_and_generate  too — same parameters:
Python
import boto3
bedrock_agent_runtime = boto3.client('bedrock-agent-runtime', region_name='us-east-1')
KNOWLEDGE_BASE_ID = 'your-kb-id'
GUARDRAIL_ID = 'your-guardrail-id'
def rag_with_guardrail(question: str) -> str:
response = bedrock_agent_runtime.retrieve_and_generate(
input={"text": question},
retrieveAndGenerateConfiguration={
"type": "KNOWLEDGE_BASE",
"knowledgeBaseConfiguration": {
"knowledgeBaseId": KNOWLEDGE_BASE_ID,
"modelArn": "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-haiku-20240307-v1:0",
"generationConfiguration": {
"guardrailConfiguration": {
"guardrailId": GUARDRAIL_ID,
"guardrailVersion": "1"
}
}
}
}
)
return response['output']['text']



Step 4: Add the Grounding Check (Stop Hallucinations)

The grounding check is the most powerful feature for RAG apps. It compares the model's response against the source documents and flags anything the documents don't support.
Python
import boto3
bedrock = boto3.client('bedrock', region_name='us-east-1')
# Add grounding check to your guardrail
bedrock.update_guardrail(
guardrailIdentifier='your-guardrail-id',
name='production-guardrail',
blockedInputMessaging='I cannot process that request.',
blockedOutputsMessaging='I cannot provide that response.',
groundingPolicyConfig={
'filtersConfig': [
{
'type': 'GROUNDING',
'threshold': 0.75 # 0-1: higher = stricter
},
{
'type': 'RELEVANCE',
'threshold': 0.75 # Block responses not relevant to the query
}
]
}
)
To use grounding checks, pass your source documents in the API call:
Python
import boto3
import json
bedrock_runtime = boto3.client('bedrock-runtime', region_name='us-east-1')
source_document = """
Our standard refund policy: customers may return products within 30 days
of purchase for a full refund. Enterprise customers have a 60-day window.
Digital products are non-refundable once downloaded.
"""
response = bedrock_runtime.apply_guardrail(
guardrailIdentifier='your-guardrail-id',
guardrailVersion='1',
source='OUTPUT', # Check model output, not input
content=[
{
"text": {
"text": "Enterprise customers get a 90-day refund window.", # WRONG — will be flagged
"qualifiers": ["grounding_source"]
}
},
{
"text": {
"text": source_document,
"qualifiers": ["grounding_source"]
}
}
]
)
print(response['action']) # GUARDRAIL_INTERVENED — response not grounded
print(response['assessments']) # Details on what failed



Step 5: Read the Trace to Understand What Fired

When  trace='ENABLED' , Bedrock returns a full breakdown of every check:
Python
import boto3
import json
bedrock_runtime = boto3.client('bedrock-runtime', region_name='us-east-1')
response = bedrock_runtime.invoke_model(
modelId='anthropic.claude-3-haiku-20240307-v1:0',
body=json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 200,
"messages": [{"role": "user", "content": "My email is test@company.com. What is the refund policy?"}]
}),
contentType='application/json',
accept='application/json',
guardrailIdentifier='your-guardrail-id',
guardrailVersion='1',
trace='ENABLED'
)
result = json.loads(response['body'].read())
# The trace is in the Amazon-Bedrock-Trace header
import base64
trace_header = response['ResponseMetadata']['HTTPHeaders'].get('amazon-bedrock-trace')
if trace_header:
trace = json.loads(base64.b64decode(trace_header))
# See what PII was found
for assessment in trace.get('guardrail', {}).get('inputAssessment', {}).values():
pii_found = assessment.get('sensitiveInformationPolicy', {}).get('piiEntities', [])
for pii in pii_found:
print(f"PII detected: {pii['type']} — action: {pii['action']}")
# Output: PII detected: EMAIL — action: ANONYMIZE



What Guardrails Cost

Guardrail pricing is per 1,000 text units processed:
Feature
Price
Content filters
$0.75 per 1,000 text units
Denied topics
$1.00 per 1,000 text units
Word filters
$0.75 per 1,000 text units
PII detection
$0.10 per 1,000 text units
Grounding check
$0.10 per 1,000 text units
At 10,000 queries/month with all features enabled: roughly $20–30/month. For the protection it provides, this is a no-brainer.



Guardrails Checklist for Production

Before you go live, tick these off:
  • [ ] Content filters enabled for all harmful categories (at least MEDIUM strength)
  • [ ] Denied topics defined for anything your app should never discuss
  • [ ] PII redaction on both INPUT and OUTPUT
  • [ ] Grounding check enabled if you're using RAG
  • [ ] Trace enabled in staging — disabled in production (saves cost)
  • [ ] Custom blocked messages that don't confuse users
  • [ ] Guardrail ID stored in environment variables or Secrets Manager — not hardcoded
  • [ ] CloudWatch alarm on guardrail intervention rate (spike = something's wrong)



Resources



I'm Meghana Rajagopal, lead Cloud & AI Delivery at STC (AWS Premier Partner) and AWS ML Engineer Associate. I write about practical AWS AI/ML solutions and architecture. Connect with me on  LinkedIn    .Follow for weekly AWS AI content.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article