Skip to Content
EvaluationsGuardrails

Guardrails

Runtime quality gates in workflows that enforce evaluation thresholds and route execution based on quality scores.

What are Guardrails?

Guardrails are workflow nodes that evaluate outputs and route execution along different paths based on quality:

This pattern enables:

  • Quality enforcement - Reject low-quality outputs automatically
  • Retry logic - Regenerate outputs that fail quality checks
  • Conditional routing - Different downstream processing based on quality
  • Graceful degradation - Fallback to human review after max retries

Configuration

Basic Guardrail

{ "type": "guardrail", "id": "quality_check", "config": { "evaluators": [ { "type": "faithfulness", "context": "$.nodes.rag_retrieval.output.chunks", "answer": "$.nodes.llm_generation.output.text", "threshold": 0.8 } ], "paths": [ { "path_id": "pass", "target_node_ids": ["format_output"] }, { "path_id": "fail", "target_node_ids": ["human_review"] } ] } }

Fields:

  • evaluators - Array of evaluation metrics to apply
  • paths - Routing rules for pass/fail outcomes
  • aggregation - How to combine multiple evaluator scores (optional)
  • pass_threshold - Minimum aggregate score to pass (optional)

Multiple Evaluators

Combine multiple quality dimensions:

{ "type": "guardrail", "config": { "evaluators": [ { "type": "faithfulness", "context": "$.nodes.rag_retrieval.output.chunks", "answer": "$.nodes.llm_generation.output.text", "threshold": 0.8, "weight": 0.5 }, { "type": "json_schema", "schema": { "type": "object", "properties": { "answer": {"type": "string"}, "confidence": {"type": "number"} }, "required": ["answer", "confidence"] }, "output": "$.nodes.llm_generation.output.data", "weight": 0.3 }, { "type": "length_check", "text": "$.nodes.llm_generation.output.text", "min_length": 50, "max_length": 500, "unit": "characters", "weight": 0.2 } ], "aggregation": "weighted_average", "pass_threshold": 0.75, "paths": [ {"path_id": "pass", "target_node_ids": ["next_step"]}, {"path_id": "fail", "target_node_ids": ["retry_node"]} ] } }

Score calculation:

  • Faithfulness: 0.9 * 0.5 = 0.45
  • JSON Schema: 1.0 * 0.3 = 0.30
  • Length Check: 1.0 * 0.2 = 0.20
  • Aggregate: 0.95 (passes threshold 0.75)

Aggregation Methods

Weighted Average

Combine scores with configurable weights:

{ "aggregation": "weighted_average", "evaluators": [ {"type": "faithfulness", "threshold": 0.8, "weight": 0.6}, {"type": "relevance", "threshold": 0.7, "weight": 0.4} ], "pass_threshold": 0.75 }

Formula: sum(score_i * weight_i) / sum(weight_i)

Use when: Different quality dimensions have different importance

Minimum

Pass only if all evaluators pass:

{ "aggregation": "min", "evaluators": [ {"type": "faithfulness", "threshold": 0.8}, {"type": "json_schema", "schema": {...}} ] }

Formula: min(score_1, score_2, ...)

Use when: All criteria are mandatory (hard requirements)

Maximum

Pass if any evaluator passes:

{ "aggregation": "max", "evaluators": [ {"type": "exact_match", "reference": "$.expected"}, {"type": "llm_judge", "criteria": "Semantically equivalent?"} ] }

Formula: max(score_1, score_2, ...)

Use when: Multiple acceptable quality definitions (fallback logic)

All

Binary pass if every evaluator passes threshold:

{ "aggregation": "all", "evaluators": [ {"type": "faithfulness", "threshold": 0.8}, {"type": "relevance", "threshold": 0.7}, {"type": "json_schema", "schema": {...}} ] }

Use when: Strict quality requirements (no partial credit)

Any

Binary pass if at least one evaluator passes:

{ "aggregation": "any", "evaluators": [ {"type": "regex_match", "pattern": "^[A-Z]{2}[0-9]+$"}, {"type": "llm_judge", "criteria": "Is format correct?"} ] }

Use when: Flexible acceptance criteria (multiple valid outputs)

Routing Paths

