Skip to main content

Overview

Guardrails in OrbitAI provide a safety and validation framework that ensures agents operate within defined boundaries. They act as automated checkpoints that validate inputs, filter outputs, enforce resource limits, and maintain compliance with content policies and regulations.

Input Validation

Validate and sanitize inputs before processing

Output Filtering

Filter harmful, sensitive, or inappropriate content

Content Safety

Block harmful, offensive, or inappropriate content

Compliance

Enforce regulatory requirements and policies

Resource Control

Limit token usage, rate limits, and resource consumption

Customizable

Create custom guardrails for specific requirements

Key Capabilities

Guardrails are automatically enforced during task execution. All agent outputs pass through guardrail validation before task completion, ensuring consistent safety without manual intervention.
Combine multiple guardrails for comprehensive protection. Stack content filtering, PII detection, token limits, and rate limiting to create defense-in-depth security.
Configure validation strictness from lenient (for development) to strict (for production). Partial approvals allow iterative refinement of agent outputs.
Implement domain-specific validation logic with custom guardrails. Extend the OrbitGuardrail protocol to enforce business rules, compliance requirements, or quality standards.

Guardrails Architecture

Guardrails Execution Pipeline
    ├── 1. Task Initialization
    │   ├── Input Validation
    │   ├── Parameter Sanitization
    │   └── Pre-Execution Checks

    ├── 2. Agent Execution
    │   ├── Resource Monitoring
    │   ├── Rate Limit Tracking
    │   └── Progress Validation

    ├── 3. Output Generation
    │   ├── Content Generation
    │   └── Initial Output

    ├── 4. Guardrail Validation ← All outputs validated
    │   ├── Content Safety Checks
    │   ├── PII Detection
    │   ├── Token Limit Enforcement
    │   ├── Custom Validations
    │   └── Compliance Checks

    ├── 5. Validation Result
    │   ├── Approved → Task Complete
    │   ├── Partially Approved → Refinement
    │   ├── Needs Revision → Retry
    │   └── Failed → Error

    └── 6. Task Completion
        └── Return Validated Output

Built-in Guardrails

OrbitAI provides several built-in guardrails for common safety and compliance requirements:

Content Safety Guardrails

  • No Harmful Content
  • Content Filter
  • No PII
Guardrail: NoHarmfulContentGuardrailPrevents generation of harmful, offensive, or dangerous content.Configuration:
guardrails: [.noHarmfulContent]
What it blocks:
  • Violence and graphic content
  • Hate speech and discrimination
  • Self-harm and dangerous activities
  • Illegal activities
  • Adult/NSFW content
  • Harassment and bullying
Example:
let contentTask = ORTask(
    description: "Generate blog post about healthy living",
    expectedOutput: "Informative health blog post",
    guardrails: [.noHarmfulContent]
)
// Blocks: Dangerous health advice, extreme diets, etc.
Use cases:
  • User-facing content generation
  • Educational content
  • Public communications
  • Customer interactions

Resource Control Guardrails

  • Token Limit
  • Rate Limit
  • Resource Limit
Guardrail: TokenLimitGuardrailEnforces maximum token limits for generated content.Configuration:
let tokenGuardrail = TokenLimitGuardrail(
    maxTokens: 8000,
    model: "gpt-4o"
)

let task = ORTask(
    description: "Generate comprehensive report",
    expectedOutput: "Detailed analysis report",
    guardrails: [tokenGuardrail]
)
Parameters:
  • maxTokens: Maximum token count allowed
  • model: Model name for accurate token counting
  • action: What to do when exceeded (truncate, fail, warn)
Use cases:
  • Prevent excessive LLM costs
  • Ensure outputs fit within constraints
  • Control response sizes
  • Manage context window usage
Example with truncation:
let limitedGuardrail = TokenLimitGuardrail(
    maxTokens: 2000,
    model: "gpt-4o",
    action: .truncate,  // Auto-truncate to limit
    preservePriority: .beginning  // or .ending
)

Input Validation

Guardrails validate inputs before processing to prevent injection attacks, malformed data, and security issues.

Input Validation Guardrails

1

Parameter Validation

Validate task and agent parameters:
final class ParameterValidationGuardrail: OrbitGuardrail {
    func check(context: GuardrailContext) async throws -> GuardrailResult {
        // Validate required parameters
        guard let input = context.inputs["query"],
              !input.isEmpty else {
            return .needsRevision(
                feedback: "Query parameter is required and cannot be empty"
            )
        }

        // Validate parameter format
        if input.count < 2 {
            return .needsRevision(
                feedback: "Query must be at least 2 characters"
            )
        }

        if input.count > 500 {
            return .needsRevision(
                feedback: "Query cannot exceed 500 characters"
            )
        }

        return .approved
    }
}

