> ## 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 Backends

> Choose how tool approvals reach a human — console prompt, plan mode, accept-edits, or a chat channel

Pick who (or what) approves a tool call — the terminal, a coding-mode fast path, or a chat channel that fans out to Slack/Telegram/Discord.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Approval Backends"
        Request[📋 User Request] --> Process[⚙️ Approval Backends]
        Process --> Result[✅ Result]
    end

    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff

    class Request input
    class Process process
    class Result output
```

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

agent = Agent(
    name="coder",
    instructions="Edit files carefully.",
    tools=["write_file"],
    approval="console",
)
agent.start("Refactor utils.py")
```

The user triggers a risky tool; the chosen approval backend prompts or routes the decision to a human.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Approval Backends"
        In[📝 Risky Tool Call] --> Backend[⚙️ Approval Backend]
        Backend --> Human[🧑 Human Decision]
        Human --> Agent[🤖 Agent]
        Agent --> Out[✅ Result]
    end

    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef process fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff

    class In input
    class Backend,Human process
    class Agent agent
    class Out output
```

### Available Backends

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    subgraph "pip install praisonai-code"
        C[console]
        P[plan]
        AE[accept-edits]
        BY[bypass]
        AU[auto]
        AG[agent]
        N[none]
    end

    subgraph "pip install praisonai"
        SL[slack]
        TG[telegram]
        DC[discord]
        WH[webhook]
        HT[http]
        SC[secure]
        PR[presentation]
    end

    classDef standalone fill:#10B981,stroke:#7C90A0,color:#fff
    classDef wrapper fill:#189AB4,stroke:#7C90A0,color:#fff

    class C,P,AE,BY,AU,AG,N standalone
    class SL,TG,DC,WH,HT,SC,PR wrapper
```

