Welcome back to our Vijil Dome series! In Part 1, we explored how to get started with Dome and integrate it seamlessly with OpenAI clients. Part 2 showed you how to leverage Dome's powerful Langchain integrations for more complex AI workflows.
Today, we're diving into one of Dome's most powerful features: creating custom guardrails. While Dome comes with robust built-in detectors for common security, privacy, and moderation concerns, every application has unique requirements. Custom guardrails allow you to implement business-specific logic, domain-specific validations, and tailored protection mechanisms that align perfectly with your use case.
Why Custom Guardrails Matter
AI applications often need specialized protection beyond standard safety filters. Consider these scenarios:
- Financial services might need to detect and block queries attempting to manipulate trading decisions
- Healthcare applications require validation that medical advice requests are appropriate for the AI's scope
- Educational platforms may want to ensure student queries remain within curriculum boundaries
- Enterprise systems often need to enforce company-specific policies and compliance requirements
Custom guardrails give you the flexibility to implement these domain-specific protections while leveraging Dome's powerful infrastructure for detection, logging, and response handling.
Building Your First Custom Guardrail: PII Phone Number Detector
Let's walk through creating a practical custom guardrail that detects and blocks potential phone number sharing in user queries. This is particularly useful for applications that need to prevent users from accidentally sharing personal contact information.
Step 1: Setting Up the Custom Detector
First, let's create our phone number detection logic:
import re
from vijil_dome.detectors import (
DetectionCategory,
DetectionResult,
DetectionMethod,
register_method,
)
# Define our custom detector name
PHONE_NUMBER_DETECTOR = "phone-number-detector"
# Register with the Privacy category since we're protecting PII
@register_method(DetectionCategory.Privacy, PHONE_NUMBER_DETECTOR)
class PhoneNumberDetector(DetectionMethod):
def __init__(self,
block_international=True,
strict_mode=False):
super().__init__()
self.block_international = block_international
self.strict_mode = strict_mode
# Define phone number patterns
self.us_pattern = re.compile(
r'(\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}|\d{10})'
)
self.international_pattern = re.compile(
r'(\+\d{1,3}[-.\s]?\(?\d{1,4}\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9})'
)
async def detect(self, query_string: str) -> DetectionResult:
# Check for US phone numbers
us_matches = self.us_pattern.findall(query_string)
# Check for international numbers if enabled
intl_matches = []
if self.block_international:
intl_matches = self.international_pattern.findall(query_string)
# Determine if we should flag this query
flagged = bool(us_matches or intl_matches)
# In strict mode, be more aggressive about potential numbers
if self.strict_mode and not flagged:
# Look for sequences that might be phone numbers
digit_sequences = re.findall(r'\d{7,}', query_string)
flagged = len(digit_sequences) > 0
# Build metadata for logging and analysis
metadata = {
"type": type(self),
"query_string": query_string,
"us_phone_matches": us_matches,
"international_matches": intl_matches,
"strict_mode_triggered": self.strict_mode and bool(re.findall(r'\d{7,}', query_string)),
"response_string": (
"I can't process requests containing phone numbers to protect your privacy. "
"Please remove any phone numbers and try again."
) if flagged else "Query processed successfully"
}
return flagged, metadataStep 2: Integrating with Your Dome Configuration
Now let's integrate our custom detector into a Dome configuration. Remember to define your custom detector before instantiating your configuration:
# Import and define custom detector (code from Step 1 goes here)
# ... PhoneNumberDetector class definition ...
from vijil_dome import Dome
# Configure Dome with our custom guardrail
dome_config = {
"pii-detection": {
"type": "privacy",
"methods": ["phone-number-detector"],
"early-exit": True,
},
"input-guards": ["pii-detection"],
"output-guards": ["pii-detection"],
"input-early-exit": True
}
# Initialize Dome
dome = Dome(dome_config)Step 3: Testing Your Custom Guardrail
Let's test our phone number detector with various inputs:
import asyncio
async def test_phone_detector():
# Test cases
test_queries = [
"Call me at (555) 123-4567 when you're ready",
"My number is 555-123-4567",
"Contact support at +1-800-555-0123",
"I need help with my account balance", # Safe query
"The reference number is 1234567890", # Might trigger strict mode
]
for query in test_queries:
try:
# Process through Dome
result = await dome.async_guard_input(query)
print(f"Query: '{query}'")
flagged = result.flagged
response = result.response_string
print(f"Result: {flagged=} {response=}")
print("-" * 50)
except Exception as e:
print(f"Error processing '{query}': {e}")
# Run the test
asyncio.run(test_phone_detector())
Expected Output
When you run this test, you should see something like:
Query: 'Call me at (555) 123-4567 when you're ready'
Result: flagged=True response="Blocked by input guardrail at Guard:pii-detection I can't process requests containing phone numbers to protect your privacy. Please remove any phone numbers and try again."
--------------------------------------------------
Query: 'My number is 555-123-4567'
Result: flagged=True response="Blocked by input guardrail at Guard:pii-detection I can't process requests containing phone numbers to protect your privacy. Please remove any phone numbers and try again."
--------------------------------------------------
Query: 'Contact support at +1-800-555-0123'
Result: flagged=True response="Blocked by input guardrail at Guard:pii-detection I can't process requests containing phone numbers to protect your privacy. Please remove any phone numbers and try again."
--------------------------------------------------
Query: 'I need help with my account balance'
Result: flagged=False response='Query processed successfully'
--------------------------------------------------
Query: 'The reference number is 1234567890'
Result: flagged=True response="Blocked by input guardrail at Guard:pii-detection I can't process requests containing phone numbers to protect your privacy. Please remove any phone numbers and try again."
--------------------------------------------------Best Practices for Custom Guardrails
1. Choose the Right Detection Category
- Security: Threats, injections, malicious content
- Privacy: PII, sensitive data, personal information
- Moderation: Inappropriate content, harassment, spam
- Integrity: Misinformation, bias, factual accuracy
- Generic: General-purpose, business logic, custom rules
2. Implement Comprehensive Logging
Always include detailed metadata in your DetectionResult. This helps with:
- Debugging and improving your detectors
- Compliance and audit requirements
- Understanding user behavior patterns
- Fine-tuning detection sensitivity
3. Test Thoroughly
Create comprehensive test suites covering:
- Expected positive cases (should be blocked)
- Expected negative cases (should be allowed)
- Edge cases and boundary conditions
- Performance with large inputs
4. Consider Performance
Custom detectors run on every request, so optimize for:
- Efficient regex patterns
- Minimal external API calls
- Appropriate caching strategies
- Asynchronous operations where possible
Conclusion
Custom guardrails in Vijil Dome provide the flexibility to implement domain-specific protection while leveraging a robust, battle-tested infrastructure. Whether you're building financial applications, healthcare platforms, or enterprise systems, custom detectors allow you to encode your unique business logic and compliance requirements directly into your AI safety layer.
In our phone number detector example, we've seen how to create a practical custom guardrail that protects user privacy while providing clear feedback. The same patterns can be applied to create detectors for industry-specific terminology, company policies, regulatory compliance, or any other custom logic your application requires.
As you build your custom guardrails, remember that they're most effective when combined with Dome's built-in detectors and integrated into a comprehensive AI safety strategy. Start with simple detectors, test thoroughly, and iterate based on real-world usage patterns.
Ready to implement your own custom guardrails? Check out the complete documentation for more advanced patterns and examples. And if you missed the earlier parts of this series, be sure to read Part 1 on getting started with OpenAI integration and Part 2 on Langchain workflows.
Have questions about implementing custom guardrails for your specific use case? We'd love to hear from you and help you build robust, domain-specific AI protection systems with Vijil Dome.