// Usage
let task = ORTask(
    description: "Process user query",
    expectedOutput: "Query results",
    guardrails: [ParameterValidationGuardrail()]
)
2

Input Sanitization

Sanitize user inputs to prevent injection:
final class InputSanitizationGuardrail: OrbitGuardrail {
    private let dangerousPatterns: [String] = [
        "<script",
        "javascript:",
        "onerror=",
        "onclick=",
        "<?php",
        "${",  // Template injection
        "{{",  // Template injection
    ]

    func check(context: GuardrailContext) async throws -> GuardrailResult {
        guard let input = context.inputs["user_input"] else {
            return .approved
        }

        // Check for injection patterns
        let lowercased = input.lowercased()
        for pattern in dangerousPatterns {
            if lowercased.contains(pattern) {
                return .needsRevision(
                    feedback: "Input contains potentially dangerous pattern: \(pattern)"
                )
            }
        }

        // Check for SQL injection
        let sqlPatterns = ["';", "--", "/*", "*/", "xp_", "sp_", "exec ", "execute "]
        for pattern in sqlPatterns {
            if lowercased.contains(pattern) {
                return .needsRevision(
                    feedback: "Input contains SQL injection pattern"
                )
            }
        }

        return .approved
    }
}
3

Schema Validation

Validate structured inputs:
final class SchemaValidationGuardrail: OrbitGuardrail {
    let requiredFields: [String]
    let schema: JSONSchema

    init(schema: JSONSchema, requiredFields: [String]) {
        self.schema = schema
        self.requiredFields = requiredFields
    }

    func check(context: GuardrailContext) async throws -> GuardrailResult {
        guard let data = context.inputs["data"] else {
            return .needsRevision(feedback: "Missing data field")
        }

        // Parse JSON
        guard let jsonData = data.data(using: .utf8),
              let json = try? JSONSerialization.jsonObject(with: jsonData) as? [String: Any] else {
            return .needsRevision(feedback: "Invalid JSON format")
        }

        // Validate required fields
        for field in requiredFields {
            if json[field] == nil {
                return .needsRevision(
                    feedback: "Missing required field: \(field)"
                )
            }
        }

        // Validate against schema
        let validationErrors = validateAgainstSchema(json, schema: schema)
        if !validationErrors.isEmpty {
            return .needsRevision(
                feedback: "Schema validation failed: \(validationErrors.joined(separator: ", "))"
            )
        }

        return .approved
    }

    private func validateAgainstSchema(
        _ data: [String: Any],
        schema: JSONSchema
    ) -> [String] {
        // Schema validation logic
        var errors: [String] = []
        // ... implementation
        return errors
    }
}
4

File Upload Validation

Validate file uploads:
final class FileUploadGuardrail: OrbitGuardrail {
    let allowedExtensions: Set<String>
    let maxSizeMB: Int
    let scanForMalware: Bool

    init(
        allowedExtensions: Set<String>,
        maxSizeMB: Int = 10,
        scanForMalware: Bool = true
    ) {
        self.allowedExtensions = allowedExtensions
        self.maxSizeMB = maxSizeMB
        self.scanForMalware = scanForMalware
    }

    func check(context: GuardrailContext) async throws -> GuardrailResult {
        guard let filePath = context.inputs["file_path"] else {
            return .approved
        }

        // Check file exists
        guard FileManager.default.fileExists(atPath: filePath) else {
            return .needsRevision(feedback: "File not found")
        }

        // Check extension
        let ext = (filePath as NSString).pathExtension.lowercased()
        guard allowedExtensions.contains(ext) else {
            return .needsRevision(
                feedback: "File type .\(ext) not allowed. Allowed: \(allowedExtensions)"
            )
        }

        // Check size
        let attrs = try FileManager.default.attributesOfItem(atPath: filePath)
        let sizeMB = (attrs[.size] as? Int64 ?? 0) / 1024 / 1024

        if sizeMB > maxSizeMB {
            return .needsRevision(
                feedback: "File size \(sizeMB)MB exceeds limit of \(maxSizeMB)MB"
            )
        }

        // Scan for malware (if enabled)
        if scanForMalware {
            let isSafe = try await scanFile(filePath)
            if !isSafe {
                return .needsRevision(
                    feedback: "File failed security scan"
                )
            }
        }

        return .approved
    }

    private func scanFile(_ path: String) async throws -> Bool {
        // Malware scanning logic
        return true
    }
}

Input Validation Best Practices

Validate Early

