Skip to content

Separate Input and Output Checks ​

Learn how to use guardrails separately for input and output validation, giving you full control over your LLM calls.

Overview ​

Instead of using LLMRails which handles everything automatically, you can use GuardrailSystem to check input and output separately. This gives you:

  • Full control over LLM invocation
  • Ability to use any LLM provider or custom LLM
  • Separate handling of input and output validation
  • Custom error handling and retry logic

Basic Pattern ​

The basic pattern is:

  1. Check input using check_input()
  2. Call your LLM if input passes
  3. Check output using check_output()
  4. Return response if output passes

Example 1: Basic Separate Checks ​

python
from elsai_guardrails.guardrails import GuardrailSystem, GuardrailConfig

# Create guardrail system (no LLM needed)
guardrail = GuardrailSystem.from_config("config.yml")

# Step 1: Check user input
user_input = "What is machine learning?"
input_result = guardrail.check_input(user_input)

if not input_result.passed:
    print(f"Input blocked: {input_result.message}")
    return  # Do not proceed to LLM

# Step 2: Input passed, call your LLM
def my_llm_call(prompt: str) -> str:
    # Replace with your actual LLM call
    return f"Response to: {prompt}"

llm_response = my_llm_call(user_input)

# Step 3: Check LLM output
output_result = guardrail.check_output(llm_response)

if not output_result.passed:
    print(f"Output blocked: {output_result.message}")
    return  # Do not return to user

# Step 4: All checks passed
print(f"Safe response: {llm_response}")

Example 2: With OpenAI ​

python
from elsai_guardrails.guardrails import GuardrailSystem
from openai import OpenAI

# Initialize guardrail and LLM
guardrail = GuardrailSystem.from_config("config.yml")
client = OpenAI(api_key="your-api-key")

user_input = "Explain quantum computing"

# Step 1: Check input
input_result = guardrail.check_input(user_input)
if not input_result.passed:
    print(f"Input blocked: {input_result.message}")
    return

# Step 2: Call OpenAI
try:
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": user_input}]
    )
    llm_response = response.choices[0].message.content
except Exception as e:
    print(f"LLM error: {str(e)}")
    return

# Step 3: Check output
output_result = guardrail.check_output(llm_response)
if not output_result.passed:
    print(f"Output blocked: {output_result.message}")
    return

# Step 4: Success
print(llm_response)

Example 3: Complete Workflow Function ​

python
from elsai_guardrails.guardrails import GuardrailSystem

guardrail = GuardrailSystem.from_config("config.yml")

def process_user_query(user_input: str) -> dict:
    """
    Complete workflow: input check -> LLM call -> output check
    
    Returns:
        dict with 'success', 'response', 'error', and 'blocked_at' keys
    """
    result = {
        'success': False,
        'response': None,
        'error': None,
        'blocked_at': None
    }
    
    # Step 1: Check input
    input_result = guardrail.check_input(user_input)
    if not input_result.passed:
        result['error'] = f"Input blocked: {input_result.message}"
        result['blocked_at'] = 'input'
        return result
    
    # Step 2: Call LLM
    try:
        # Your LLM call here
        llm_response = f"Response to: {user_input}"
    except Exception as e:
        result['error'] = f"LLM error: {str(e)}"
        result['blocked_at'] = 'llm_call'
        return result
    
    # Step 3: Check output
    output_result = guardrail.check_output(llm_response)
    if not output_result.passed:
        result['error'] = f"Output blocked: {output_result.message}"
        result['blocked_at'] = 'output'
        return result
    
    # Step 4: Success
    result['success'] = True
    result['response'] = llm_response
    return result

# Usage
result = process_user_query("What is AI?")
if result['success']:
    print(f"Response: {result['response']}")
else:
    print(f"Blocked at {result['blocked_at']}: {result['error']}")

Example 4: Getting Detailed Results ​

