<!-- source: https://deepwiki.com/MervinPraison/PraisonAI/6.1-guardrails -->

# Guardrails

- README.md
- api.md
- src/praisonai/README.md

## Purpose and Scope

The guardrails system provides input/output validation and safety checks for agent and task executions in PraisonAI. Guardrails automatically validate LLM-generated outputs against custom criteria, with configurable retry logic when validation fails. The system supports function-based validation (Python callables), LLM-based validation (natural language criteria via `LLMGuardrail`), and preset validation rules (`GuardrailConfig`).

Guardrails are part of PraisonAI's broader safety and control architecture, which includes:

- Guardrails (this page) - Input/output validation
- Human Approval System (page 6.2) - Human-in-the-loop gates for tool execution
- Policy Engine (page 13) - Resource-level allow/deny rules
- Hooks System (page 10) - Lifecycle event interception

This page focuses on validation mechanisms for task outputs. For tool execution safety gates, see Human Approval System. For agent behavior control, see Autonomy and Handoff (page 2.6).

## Guardrail Types

PraisonAI supports three types of guardrails:

### Function-Based Guardrails

Custom Python functions that validate `TaskOutput` objects. Functions must accept exactly one parameter (the `TaskOutput`) and return either a `GuardrailResult` or `Tuple[bool, Any]`.

**Function Signature Requirements:**

- Single parameter of type TaskOutput
- Return type: GuardrailResult or Tuple[bool, Any]
- Return tuple format: (success: bool, result_or_error: Any)

```

```