Validate inputs before they reach agents:
// Apply at task level
let task = ORTask(
    description: "Process input",
    guardrails: [
        InputSanitizationGuardrail(),
        ParameterValidationGuardrail()
    ]
)

Whitelist Over Blacklist

Define allowed inputs rather than blocked ones:
// Good: Whitelist allowed characters
let allowedChars = CharacterSet.alphanumerics
    .union(.whitespaces)
    .union(CharacterSet(charactersIn: ".,!?"))

// Bad: Blacklist dangerous characters
let blockedChars = CharacterSet(
    charactersIn: "<>\"';"
)

Provide Clear Feedback

Help users understand validation failures:
return .needsRevision(
    feedback: """
    Email format invalid.
    Expected: [email protected]
    Received: \(input)
    """
)

Layer Validation

Use multiple validation layers:
guardrails: [
    ParameterValidationGuardrail(),  // 1. Structure
    InputSanitizationGuardrail(),    // 2. Security
    SchemaValidationGuardrail(),     // 3. Format
    BusinessRuleGuardrail()          // 4. Logic
]

Output Validation

Output guardrails filter and validate agent-generated content before returning results.

Output Validation Strictness

Configure how strictly outputs are validated:
public enum ValidationStrictness: String, Codable {
    case lenient   // Partial approvals accepted
    case standard  // Balanced validation (default)
    case strict    // Even partial approvals require revision
}
  • Lenient
  • Standard
  • Strict
Use case: Development, testing, experimentation
let task = ORTask(
    description: "Generate draft content",
    expectedOutput: "Draft document",
    validationStrictness: .lenient,
    guardrails: [.noHarmfulContent]
)
Behavior:
  • Partial approvals are accepted
  • Warnings don’t block output
  • Faster iteration
  • More permissive filtering
When to use:
  • Prototyping
  • Internal tools
  • Development environments
  • Creative exploration

Validation Results

public enum TaskValidationResult {
    case approved
    case partiallyApproved(feedback: String)
    case needsRevision(feedback: String)
    case validationFailed
}
Output passes all guardrails.
func check(context: GuardrailContext) async throws -> GuardrailResult {
    // All checks passed
    return .approved
}
What happens:
  • Task completes successfully
  • Output returned to user
  • No retries needed
Output is acceptable but has minor issues.
func check(context: GuardrailContext) async throws -> GuardrailResult {
    if hasMinorIssues {
        return .partiallyApproved(
            feedback: "Output is acceptable but could be improved: \(issues)"
        )
    }
    return .approved
}
What happens:
  • Lenient/Standard: Output accepted with feedback
  • Strict: Retry required
  • Feedback provided for improvement
Output has issues that must be fixed.
func check(context: GuardrailContext) async throws -> GuardrailResult {
    if hasViolations {
        return .needsRevision(
            feedback: "Output contains prohibited content: \(violations)"
        )
    }
    return .approved
}
What happens:
  • Task retries if retries available
  • Feedback sent to agent for revision
  • Previous output discarded
Output cannot be validated (technical error).
func check(context: GuardrailContext) async throws -> GuardrailResult {
    guard let output = context.output else {
        return .validationFailed
    }

    do {
        try await performValidation(output)
        return .approved
    } catch {
        return .validationFailed
    }
}
What happens:
  • Task fails immediately
  • Error logged
  • No retries (technical failure)

Safety and Compliance

Content Safety

Implement comprehensive content safety with multiple layers:
import OrbitAI

// Content safety configuration
let contentSafetyAgent = Agent(
    role: "Content Moderator",
    purpose: "Generate safe, appropriate content",
    context: """
    Expert content creator who:
    - Avoids harmful, offensive, or inappropriate content
    - Respects cultural sensitivities
    - Maintains professional tone
    - Follows community guidelines
    """,
    guardrails: [
        .noHarmfulContent,
        .contentFilter,
        CustomSensitivityGuardrail(level: .high)
    ]
)

// Custom sensitivity guardrail
final class CustomSensitivityGuardrail: OrbitGuardrail {
    enum SensitivityLevel {
        case low, medium, high
    }

    let level: SensitivityLevel

    init(level: SensitivityLevel) {
        self.level = level
    }

    func check(context: GuardrailContext) async throws -> GuardrailResult {
        guard let output = context.output else {
            return .validationFailed
        }

        // Check sentiment
        let sentiment = analyzeSentiment(output)

        switch level {
        case .high:
            if sentiment.negativity > 0.2 || sentiment.controversy > 0.1 {
                return .needsRevision(
                    feedback: "Content tone is too negative or controversial"
                )
            }

        case .medium:
            if sentiment.negativity > 0.4 || sentiment.controversy > 0.3 {
                return .partiallyApproved(
                    feedback: "Consider adjusting tone for broader audience"
                )
            }

        case .low:
            if sentiment.negativity > 0.6 {
                return .partiallyApproved(
                    feedback: "Content may benefit from more positive framing"
                )
            }
        }

        return .approved
    }

