How to beginner · 3 min read

How to write custom validators in Guardrails AI

Quick answer
In Guardrails AI, write custom validators by defining Python functions that accept the input value and return a boolean or raise an exception. Register these functions with guard decorators or in the validators section of your rail schema to enforce custom validation logic during AI interactions.

PREREQUISITES

  • Python 3.8+
  • pip install guardrails-ai
  • Basic knowledge of Python functions and decorators

Setup

Install the guardrails-ai package and import necessary modules to start defining custom validators.

bash
pip install guardrails-ai

Step by step

Define a Python function as a validator that checks input values and integrate it into a Guardrails rail schema. Use the @guard decorator or specify the validator in the validators section of your rail YAML or JSON schema.

python
from guardrails import Guard

# Define a custom validator function
# It should raise ValueError if validation fails

def is_positive(value):
    if not isinstance(value, (int, float)) or value <= 0:
        raise ValueError("Value must be a positive number.")
    return True

# Define a rail schema with a field using the custom validator
rail_schema = {
    "fields": [
        {
            "name": "age",
            "type": "integer",
            "validators": ["is_positive"]
        }
    ],
    "validators": {
        "is_positive": is_positive
    }
}

# Create a Guard instance with the schema
guard = Guard(rail=rail_schema)

# Example input to validate
input_data = {"age": 25}

# Validate input
validated = guard.validate(input_data)
print("Validation passed:", validated)

# Example invalid input
try:
    guard.validate({"age": -5})
except Exception as e:
    print("Validation error:", e)
output
Validation passed: {'age': 25}
Validation error: Value must be a positive number.

Common variations

You can write async validators by defining async functions and registering them similarly. Also, custom validators can be used with YAML rail files by referencing the validator name in the validators section and loading the Python functions at runtime.

python
import asyncio
from guardrails import Guard

async def is_non_empty_string(value):
    if not isinstance(value, str) or not value.strip():
        raise ValueError("Value must be a non-empty string.")
    return True

rail_schema = {
    "fields": [
        {
            "name": "username",
            "type": "string",
            "validators": ["is_non_empty_string"]
        }
    ],
    "validators": {
        "is_non_empty_string": is_non_empty_string
    }
}

guard = Guard(rail=rail_schema)

async def validate_async():
    valid = await guard.validate_async({"username": "Alice"})
    print("Async validation passed:", valid)

    try:
        await guard.validate_async({"username": "  "})
    except Exception as e:
        print("Async validation error:", e)

asyncio.run(validate_async())
output
Async validation passed: {'username': 'Alice'}
Async validation error: Value must be a non-empty string.

Troubleshooting

  • If your custom validator is not called, ensure it is correctly registered in the validators dictionary of your rail schema.
  • Raise ValueError with a clear message inside your validator to signal validation failure.
  • For async validators, use validate_async method and ensure your environment supports async execution.

Key Takeaways

  • Define custom validators as Python functions that raise exceptions on invalid input.
  • Register validators in the rail schema under the 'validators' key for Guardrails to use them.
  • Use async validators with Guardrails' async validation methods for asynchronous checks.
Verified 2026-04
Verify ↗