<Note>
  **Which class runs the prompt?**

  * `Agent(approval=True)` in Python → `praisonaiagents.approval.ConsoleBackend` (Rich terminal prompt, no permission-mode features).
  * `praisonai --approval console` (also `true`, `Console`, `plan`, `accept-edits`, `bypass`) → `praisonai_code.cli.approval_backend.InteractiveCLIApprovalBackend`, which layers `PermissionMode` (plan / accept-edits / bypass) and declarative permission rules on top.

  Both render the same unified-diff preview for file-mutating tools. The extra CLI-only features (plan mode, accept-edits, bypass, `praisonai permissions` rules) come from `InteractiveCLIApprovalBackend`.

  * On any of these backends, standing registry grants (`PRAISONAI_AUTO_APPROVE`, YAML `approve:`, session grants recorded via `[s]`) are now checked **before** the backend is invoked — no more re-prompting for calls the user already blessed. Fixed in [PR #4878](https://github.com/MervinPraison/PraisonAI/pull/4878). See [Standing grants and attached backends](/docs/features/approval#standing-grants-and-attached-backends).
</Note>

## How It Works

A risky tool call pauses until the chosen backend collects a human decision.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Agent
    participant ApprovalBackend

    User->>Agent: Task with risky tool
    Agent->>ApprovalBackend: Request approval
    ApprovalBackend-->>Agent: Approve / deny
    Agent-->>User: Result or blocked
```

### Diff preview

The `console` backend renders a coloured unified diff for file-mutating tools — `edit_file`, `acp_edit_file`, `write_file`, `acp_create_file`, and `apply_patch` — so the reviewer sees the concrete change, not truncated arguments.

The diff rides on `ApprovalRequest.context["diff"]`, a stable public field. Wrapper backends (`slack`, `telegram`, `discord`, `webhook`, `http`) can read it and render or attach it in their channel — this is where custom-backend authors should look.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Inside a custom backend
def request_approval_sync(self, request):
    diff = request.context.get("diff")
    if diff:
        ...  # render as a code block, attachment, or on-request expand
```

See [Approval › Diff preview in approval prompts](/docs/features/approval#diff-preview-in-approval-prompts) for the full tool contract and safety rules.

## Backend Matrix

| Backend                           | Where it runs | One-line meaning                                                         |
| --------------------------------- | ------------- | ------------------------------------------------------------------------ |
| `console` (also `true`/`yes`/`1`) | Standalone    | Ask on the terminal, y/N — shows a rendered diff for file-mutating tools |
| `none` (also `false`/`no`/`0`)    | Standalone    | Auto-approve everything (unsafe)                                         |
| `auto`                            | Standalone    | Auto-approve safe read-only tools                                        |
| `plan`                            | Standalone    | Coding-mode plan approval                                                |
| `accept-edits`                    | Standalone    | Auto-accept file-edit tools                                              |
| `bypass`                          | Standalone    | Approve without prompting (dev)                                          |
| `agent`                           | Standalone    | Delegate to a reviewer agent (see below)                                 |
| `slack`                           | Wrapper       | Approvals routed to Slack                                                |
| `telegram`                        | Wrapper       | Approvals routed to Telegram                                             |
| `discord`                         | Wrapper       | Approvals routed to Discord                                              |
| `webhook`                         | Wrapper       | Custom outbound HTTP webhook                                             |
| `http`                            | Wrapper       | Inbound HTTP approval endpoint                                           |
| `secure`                          | Wrapper       | Secure-mode policy (audit-logged)                                        |
| `presentation`                    | Wrapper       | Presentation/demo-safe policy                                            |

<Note>
  Wrapper backends (`slack`, `telegram`, `discord`, `webhook`, `http`, `secure`, `presentation`) require `pip install praisonai`.
</Note>

### CLI opt-outs register a registry backend

`praisonai code --no-safe` and `--dangerously-skip-approval` do two things, not one:

* **Set env vars** — `PRAISON_APPROVAL_MODE=auto`, `PRAISONAI_TOOL_SAFETY=off` — consumed by the CLI's own tool wiring.
* **Register `AutoApproveBackend`** on the approval registry — consumed by the core `@require_approval` decorator that gates critical tools like `acp_execute_command`. Without this the flag was a no-op for any registry-decorated tool.

A safe-mode run *removes* the `AutoApproveBackend` a prior `--no-safe` installed in the same process, and removes **only** that backend — a caller-supplied backend or one installed by `--plan` is preserved. A per-agent backend still wins, since the core consults `Agent(approval=…)` before the global registry. See [Approval → Bypassing safety](/docs/features/approval#bypassing-safety) for the full resolution order.

***

## Quick Start

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

agent = Agent(
    name="Code assistant",
    instructions="Help refactor code files.",
)
agent.start("Refactor utils.py")
```

<Steps>
  <Step title="Choose your approval mode">
    <Tabs>
      <Tab title="Terminal">
        Ask the user on the terminal before each risky tool call:

        ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
        praisonai-code run --approval console "Refactor utils.py"
        ```
      </Tab>

      <Tab title="Coding fast path">
        Use plan/accept-edits mode (Claude Code-style flow) for unattended coding runs:

        ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
        praisonai-code run --approval plan "Refactor utils.py"
        ```

        `accept-edits` auto-accepts file edits; `plan` requires explicit plan approval before execution.
      </Tab>

      <Tab title="Chat channel (wrapper)">
        Route approvals to a Slack channel:

        ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
        praisonai run --approval slack --approval-timeout 300 "Refactor utils.py"
        ```

        <Note>
          Channel backends (`slack`, `telegram`, `discord`, `webhook`, `http`, `secure`, `presentation`) require `pip install praisonai`.
        </Note>
      </Tab>
    </Tabs>
  </Step>
</Steps>

***

## `--approval-timeout`

`--approval-timeout` takes seconds. Pass `none` to wait indefinitely.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai-code run --approval console --approval-timeout 60 "..."
praisonai-code run --approval slack --approval-timeout none "..."
```

***

## Reviewer-Agent Mode (`--approval agent`)

When you pass `--approval agent`, a built-in LLM reviewer gates every tool call. The default reviewer instruction is:

> *"You are a security reviewer. Only approve low-risk read operations. Deny anything destructive. Respond with exactly one word: APPROVE or DENY"*

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai-code run --approval agent "List all files and summarise the project"
```

The reviewer responds with exactly `APPROVE` or `DENY` for each pending tool call. You can override the default instruction by passing a custom reviewer prompt via the API:

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

reviewer = Agent(
    name="strict-reviewer",
    instructions="Only approve file reads. Deny everything else. Reply APPROVE or DENY.",
)

agent = Agent(
    name="Assistant",
    instructions="Help with coding tasks.",
    approval=AgentApproval(approver_agent=reviewer),
)
agent.start("Read and summarise main.py")
```

***

## Unknown-Backend Error

If you pass an unrecognised backend name, the CLI raises:

```
Unknown approval backend: '<value>'. Valid options: console, plan, accept-edits, bypass, auto, agent, none, discord, http, presentation, secure, slack, telegram, webhook
```

Use this to trap typos — the valid list is alphabetically sorted within the wrapper group.

***

## Best Practices

<AccordionGroup>
  <Accordion title="Use console in interactive dev, agent for unattended runs">
    Use `console` in interactive dev, `agent` for unattended runs where a reviewer LLM can gate tools.
  </Accordion>

  <Accordion title="Pair accept-edits and plan with praisonai-code code">
    `accept-edits` and `plan` are the coding-mode fast paths — pair them with `praisonai-code code`.
  </Accordion>

  <Accordion title="Never use none outside throwaway sandboxes">
    `none` disables approval entirely; only use it in throwaway sandboxes.
  </Accordion>
</AccordionGroup>

***

## Related

<CardGroup cols={2}>
  <Card title="Local Tools Loading" icon="wrench" href="/docs/features/local-tools-loading">
    Approval decides who says yes to your local tools.
  </Card>

  <Card title="Approval" icon="shield" href="/docs/features/approval">
    The full approval system — dangerous tool gating, TTY detection, and safe defaults.
  </Card>
</CardGroup>