    private func analyzeSentiment(_ text: String) -> (negativity: Double, controversy: Double) {
        // Sentiment analysis implementation
        return (0.0, 0.0)
    }
}

Privacy Compliance

Ensure GDPR, CCPA, and privacy regulation compliance:
final class PrivacyComplianceGuardrail: OrbitGuardrail {
    let regulations: Set<PrivacyRegulation>

    enum PrivacyRegulation {
        case gdpr      // EU General Data Protection Regulation
        case ccpa      // California Consumer Privacy Act
        case hipaa     // Health Insurance Portability and Accountability Act
        case coppa     // Children's Online Privacy Protection Act
    }

    init(regulations: Set<PrivacyRegulation>) {
        self.regulations = regulations
    }

    func check(context: GuardrailContext) async throws -> GuardrailResult {
        guard let output = context.output else {
            return .validationFailed
        }

        var violations: [String] = []

        // GDPR compliance
        if regulations.contains(.gdpr) {
            let gdprIssues = checkGDPRCompliance(output)
            violations.append(contentsOf: gdprIssues)
        }

        // HIPAA compliance
        if regulations.contains(.hipaa) {
            let hipaaIssues = checkHIPAACompliance(output)
            violations.append(contentsOf: hipaaIssues)
        }

        // COPPA compliance
        if regulations.contains(.coppa) {
            let coppaIssues = checkCOPPACompliance(output)
            violations.append(contentsOf: coppaIssues)
        }

        if !violations.isEmpty {
            return .needsRevision(
                feedback: "Privacy violations detected: \(violations.joined(separator: "; "))"
            )
        }

        return .approved
    }

    private func checkGDPRCompliance(_ output: String) -> [String] {
        var issues: [String] = []

        // Check for PII
        if detectsPII(output) {
            issues.append("Contains PII without consent")
        }

        // Check for data minimization
        if containsExcessiveData(output) {
            issues.append("Violates data minimization principle")
        }

        // Check for right to erasure
        if containsUndeletableReferences(output) {
            issues.append("Contains data that cannot be erased")
        }

        return issues
    }

    private func checkHIPAACompliance(_ output: String) -> [String] {
        var issues: [String] = []

        // Protected Health Information (PHI) detection
        let phiPatterns = [
            "medical record",
            "diagnosis:",
            "prescription:",
            "treatment plan",
            "lab results"
        ]

        for pattern in phiPatterns {
            if output.lowercased().contains(pattern) {
                // Check if properly encrypted/secured
                if !isProperlySecured(output, pattern: pattern) {
                    issues.append("Unsecured PHI: \(pattern)")
                }
            }
        }

        return issues
    }

    private func checkCOPPACompliance(_ output: String) -> [String] {
        var issues: [String] = []

        // Age-inappropriate content
        if containsAgeInappropriateContent(output) {
            issues.append("Contains content inappropriate for children")
        }

        // Personal info collection
        if requestsPersonalInfo(output) {
            issues.append("Requests personal information from minors")
        }

        return issues
    }

    private func detectsPII(_ text: String) -> Bool {
        // PII detection logic
        return false
    }

    private func containsExcessiveData(_ text: String) -> Bool {
        // Data minimization check
        return false
    }

    private func containsUndeletableReferences(_ text: String) -> Bool {
        // Erasure compliance check
        return false
    }

    private func isProperlySecured(_ text: String, pattern: String) -> Bool {
        // Security check for PHI
        return true
    }

    private func containsAgeInappropriateContent(_ text: String) -> Bool {
        // Age appropriateness check
        return false
    }

    private func requestsPersonalInfo(_ text: String) -> Bool {
        // Personal info request detection
        return false
    }
}

// Usage
let healthcareAgent = Agent(
    role: "Medical Information Assistant",
    purpose: "Provide health information",
    context: "HIPAA-compliant medical assistant",
    guardrails: [
        .noPII,
        PrivacyComplianceGuardrail(regulations: [.hipaa, .gdpr])
    ]
)

Industry-Specific Compliance

  • Financial Services
  • Healthcare
  • Education