python
from elsai_guardrails.guardrails import GuardrailSystem

guardrail = GuardrailSystem.from_config("config.yml")

user_input = "What is artificial intelligence?"
input_result = guardrail.check_input(user_input)

print(f"=== Input Check Details ===")
print(f"Passed: {input_result.passed}")
print(f"Message: {input_result.message}")
print(f"\nToxicity:")
print(f"  Class: {input_result.toxicity.get('label', 'N/A')}")
print(f"  Confidence: {input_result.toxicity.get('confidence', 'N/A')}")
print(f"\nSensitive Data:")
print(f"  Labels: {input_result.sensitive_data.get('predicted_labels', [])}")
print(f"\nContent Class: {input_result.semantic_class}")

if input_result.passed:
    print("\nInput is safe to send to LLM")
else:
    print("\nInput should be blocked")

Example 5: Handling Blocked Input ​

python
from elsai_guardrails.guardrails import GuardrailSystem

guardrail = GuardrailSystem.from_config("config.yml")

# Input with sensitive data
user_input = "My email is user@example.com and my phone is 555-1234"
input_result = guardrail.check_input(user_input)

if not input_result.passed:
    print(f"Input blocked: {input_result.message}")
    
    # Check what was detected
    if input_result.sensitive_data.get('predicted_labels'):
        labels = input_result.sensitive_data['predicted_labels']
        if labels != ["No sensitive data detected"]:
            print(f"Sensitive data detected: {labels}")
            print("Please ask user to remove sensitive information")
    
    if input_result.semantic_class:
        print(f"Content issue: {input_result.semantic_class}")
    
    # Do not call LLM
    return

Example 6: Handling Blocked Output ​

python
from elsai_guardrails.guardrails import GuardrailSystem

guardrail = GuardrailSystem.from_config("config.yml")

# Simulate LLM response that might be blocked
llm_response = "Here is some information: user@example.com and 555-1234"
output_result = guardrail.check_output(llm_response)

if not output_result.passed:
    print(f"Output blocked: {output_result.message}")
    
    # Check what was detected
    if output_result.sensitive_data.get('predicted_labels'):
        labels = output_result.sensitive_data['predicted_labels']
        if labels != ["No sensitive data detected"]:
            print(f"Sensitive data in output: {labels}")
    
    # Options:
    # 1. Do not return to user
    # 2. Sanitize the response
    # 3. Ask LLM to regenerate without sensitive data
    return

# Output passed, safe to return
print(llm_response)

Example 7: Custom Configuration ​

python
from elsai_guardrails.guardrails import GuardrailSystem, GuardrailConfig

# Create custom guardrail config
custom_config = GuardrailConfig(
    check_toxicity=True,
    check_sensitive_data=True,
    check_semantic=True,
    toxicity_threshold=0.5,  # Lower threshold = more strict
    block_toxic=True,
    block_sensitive_data=True
)

# Create guardrail system with custom config
guardrail = GuardrailSystem(
    config=custom_config,
    input_checks=True,
    output_checks=True
)

# Use as before
input_result = guardrail.check_input("test input")

Benefits of Separate Checks ​

  1. Flexibility: Use any LLM provider or custom implementation
  2. Control: Full control over LLM invocation and error handling
  3. Customization: Different handling for input vs output failures
  4. Integration: Easy to integrate with existing LLM code
  5. Debugging: Clear separation of concerns for easier debugging

When to Use Separate Checks ​

Use separate checks when:

  • You have existing LLM code you want to add guardrails to
  • You need custom LLM invocation logic
  • You want different error handling for input vs output
  • You're using an LLM provider not directly supported
  • You need fine-grained control over the process

When to Use LLMRails ​

Use LLMRails when:

  • You want automatic end-to-end guardrails
  • You're using a supported LLM provider
  • You want the simplest integration
  • You don't need custom LLM logic

Next Steps ​

Copyright © 2026 elsai foundry.