> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Approval Module

> Human-in-the-loop approval system for dangerous tool operations

# Approval Module

The Approval module provides a minimal human-in-the-loop approval system for dangerous tool operations. It extends the existing callback system to require human approval before executing high-risk tools.

## Import

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import require_approval, set_approval_callback
from praisonaiagents.approval import ApprovalDecision, RiskLevel
```

## Quick Example

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import require_approval

@require_approval(risk_level="high")
def delete_file(path: str):
    """Delete a file - requires human approval."""
    import os
    os.remove(path)
    return f"Deleted {path}"
```

## Risk Levels

| Level      | Description                                         |
| ---------- | --------------------------------------------------- |
| `critical` | Irreversible actions (delete database, format disk) |
| `high`     | Potentially dangerous (delete files, send emails)   |
| `medium`   | Moderate risk (modify configs, write files)         |
| `low`      | Low risk but worth noting                           |

## Decorators

### `@require_approval(risk_level)`

Marks a tool as requiring human approval before execution.

**Parameters:**

* `risk_level` (str): One of "critical", "high", "medium", "low"

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
@require_approval(risk_level="critical")
def drop_database(db_name: str):
    """Drop a database - requires critical approval."""
    ...
```

## Functions

### `set_approval_callback(callback_fn)`

Set a custom approval callback function.

**Parameters:**

* `callback_fn`: Function that accepts `(function_name, arguments, risk_level)` and returns `ApprovalDecision`

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
def my_approval_handler(func_name, args, risk_level):
    if risk_level == "critical":
        # Always require manual approval for critical
        response = input(f"Approve {func_name}? (y/n): ")
        return ApprovalDecision(approved=response.lower() == 'y')
    return ApprovalDecision(approved=True)

set_approval_callback(my_approval_handler)
```

### `get_approval_callback()`

Get the current approval callback function.

**Returns:** The current callback or `None`

### `mark_approved(tool_name)`

Mark a tool as approved in the current context.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
mark_approved("delete_file")
```

### `is_already_approved(tool_name)`

Check if a tool is already approved in the current context.

**Returns:** `bool`

### `clear_approval_context()`

Clear the approval context (reset all approvals).

## ApprovalDecision Class

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
class ApprovalDecision:
    def __init__(
        self,
        approved: bool,
        modified_args: Optional[Dict[str, Any]] = None,
        reason: str = ""
    ):
        self.approved = approved
        self.modified_args = modified_args or {}
        self.reason = reason
```

## Example: Custom Approval UI

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import set_approval_callback, require_approval
from praisonaiagents.approval import ApprovalDecision
from rich.console import Console
from rich.prompt import Confirm

console = Console()

def rich_approval_handler(func_name, args, risk_level):
    """Custom approval handler with Rich UI."""
    console.print(f"\n[bold yellow]⚠️ Approval Required[/bold yellow]")
    console.print(f"Function: [cyan]{func_name}[/cyan]")
    console.print(f"Risk Level: [red]{risk_level}[/red]")
    console.print(f"Arguments: {args}")
    
    approved = Confirm.ask("Do you approve this action?")
    return ApprovalDecision(
        approved=approved,
        reason="User approved" if approved else "User denied"
    )

set_approval_callback(rich_approval_handler)

@require_approval(risk_level="high")
def send_email(to: str, subject: str, body: str):
    """Send an email - requires approval."""
    # Email sending logic
    return f"Email sent to {to}"
```

## Example: Automatic Approval for Low Risk

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import set_approval_callback
from praisonaiagents.approval import ApprovalDecision

def smart_approval(func_name, args, risk_level):
    """Auto-approve low risk, prompt for others."""
    if risk_level == "low":
        return ApprovalDecision(approved=True, reason="Auto-approved (low risk)")
    
    if risk_level == "medium":
        print(f"Medium risk: {func_name}")
        return ApprovalDecision(approved=True, reason="Auto-approved (medium)")
    
    # High and critical require manual approval
    response = input(f"Approve {func_name} ({risk_level})? (y/n): ")
    return ApprovalDecision(approved=response.lower() == 'y')

set_approval_callback(smart_approval)
```

## Global Registries

| Registry                  | Type             | Description                          |
| ------------------------- | ---------------- | ------------------------------------ |
| `APPROVAL_REQUIRED_TOOLS` | `Set[str]`       | Set of tool names requiring approval |
| `TOOL_RISK_LEVELS`        | `Dict[str, str]` | Mapping of tool names to risk levels |

## Related

* [Agent Module](/docs/sdk/praisonaiagents/agent/agent) - Agent class
* [Tools Module](/docs/sdk/praisonaiagents/tools/tools) - Tool definitions
* [Guardrails Module](/docs/sdk/praisonaiagents/guardrails/guardrails) - Input/output validation