Regulations: PCI-DSS, SOX, GLBA
final class FinancialComplianceGuardrail: OrbitGuardrail {
    func check(context: GuardrailContext) async throws -> GuardrailResult {
        guard let output = context.output else {
            return .validationFailed
        }

        var violations: [String] = []

        // PCI-DSS: No credit card data
        if detectsCreditCardData(output) {
            violations.append("Credit card data detected (PCI-DSS violation)")
        }

        // SOX: Financial data accuracy
        if containsFinancialData(output) && !isAuditable(output) {
            violations.append("Financial data not auditable (SOX compliance)")
        }

        // GLBA: Customer financial information
        if containsCustomerFinancialInfo(output) && !isEncrypted(output) {
            violations.append("Unencrypted customer financial info (GLBA)")
        }

        // Investment advice disclaimer
        if appearsToBeInvestmentAdvice(output) && !hasDisclaimer(output) {
            violations.append("Investment advice missing required disclaimers")
        }

        if !violations.isEmpty {
            return .needsRevision(
                feedback: violations.joined(separator: "\n")
            )
        }

        return .approved
    }

    private func detectsCreditCardData(_ text: String) -> Bool {
        // Credit card pattern detection
        let ccPattern = #"\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}"#
        return text.range(of: ccPattern, options: .regularExpression) != nil
    }

    private func containsFinancialData(_ text: String) -> Bool {
        let keywords = ["revenue", "profit", "loss", "earnings", "balance sheet"]
        return keywords.contains { text.lowercased().contains($0) }
    }

    private func isAuditable(_ text: String) -> Bool {
        // Check for audit trail metadata
        return true
    }

    private func containsCustomerFinancialInfo(_ text: String) -> Bool {
        let patterns = ["account balance", "transaction history", "credit score"]
        return patterns.contains { text.lowercased().contains($0) }
    }

    private func isEncrypted(_ text: String) -> Bool {
        // Check encryption status
        return true
    }

    private func appearsToBeInvestmentAdvice(_ text: String) -> Bool {
        let advisoryKeywords = ["should invest", "recommend buying", "stock tip"]
        return advisoryKeywords.contains { text.lowercased().contains($0) }
    }

    private func hasDisclaimer(_ text: String) -> Bool {
        let disclaimers = ["not financial advice", "consult a financial advisor"]
        return disclaimers.contains { text.lowercased().contains($0) }
    }
}

Custom Guardrails

Create custom guardrails for domain-specific requirements:

OrbitGuardrail Protocol

public protocol OrbitGuardrail {
    func check(context: GuardrailContext) async throws -> GuardrailResult
}

public struct GuardrailContext {
    public let inputs: [String: String]
    public let output: String?
    public let metadata: [String: String]
    public let agent: Agent?
    public let task: ORTask?
}

public enum GuardrailResult {
    case approved
    case partiallyApproved(feedback: String)
    case needsRevision(feedback: String)
    case validationFailed
}

Custom Guardrail Examples

  • Business Rules
  • Quality Standards
  • Brand Guidelines
Enforce business logic and domain rules:
final class BusinessRulesGuardrail: OrbitGuardrail {
    let rules: [BusinessRule]

    struct BusinessRule {
        let name: String
        let condition: (String) -> Bool
        let errorMessage: String
    }

    init(rules: [BusinessRule]) {
        self.rules = rules
    }

    func check(context: GuardrailContext) async throws -> GuardrailResult {
        guard let output = context.output else {
            return .validationFailed
        }

        var violations: [String] = []

        for rule in rules {
            if !rule.condition(output) {
                violations.append("\(rule.name): \(rule.errorMessage)")
            }
        }

        if !violations.isEmpty {
            return .needsRevision(
                feedback: "Business rule violations:\n" + violations.joined(separator: "\n")
            )
        }

        return .approved
    }
}