Sources: [praisonaiagents/task/task.py162-215](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L162-L215) [examples/guardrail_example_fixed.py12-40](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/examples/guardrail_example_fixed.py#L12-L40)

### LLM-Based Guardrails

Natural language descriptions of validation criteria. The system creates an `LLMGuardrail` instance that uses an LLM to evaluate outputs against the description.

**Activation:** Provide a string description instead of a callable function:

```

```

The `LLMGuardrail` class constructs a validation prompt and interprets the LLM's response as "PASS" or "FAIL: [reason]".

Sources: [praisonaiagents/guardrails/llm_guardrail.py14-130](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/guardrails/llm_guardrail.py#L14-L130) [praisonaiagents/task/task.py206-213](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L206-L213)

### Preset Guardrails

Built-in validation presets activated by string identifiers:

- "permissive" - Minimal validation
- "safety" - Content safety checks
- "strict" - Comprehensive validation

Presets are only supported at the agent level (not task level).

Sources: [agent_guardrails_example.py73-84](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/agent_guardrails_example.py#L73-L84)

## Return Types

### GuardrailResult

Pydantic model providing structured validation results:

The `GuardrailResult.from_tuple()` class method converts legacy tuple returns to the structured format.

Sources: [praisonaiagents/guardrails/guardrail_result.py13-43](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/guardrails/guardrail_result.py#L13-L43)

### Tuple Format

Legacy format `Tuple[bool, Any]` for backward compatibility:

- First element: bool indicating success
- Second element: TaskOutput on success, error message on failure

The `Task._process_guardrail()` method automatically converts tuple returns to `GuardrailResult` instances.

Sources: [praisonaiagents/task/task.py162-204](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L162-L204) [test_guardrail_return_types.py32-46](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/test_guardrail_return_types.py#L32-L46)

## Architecture

### Guardrail Class Structure

```

```

**Key Code Entities:**

- GuardrailResult - Structured validation result with success status, result, and error message
- GuardrailConfig - Configuration object for guardrail settings (enables consolidated parameter system)
- GuardrailAction - Enumeration of possible guardrail actions (ALLOW, DENY, MODIFY, WARN)
- LLMGuardrail - LLM-based validator that evaluates outputs against natural language criteria
- Task.guardrail / Task.guardrails - Task-level validation configuration
- Agent.guardrails - Agent-level validation configuration
- Task._setup_guardrail() - Initializes guardrail function from configuration
- Task._process_guardrail() - Executes validation and handles retry logic

Sources: [praisonaiagents/guardrails/guardrail_result.py13-43](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/guardrails/guardrail_result.py#L13-L43) [praisonaiagents/guardrails/llm_guardrail.py14-130](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/guardrails/llm_guardrail.py#L14-L130) [praisonaiagents/task/task.py15-270](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L15-L270) [praisonaiagents/config/feature_configs.py](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/config/feature_configs.py)

### Validation Flow with Retry Logic

```

```

**Key Methods:**

- Task.execute() - Main task execution entry point
- Task._process_guardrail(output: TaskOutput) - Validates output and returns GuardrailResult
- Task._guardrail_fn - Stored callable (function or LLMGuardrail instance)
- LLMGuardrail.__call__(task_output: TaskOutput) - LLM-based validation implementation
- GuardrailResult.from_tuple(result: Tuple) - Converts legacy tuple format to structured result

Sources: [praisonaiagents/task/task.py240-350](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L240-L350) [praisonaiagents/guardrails/llm_guardrail.py70-130](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/guardrails/llm_guardrail.py#L70-L130) [praisonaiagents/guardrails/guardrail_result.py13-43](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/guardrails/guardrail_result.py#L13-L43)

### Guardrail Initialization Pipeline

```

```

**Code Path Details:**

- Task.__init__() - Accepts guardrail or guardrails parameter (aliases)
- Agent.__init__() - Accepts guardrails parameter and max_guardrail_retries
- Task._setup_guardrail() - Validates and initializes _guardrail_fn at praisonaiagents/task/task.py 161-215
- Agent._setup_guardrail() - Similar validation for agent-level guardrails
- inspect.signature() - Used to validate callable signatures
- LLMGuardrail.__init__() - Instantiated at praisonaiagents/guardrails/llm_guardrail.py 14-70

Sources: [praisonaiagents/task/task.py161-215](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L161-L215) [praisonaiagents/guardrails/llm_guardrail.py14-130](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/guardrails/llm_guardrail.py#L14-L130) [agent_guardrails_example.py43-89](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/agent_guardrails_example.py#L43-L89)

## Task-Level Guardrails

Task-level guardrails apply to a specific task and support all three guardrail types (function-based, LLM-based, and callable).

### Configuration

Task guardrails are configured via the `Task` constructor:

The `guardrails` parameter is an alias for `guardrail` - both refer to the same functionality.

Sources: [praisonaiagents/task/task.py46-96](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L46-L96)

### Validation Process

When a task executes:

1. Initial Execution: Agent generates TaskOutput
2. Guardrail Check: _process_guardrail(output) validates the output
3. Success Path: Returns validated output
4. Failure Path: Stores validation_feedback with error details Increments retry_count Re-executes task with feedback in prompt Repeats until success or max_retries reached

The validation feedback includes:

- validation_response - Error message from guardrail
- validated_task - Task name/description
- validation_details - Additional context
- rejected_output - The failed output

Sources: [praisonaiagents/task/task.py240-350](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L240-L350) [praisonaiagents/process/process.py147-169](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/process/process.py#L147-L169)

### Implementation Details

The `_setup_guardrail()` method performs initialization:

**For Callable Guardrails:**

- Validates function signature (exactly 1 parameter)
- Checks return type annotation if present
- Accepts GuardrailResult or Tuple[bool, Any]
- Stores function as _guardrail_fn

**For String Guardrails:**

- Creates LLMGuardrail instance
- Extracts LLM from agent.llm or agent.llm_instance
- Passes description to LLMGuardrail.__init__()
- Raises ValueError if agent not provided

Sources: [praisonaiagents/task/task.py161-215](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L161-L215)

## Agent-Level Guardrails

Agent-level guardrails apply to all tasks executed by an agent. They support function-based validation and preset strings, but **do not support** LLM-based guardrails (custom string descriptions).

### Configuration

Agent guardrails are configured via the `Agent` constructor:

**Supported preset strings:** `"permissive"`, `"safety"`, `"strict"`

Sources: [agent_guardrails_example.py1-93](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/agent_guardrails_example.py#L1-L93)

### Function-Based Agent Guardrails

Function-based guardrails at the agent level follow the same signature requirements as task guardrails:

```

```

The agent passes the guardrail function to each task it executes.

Sources: [agent_guardrails_example.py27-41](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/agent_guardrails_example.py#L27-L41)

### Preset Agent Guardrails

Preset guardrails use predefined validation rules:

```

```

Presets are resolved during agent initialization and applied to all tasks.

Sources: [agent_guardrails_example.py73-84](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/agent_guardrails_example.py#L73-L84)

### Limitations

Agent-level guardrails **cannot** use custom string descriptions for LLM-based validation. For LLM guardrails with natural language criteria, use task-level guardrails:

```

```

Sources: [agent_guardrails_example.py87-89](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/agent_guardrails_example.py#L87-L89)

## Retry Mechanism

### Retry Flow

```

```

Sources: [praisonaiagents/task/task.py240-350](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L240-L350) [praisonaiagents/process/process.py147-202](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/process/process.py#L147-L202)

### Validation Feedback Integration

When a guardrail fails, the system stores validation context in `task.validation_feedback`:

```

```

On retry, `Process._build_task_context()` injects this feedback into the task prompt:

```
Previous attempt failed validation with reason: Output too short
Validated task: WriteEmailTask
Validation feedback: Content length check failed
Rejected output: Hello.
Please try again with a different approach based on this feedback.
```

The feedback is cleared after inclusion to prevent persistence across multiple retries.

Sources: [praisonaiagents/process/process.py147-169](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/process/process.py#L147-L169) [praisonaiagents/task/task.py94](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L94-L94)

### Retry Counter Management

Retry tracking occurs at two levels:

**Task Level:**

- task.retry_count - Current retry attempt
- task.max_retries - Maximum allowed retries (default: 3)
- Incremented in task.execute() on validation failure

**Process Level:**

- process.task_retry_counter - Dict mapping task IDs to retry counts
- Used for fallback task selection
- Limits: Process.DEFAULT_RETRY_LIMIT = 3

Sources: [praisonaiagents/task/task.py48-96](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L48-L96) [praisonaiagents/process/process.py17-239](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/process/process.py#L17-L239)

## Configuration

### Consolidated Parameter System

Guardrails integrate with PraisonAI's consolidated parameter system via `GuardrailConfig` and `ExecutionConfig` for consistent configuration across agents and multi-agent systems.

**Agent Configuration via GuardrailConfig:**

```

```

**Multi-Agent Configuration via Agents:**

```

```

**Task-Level Override:**

```

```

Sources: [praisonaiagents/agents/agents.py189-224](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/agents/agents.py#L189-L224) [praisonaiagents/config/feature_configs.py](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/config/feature_configs.py) [praisonaiagents/task/task.py46-96](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L46-L96)

### Parameter Precedence

When configuring guardrails, the system follows this precedence order:

1. Task-level guardrail parameter (highest)
2. Agent-level guardrails parameter
3. Multi-agent guardrails parameter (lowest)

Task-level guardrails override agent-level guardrails. Agent-level guardrails apply when no task-level guardrail is specified.

Sources: [praisonaiagents/task/task.py90-91](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L90-L91)

### Configuration Options Summary

**Valid Preset Strings:**

- "permissive" - Minimal validation (agent/multi-agent only)
- "safety" - Content safety checks (agent/multi-agent only)
- "strict" - Comprehensive validation (agent/multi-agent only)

**Code Entity Mapping:**

- Task.guardrail / Task.guardrails - Task-level configuration
- Agent.guardrails - Agent-level configuration
- Agents.guardrails - Multi-agent configuration
- GuardrailConfig - Configuration data class at praisonaiagents/config/feature_configs.py
- ExecutionConfig - Execution settings including retry limits

Sources: [praisonaiagents/task/task.py46-52](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L46-L52) [praisonaiagents/agent/agent.py](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/agent/agent.py) [praisonaiagents/agents/agents.py191-193](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/agents/agents.py#L191-L193) [praisonaiagents/config/feature_configs.py](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/config/feature_configs.py) [agent_guardrails_example.py43-89](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/agent_guardrails_example.py#L43-L89)

## Examples

### Function-Based Guardrail with GuardrailResult

```

```

Sources: [examples/guardrail_example_fixed.py12-29](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/examples/guardrail_example_fixed.py#L12-L29)

### Function-Based Guardrail with Tuple Return

```

```

Sources: [examples/guardrail_example_fixed.py32-40](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/examples/guardrail_example_fixed.py#L32-L40)

### LLM-Based Guardrail (Task Level Only)

```

```

Sources: [examples/guardrail_example_fixed.py96-102](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/examples/guardrail_example_fixed.py#L96-L102)

### Agent-Level Function Guardrail

```

```

Sources: [agent_guardrails_example.py27-66](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/agent_guardrails_example.py#L27-L66)

### Agent-Level Preset Guardrail

```

```

Sources: [agent_guardrails_example.py73-84](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/agent_guardrails_example.py#L73-L84)

### Multi-Agent Shared Guardrail

```

```

Sources: [praisonaiagents/agents/agents.py189-224](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/agents/agents.py#L189-L224)

## Error Handling

### Validation Failure Processing

When a guardrail returns `False` or `GuardrailResult(success=False)`:

1. Extract Error Message: From GuardrailResult.error field From second element of Tuple[bool, str] Default: "Guardrail validation failed"
2. Check Retry Limit: If retry_count < max_retries : Store feedback and retry If retry_count >= max_retries : Raise ValidationError
3. Store Feedback: validation_response : Error message validated_task : Task identifier rejected_output : Failed output text
4. Retry Execution: Build new prompt with feedback context Increment retry_count Re-execute task with agent

Sources: [praisonaiagents/task/task.py240-350](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L240-L350)

### Guardrail Setup Errors

The `_setup_guardrail()` method validates guardrail configuration and raises `ValueError` for:

**Invalid Function Signatures:**

```

```

**Invalid Return Annotations:**

```

```

**Missing Agent for LLM Guardrails:**

```

```

Sources: [praisonaiagents/task/task.py168-214](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L168-L214)

### LLM Guardrail Errors

The `LLMGuardrail` class handles LLM initialization and validation errors gracefully:

**LLM Initialization Failure:**

- Logs error message
- Returns None for LLM instance
- Validation passes through output unchanged

**LLM Call Failure:**

- Catches exceptions during validation
- Logs error
- Returns (True, output) - passes through on error

**Unclear LLM Response:**

- Response doesn't start with "PASS" or "FAIL"
- Logs warning
- Returns (True, output) - passes through when unclear

Sources: [praisonaiagents/guardrails/llm_guardrail.py38-130](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/guardrails/llm_guardrail.py#L38-L130)

Sources: [praisonaiagents/guardrails/guardrail_result.py1-43](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/guardrails/guardrail_result.py#L1-L43) [praisonaiagents/guardrails/llm_guardrail.py1-130](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/guardrails/llm_guardrail.py#L1-L130) [praisonaiagents/task/task.py15-350](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/task/task.py#L15-L350) [praisonaiagents/agents/agents.py172-224](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/agents/agents.py#L172-L224) [praisonaiagents/process/process.py17-202](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/praisonaiagents/process/process.py#L17-L202) [agent_guardrails_example.py1-93](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/agent_guardrails_example.py#L1-L93) [examples/guardrail_example_fixed.py1-140](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/examples/guardrail_example_fixed.py#L1-L140) [test_guardrail_return_types.py1-156](https://github.com/MervinPraison/PraisonAI/blob/ab80807b/test_guardrail_return_types.py#L1-L156)