Pass/Fail Routing

Basic binary routing:

{ "paths": [ { "path_id": "pass", "target_node_ids": ["format_output", "log_success"] }, { "path_id": "fail", "target_node_ids": ["retry_generation", "log_failure"] } ] }

Execution:

  • Guardrail evaluates output
  • If aggregate score >= pass_threshold, execute “pass” path nodes
  • If aggregate score < pass_threshold, execute “fail” path nodes

Multi-Path Routing

Route based on score ranges:

{ "paths": [ { "path_id": "high_quality", "condition": "score >= 0.9", "target_node_ids": ["publish_immediately"] }, { "path_id": "medium_quality", "condition": "score >= 0.7 and score < 0.9", "target_node_ids": ["queue_for_review"] }, { "path_id": "low_quality", "condition": "score < 0.7", "target_node_ids": ["regenerate"] } ] }

Use cases:

  • Progressive quality thresholds (auto-publish high quality, review medium)
  • Different processing based on confidence
  • Tiered retry strategies

Evaluator-Specific Routing

Route based on which evaluator failed:

{ "evaluators": [ {"type": "faithfulness", "id": "faith", "threshold": 0.8}, {"type": "json_schema", "id": "schema", "schema": {...}} ], "paths": [ { "path_id": "all_pass", "condition": "faith.pass and schema.pass", "target_node_ids": ["success"] }, { "path_id": "faith_fail", "condition": "not faith.pass", "target_node_ids": ["retry_with_more_context"] }, { "path_id": "schema_fail", "condition": "not schema.pass", "target_node_ids": ["retry_with_schema_prompt"] } ] }

Enables targeted retry strategies based on failure mode.

Retry Patterns

Simple Retry

Retry generation with same prompt:

{ "type": "guardrail", "config": { "evaluators": [...], "max_retries": 3, "paths": [ {"path_id": "pass", "target_node_ids": ["success"]}, {"path_id": "fail", "target_node_ids": ["llm_generation"]} ] } }

Behavior:

  1. LLM generates output
  2. Guardrail evaluates
  3. If fail and retries < max_retries, loop back to LLM
  4. If fail and retries >= max_retries, execute fallback path

Use when: LLM non-determinism may produce better output on retry

Retry with Better Prompt

Enhance prompt based on failure:

{ "paths": [ {"path_id": "pass", "target_node_ids": ["success"]}, { "path_id": "fail", "target_node_ids": [ "enhance_prompt", // Add "Ensure output is faithful to context" "llm_generation_retry" ] } ] }

Prompt enhancement node:

# Add guidance based on failed evaluator if failure_reason == "faithfulness": enhanced_prompt = original_prompt + "\n\nIMPORTANT: Only use information from the provided context. Do not add external knowledge." elif failure_reason == "json_schema": enhanced_prompt = original_prompt + f"\n\nOutput must match this schema: {schema}"

Use when: Specific failure modes have known prompt fixes

Retry with Different Model

Fallback to more capable (or different) model:

{ "paths": [ {"path_id": "pass", "target_node_ids": ["success"]}, { "path_id": "fail", "target_node_ids": ["llm_gpt4_fallback"] } ] }

Node configuration:

  • Initial LLM node: model: gpt-3.5-turbo
  • Fallback LLM node: model: gpt-4

Use when: Quality issues stem from model capability limits

Exponential Backoff

Increase retry delay to avoid rate limits:

{ "retry_strategy": { "type": "exponential_backoff", "initial_delay_ms": 1000, "max_delay_ms": 10000, "multiplier": 2, "max_retries": 5 } }

Delays:

  • Retry 1: 1000ms
  • Retry 2: 2000ms
  • Retry 3: 4000ms
  • Retry 4: 8000ms
  • Retry 5: 10000ms (capped at max_delay_ms)

Use when: API rate limiting may cause transient failures

Human-in-the-Loop Integration

Route low-quality outputs to human review:

{ "type": "guardrail", "config": { "evaluators": [...], "max_retries": 2, "paths": [ {"path_id": "pass", "target_node_ids": ["publish"]}, { "path_id": "fail_retry", "condition": "retries < max_retries", "target_node_ids": ["retry_generation"] }, { "path_id": "fail_final", "condition": "retries >= max_retries", "target_node_ids": ["human_review_node"] } ] } }

Human Review Node:

{ "type": "hitl", "config": { "review_type": "correction", "instructions": "The AI output failed quality checks. Please correct or regenerate.", "fields": [ { "name": "corrected_output", "type": "text", "default": "$.nodes.llm_generation.output.text" } ] } }

See Human-in-the-Loop for detailed HITL configuration.

Creating Guardrail Nodes

Add Guardrail Node

In the workflow canvas:

  1. Open workflow editor
  2. Drag “Guardrail” node from palette
  3. Position between source node (LLM) and downstream nodes

Configure Evaluators

In the node properties panel:

  1. Click “Add Evaluator”
  2. Select evaluator type (faithfulness, relevance, etc.)
  3. Configure JSONPath references to workflow data
  4. Set threshold and weight (if applicable)
  5. Repeat for additional evaluators

Define Routing Paths

In the “Paths” section:

  1. Add “Pass” path
    • Click downstream nodes that should execute on pass
  2. Add “Fail” path
    • Click downstream nodes that should execute on fail
  3. Optionally add conditional paths for multi-tier routing

Set Aggregation

If using multiple evaluators:

  1. Select aggregation method (weighted_average, min, max, all, any)
  2. Set pass_threshold (0.0-1.0)
  3. Adjust evaluator weights if using weighted_average

Test Guardrail

  1. Save workflow
  2. Click “Test Run” with sample input
  3. View guardrail evaluation results in execution logs
  4. Check which path was taken
  5. Iterate configuration based on results

Monitoring Guardrails

Execution Metrics

Track guardrail performance:

MetricDefinitionTarget
Pass RatePercentage of evaluations passing> 80%
Fail RatePercentage failing (requiring retry/review)< 20%
Retry RatePercentage requiring retries< 10%
HITL RatePercentage escalated to human review< 5%
Evaluation LatencyTime spent in guardrail evaluation< 500ms

Failure Analysis

Group failures by:

  • Evaluator - Which evaluator failed most often?
  • Score Range - Distribution of failing scores (just below threshold vs far below)
  • Input Type - Certain inputs fail more than others?
  • Timestamp - Quality degrading over time?

Example dashboard:

Guardrail: RAG Faithfulness Check (Last 7 Days) Pass Rate: ████████████░░░░░░░░ 72% (↓ 5% from last week) Retry Rate: ████░░░░░░░░░░░░░░░░ 18% HITL Rate: ██░░░░░░░░░░░░░░░░░░ 10% Failed Evaluators: - Faithfulness: 65% (score: 0.65 avg) - JSON Schema: 25% - Length Check: 10% Common Failure Patterns: 1. Long context (> 5 chunks) → hallucination (40% of failures) 2. Multi-part questions → incomplete answers (30%) 3. Technical jargon → low relevance scores (15%)

This analysis informs:

  • Threshold adjustment - Lower threshold if failure rate too high
  • Prompt improvements - Address common failure patterns
  • Model changes - Upgrade if capability insufficient

Alerts

Set up alerts for:

Pass rate drops below 70%:

  • Indicates quality degradation
  • Check if upstream data changed or model updated

HITL rate exceeds 10%:

  • Too many manual reviews needed
  • Review guardrail configuration or improve prompts

Evaluation latency > 1000ms:

  • Slow evaluations bottleneck workflow
  • Cache results or use faster evaluators

Best Practices

Evaluator Selection

  • Start with fast evaluators (schema, regex) before slow ones (LLM-based)
  • Use domain-specific evaluators when available
  • Combine reference-free metrics (faithfulness, relevance) with structural checks (schema)
  • Avoid redundant evaluators (high correlation = wasted computation)

Threshold Tuning

  1. Collect baseline data - Run guardrails without enforcement, log scores
  2. Analyze distribution - Plot score histogram
  3. Set threshold at target percentile (e.g., p10 to reject bottom 10%)
  4. Monitor false positives - Review outputs that fail but shouldn’t
  5. Iterate - Adjust threshold based on production metrics

Example: Faithfulness threshold tuning

Score Distribution (1000 samples): 0.9-1.0: ████████████████████ 45% 0.8-0.9: ████████████████ 32% 0.7-0.8: ██████ 12% 0.6-0.7: ████ 8% 0.5-0.6: ██ 3% Recommended threshold: 0.75 (rejects bottom 11%, passes 89%)

Retry Strategy

  • Limit retries - Max 2-3 retries (diminishing returns)
  • Fail fast - Don’t retry if score is extremely low (< 0.3)
  • Vary approach - Don’t retry same prompt/model repeatedly
  • Fallback to HITL - Escalate after max retries

Performance

  • Evaluate selectively - Not every workflow run needs guardrails
  • Sample in production - Evaluate 10-20% of traffic, not 100%
  • Cache results - Identical inputs = identical scores
  • Parallel evaluation - Run independent evaluators concurrently

Documentation

Document guardrail purpose in workflow:

{ "type": "guardrail", "description": "Ensures LLM output is faithful to retrieved context. Retry with better prompt if failed. Escalate to human review after 3 retries.", "config": {...} }

This helps team understand why guardrails fail and how to improve.

Common Patterns

RAG Faithfulness Gate

{ "evaluators": [ { "type": "faithfulness", "context": "$.nodes.rag_retrieval.output.chunks", "answer": "$.nodes.llm_generation.output.text", "threshold": 0.8 } ], "max_retries": 2, "paths": [ {"path_id": "pass", "target_node_ids": ["return_answer"]}, { "path_id": "fail", "target_node_ids": ["retry_with_instruction"], "instruction": "Only use information from provided context. Do not add external knowledge." } ] }

Structured Extraction Validation

{ "evaluators": [ { "type": "json_schema", "schema": { "type": "object", "properties": { "invoice_number": {"type": "string"}, "date": {"type": "string", "format": "date"}, "total": {"type": "number"} }, "required": ["invoice_number", "date", "total"] }, "output": "$.nodes.extraction.output.data" }, { "type": "regex_match", "pattern": "^INV-[0-9]{6}$", "text": "$.nodes.extraction.output.data.invoice_number" } ], "aggregation": "all", "paths": [ {"path_id": "pass", "target_node_ids": ["save_to_database"]}, {"path_id": "fail", "target_node_ids": ["manual_extraction"]} ] }

Multi-Tier Quality Routing

{ "evaluators": [ {"type": "faithfulness", "threshold": 0.8, "weight": 0.5}, {"type": "relevance", "threshold": 0.7, "weight": 0.5} ], "aggregation": "weighted_average", "paths": [ { "path_id": "high_quality", "condition": "score >= 0.9", "target_node_ids": ["auto_publish"] }, { "path_id": "medium_quality", "condition": "score >= 0.7", "target_node_ids": ["queue_for_review"] }, { "path_id": "low_quality", "condition": "score < 0.7", "target_node_ids": ["regenerate"] } ] }

Troubleshooting

Guardrails Always Fail

Possible causes:

  • Threshold too high (reduce to 0.6-0.7 and tune up)
  • Evaluator misconfigured (wrong JSONPath references)
  • Output format doesn’t match evaluator expectations
  • Insufficient context for evaluation

Debugging:

  1. Check evaluation logs for actual scores
  2. Review failed outputs manually - should they pass?
  3. Lower threshold temporarily to collect score distribution
  4. Test evaluator in isolation with known good/bad examples

Guardrails Always Pass

Possible causes:

  • Threshold too low (increase to 0.8-0.9)
  • Evaluator not sensitive enough to quality differences
  • Bug in evaluator logic (always returns high score)

Debugging:

  1. Test with known bad outputs
  2. Check if evaluator is even running (view logs)
  3. Try different evaluator types
  4. Manually review “passing” outputs for quality

High Retry Rate

Solutions:

  • Improve upstream prompts (reduce quality variance)
  • Relax thresholds (accept more outputs)
  • Switch to better model (fewer failures)
  • Add HITL earlier (don’t retry forever)

Slow Evaluation

Optimizations:

  • Use faster evaluators (regex before LLM judge)
  • Cache evaluation results
  • Run evaluators in parallel
  • Sample evaluation (not every run)

Next Steps

Last updated on