// Usage: E-commerce rules
let ecommerceRules = BusinessRulesGuardrail(rules: [
    BusinessRule(
        name: "Price Validity",
        condition: { output in
            // Check prices are in valid range
            let pricePattern = #"\$(\d+\.?\d*)"#
            if let regex = try? NSRegularExpression(pattern: pricePattern) {
                let matches = regex.matches(
                    in: output,
                    range: NSRange(output.startIndex..., in: output)
                )

                for match in matches {
                    if let range = Range(match.range(at: 1), in: output) {
                        let priceStr = String(output[range])
                        if let price = Double(priceStr), price < 0 || price > 999999 {
                            return false  // Invalid price
                        }
                    }
                }
            }
            return true
        },
        errorMessage: "Prices must be between $0 and $999,999"
    ),

    BusinessRule(
        name: "Discount Limits",
        condition: { output in
            // Check discounts don't exceed 70%
            let discountPattern = #"(\d+)%\s+off"#
            if let regex = try? NSRegularExpression(pattern: discountPattern, options: .caseInsensitive) {
                let matches = regex.matches(
                    in: output,
                    range: NSRange(output.startIndex..., in: output)
                )

                for match in matches {
                    if let range = Range(match.range(at: 1), in: output) {
                        let discountStr = String(output[range])
                        if let discount = Int(discountStr), discount > 70 {
                            return false  // Excessive discount
                        }
                    }
                }
            }
            return true
        },
        errorMessage: "Discounts cannot exceed 70%"
    ),

    BusinessRule(
        name: "Stock Availability",
        condition: { output in
            // Don't promise availability without checking
            let promisePatterns = [
                "in stock",
                "available now",
                "ships immediately"
            ]

            for pattern in promisePatterns {
                if output.lowercased().contains(pattern) {
                    // Check if includes disclaimer
                    if !output.lowercased().contains("while supplies last") &&
                       !output.lowercased().contains("subject to availability") {
                        return false
                    }
                }
            }
            return true
        },
        errorMessage: "Availability claims must include disclaimers"
    )
])

let productAgent = Agent(
    role: "Product Description Writer",
    purpose: "Create product descriptions",
    context: "E-commerce content expert",
    guardrails: [ecommerceRules]
)

Best Practices

Guardrail Configuration

Layer Guardrails

Use multiple guardrails for defense-in-depth:
let secureTask = ORTask(
    description: "Process customer data",
    expectedOutput: "Customer report",
    guardrails: [
        // Layer 1: Input validation
        InputSanitizationGuardrail(),

        // Layer 2: Security
        .noPII,
        .noHarmfulContent,

        // Layer 3: Compliance
        PrivacyComplianceGuardrail(
            regulations: [.gdpr, .ccpa]
        ),

        // Layer 4: Quality
        QualityStandardsGuardrail(),

        // Layer 5: Business rules
        BusinessRulesGuardrail(rules: rules)
    ]
)

Environment-Specific

Adjust strictness by environment:
#if DEBUG
let strictness: ValidationStrictness = .lenient
let guardrails: [any OrbitGuardrail] = [
    .noHarmfulContent
]
#else
let strictness: ValidationStrictness = .strict
let guardrails: [any OrbitGuardrail] = [
    .noHarmfulContent,
    .noPII,
    .contentFilter,
    ComplianceGuardrail()
]
#endif

let task = ORTask(
    description: "Generate content",
    expectedOutput: "Content output",
    validationStrictness: strictness,
    guardrails: guardrails
)

Monitor Violations

Track guardrail violations:
final class GuardrailMonitor {
    static let shared = GuardrailMonitor()

    private var violations: [ViolationRecord] = []

    struct ViolationRecord {
        let timestamp: Date
        let guardrail: String
        let task: String
        let feedback: String
    }

    func recordViolation(
        guardrail: String,
        task: String,
        feedback: String
    ) {
        let record = ViolationRecord(
            timestamp: Date(),
            guardrail: guardrail,
            task: task,
            feedback: feedback
        )

        violations.append(record)

        // Alert if too many violations
        if recentViolationCount() > 10 {
            alertSecurityTeam()
        }
    }

    private func recentViolationCount() -> Int {
        let hourAgo = Date().addingTimeInterval(-3600)
        return violations.filter { $0.timestamp > hourAgo }.count
    }

    private func alertSecurityTeam() {
        // Send alert
    }
}

Test Guardrails

Unit test custom guardrails:
import XCTest
@testable import MyApp

final class GuardrailTests: XCTestCase {
    func testNoPIIGuardrail() async throws {
        let guardrail = NoPIIGuardrail()

        // Test: Should block email
        let emailContext = GuardrailContext(
            inputs: [:],
            output: "Contact me at [email protected]",
            metadata: [:],
            agent: nil,
            task: nil
        )

        let result = try await guardrail.check(
            context: emailContext
        )

        XCTAssertEqual(
            result,
            .needsRevision(
                feedback: "Contains PII: email address"
            )
        )

        // Test: Should approve clean content
        let cleanContext = GuardrailContext(
            inputs: [:],
            output: "This is clean content",
            metadata: [:],
            agent: nil,
            task: nil
        )

        let cleanResult = try await guardrail.check(
            context: cleanContext
        )

        XCTAssertEqual(cleanResult, .approved)
    }
}

Performance Optimization

Cache expensive validation operations:
final class CachedGuardrail: OrbitGuardrail {
    private let underlying: OrbitGuardrail
    private var cache: [String: GuardrailResult] = [:]

    init(wrapping guardrail: OrbitGuardrail) {
        self.underlying = guardrail
    }

    func check(context: GuardrailContext) async throws -> GuardrailResult {
        // Create cache key
        let key = cacheKey(for: context)

        // Check cache
        if let cached = cache[key] {
            return cached
        }

        // Execute validation
        let result = try await underlying.check(context: context)

        // Cache result
        cache[key] = result

        return result
    }

    private func cacheKey(for context: GuardrailContext) -> String {
        // Create unique key from context
        return "\(context.output?.hashValue ?? 0)"
    }
}
Run independent guardrails in parallel:
func validateInParallel(
    context: GuardrailContext,
    guardrails: [any OrbitGuardrail]
) async throws -> GuardrailResult {
    try await withThrowingTaskGroup(of: GuardrailResult.self) { group in
        // Add all guardrail checks
        for guardrail in guardrails {
            group.addTask {
                try await guardrail.check(context: context)
            }
        }

        // Collect results
        var results: [GuardrailResult] = []
        for try await result in group {
            results.append(result)
        }

        // Aggregate results
        return aggregateResults(results)
    }
}

func aggregateResults(_ results: [GuardrailResult]) -> GuardrailResult {
    // If any failed, return first failure
    for result in results {
        if case .needsRevision(let feedback) = result {
            return .needsRevision(feedback: feedback)
        }
    }

    // If any partial, return first partial
    for result in results {
        if case .partiallyApproved(let feedback) = result {
            return .partiallyApproved(feedback: feedback)
        }
    }

    // All approved
    return .approved
}
Stop on first failure for performance:
func validateWithShortCircuit(
    context: GuardrailContext,
    guardrails: [any OrbitGuardrail]
) async throws -> GuardrailResult {
    for guardrail in guardrails {
        let result = try await guardrail.check(context: context)

        // Stop on first failure
        switch result {
        case .needsRevision, .validationFailed:
            return result
        case .partiallyApproved, .approved:
            continue
        }
    }

    return .approved
}

Security Best Practices

Critical: Guardrails are your last line of defense. Always enable guardrails in production environments.
// Enable guardrails in environment
// .env file
ORBIT_ENABLE_GUARDRAILS=true

// Verify guardrails are enabled
guard ProcessInfo.processInfo.environment["ORBIT_ENABLE_GUARDRAILS"] == "true" else {
    fatalError("Guardrails must be enabled in production")
}

// Use strict validation
let productionTask = ORTask(
    description: "Production task",
    expectedOutput: "Production output",
    validationStrictness: .strict,  // Always strict in production
    guardrails: [
        .noHarmfulContent,
        .noPII,
        .contentFilter,
        ComplianceGuardrail()
    ]
)

// Log all guardrail violations
extension OrbitGuardrail {
    func checkWithLogging(
        context: GuardrailContext
    ) async throws -> GuardrailResult {
        let result = try await check(context: context)

        // Log violations
        switch result {
        case .needsRevision(let feedback),
             .partiallyApproved(let feedback):
            logger.warning("Guardrail violation: \(feedback)")
            GuardrailMonitor.shared.recordViolation(
                guardrail: String(describing: type(of: self)),
                task: context.task?.description ?? "Unknown",
                feedback: feedback
            )
        case .validationFailed:
            logger.error("Guardrail validation failed")
        case .approved:
            break
        }

        return result
    }
}

Troubleshooting

Common Issues

Symptom: Tasks repeatedly fail guardrail validation.Causes:
  • Overly strict guardrails
  • Poorly configured thresholds
  • Agent generating inappropriate content
  • Conflicting guardrails
Diagnosis:
// Enable detailed logging
let task = ORTask(
    description: "Test task",
    expectedOutput: "Test output",
    guardrails: [
        VerboseGuardrail(wrapping: .noHarmfulContent)
    ]
)

final class VerboseGuardrail: OrbitGuardrail {
    let wrapped: any OrbitGuardrail

    init(wrapping guardrail: any OrbitGuardrail) {
        self.wrapped = guardrail
    }

    func check(context: GuardrailContext) async throws -> GuardrailResult {
        print("Checking guardrail: \(type(of: wrapped))")
        print("Output: \(context.output ?? "nil")")

        let result = try await wrapped.check(context: context)

        print("Result: \(result)")

        return result
    }
}
Solutions:
// 1. Adjust strictness for development
let task = ORTask(
    description: "Development task",
    expectedOutput: "Output",
    validationStrictness: .lenient  // Less strict
)

// 2. Increase token limit
let tokenGuardrail = TokenLimitGuardrail(
    maxTokens: 12000,  // Increased from 8000
    model: "gpt-4o"
)

// 3. Improve agent instructions
let agent = Agent(
    role: "Content Writer",
    purpose: "Generate safe, appropriate content",
    context: """
    Important guidelines:
    - Use professional, respectful language
    - Avoid controversial topics
    - Do not include personal information
    - Keep content factual and balanced
    """
)

// 4. Customize guardrail behavior
let customPIIGuardrail = NoPIIGuardrail(
    detectTypes: [.email, .phone],  // Only these types
    action: .redact  // Redact instead of block
)
Symptom: Guardrails block legitimate content.Causes:
  • Overly sensitive detection
  • Pattern matching too broad
  • Context not considered
Solutions:
// 1. Add context-aware validation
final class ContextAwarePIIGuardrail: OrbitGuardrail {
    func check(context: GuardrailContext) async throws -> GuardrailResult {
        guard let output = context.output else {
            return .validationFailed
        }

        // Check context
        if context.metadata["content_type"] == "example" {
            // Allow example emails in documentation
            return .approved
        }

        // Normal PII detection
        return try await detectPII(output)
    }

    private func detectPII(_ text: String) async throws -> GuardrailResult {
        // PII detection logic
        return .approved
    }
}

// 2. Use allowlists
final class AllowlistGuardrail: OrbitGuardrail {
    let allowedPatterns: [String]

    func check(context: GuardrailContext) async throws -> GuardrailResult {
        guard let output = context.output else {
            return .validationFailed
        }

        // Check if matches allowed pattern
        for pattern in allowedPatterns {
            if output.range(of: pattern, options: .regularExpression) != nil {
                return .approved
            }
        }

        // Normal validation
        return .needsRevision(feedback: "Does not match allowed patterns")
    }
}

// 3. Adjust sensitivity
let sensitiveContentFilter = ContentFilterGuardrail(
    sensitivityLevel: .medium  // Reduced from .high
)
Symptom: Guardrail validation is slow.Causes:
  • Too many guardrails
  • Expensive operations (API calls, ML models)
  • Sequential validation
  • No caching
Solutions:
// 1. Run guardrails in parallel
let parallelValidation = ParallelGuardrailValidator(
    guardrails: [
        .noHarmfulContent,
        .noPII,
        .contentFilter
    ]
)

// 2. Implement caching
let cachedGuardrail = CachedGuardrail(
    wrapping: ExpensiveAPIGuardrail()
)

// 3. Use lightweight guardrails for common cases
final class QuickCheckGuardrail: OrbitGuardrail {
    func check(context: GuardrailContext) async throws -> GuardrailResult {
        guard let output = context.output else {
            return .validationFailed
        }

        // Quick regex checks
        if output.isEmpty {
            return .needsRevision(feedback: "Output is empty")
        }

        if output.count > 100000 {
            return .needsRevision(feedback: "Output too long")
        }

        return .approved
    }
}

// 4. Short-circuit on first failure
for guardrail in guardrails {
    let result = try await guardrail.check(context: context)
    if case .needsRevision = result {
        return result  // Stop early
    }
}
Symptom: Same content passes sometimes, fails other times.Causes:
  • Non-deterministic validation
  • Race conditions
  • Stateful guardrails
  • External API inconsistency
Solutions:
// 1. Make guardrails deterministic
final class DeterministicGuardrail: OrbitGuardrail {
    // Don't use random numbers, timestamps, or external APIs

    func check(context: GuardrailContext) async throws -> GuardrailResult {
        guard let output = context.output else {
            return .validationFailed
        }

        // Deterministic validation
        let hash = output.hashValue
        let isValid = hash % 2 == 0  // Always same for same input

        return isValid ? .approved : .needsRevision(feedback: "Validation failed")
    }
}

// 2. Use immutable state
final class StatelessGuardrail: OrbitGuardrail {
    let config: Config  // Immutable configuration

    struct Config {
        let threshold: Double
        let patterns: [String]
    }

    func check(context: GuardrailContext) async throws -> GuardrailResult {
        // No mutable state, same input = same output
        return .approved
    }
}

// 3. Cache external API calls
final class CachedAPIGuardrail: OrbitGuardrail {
    private var cache: [String: GuardrailResult] = [:]

    func check(context: GuardrailContext) async throws -> GuardrailResult {
        guard let output = context.output else {
            return .validationFailed
        }

        // Check cache first
        if let cached = cache[output] {
            return cached
        }

        // Call API
        let result = try await callExternalAPI(output)

        // Cache result
        cache[output] = result

        return result
    }
}

Next Steps


Pro Tip: Start with lenient validation during development to iterate quickly, then gradually increase strictness as you refine your content. Always use strict validation in production environments to ensure safety and compliance.