Skip to main content
Interactive approval is now the default for dangerous built-in tools — no configuration needed. When an agent calls a sensitive or external tool, PraisonAI pauses and asks you before it runs. Your choices can be saved as project rules for next time. See Approval for the full list of gated tools and bypass options.
The user requests a change; PraisonAI pauses on dangerous tools until they allow or deny in the terminal.

Quick Start

1

Simple Usage

2

With Configuration

A prompt appears:
Each key chooses how long the approval lasts:
  • [o] once — approve this exact call and prompt again next time (default; backward compatible).
  • [s] session — auto-approve matching calls (same permission target) for the rest of this run. Never persisted — restarting the process starts over.
  • [a] always — persist an allow-rule to approvals.json. The suggested pattern in parentheses (e.g. bash:git status *, edit:src/app.py) is what gets saved; it is auto-derived from the tool + arguments.
  • [n] no — deny (also selected on Ctrl-C / EOF).
The prompt no longer offers a single “allow ALL uses of this tool” key. Author a blanket bash:* rule with praisonai permissions allow "bash:*" when you need one.

When approval is required

Approval runs when any of these apply:
  • The agent has approval=True (or a CLI --approval backend)
  • The tool is in the default dangerous-tools list (e.g. bash, write, delete)
  • The tool has trust_level == "external" in the tool registry

Scope choice

Four options in one row — this diagram picks the right one.
A nameless always grant degrades to session. An always grant without an agent_name would match any later agent making the same target call, so the registry refuses to persist it and keeps it in-memory for this run only — which is why an “always” click sometimes doesn’t outlive the run.
session grants are keyed by (agent_name, permission_target) and live in an in-memory set. clear_approved() wipes them, and they are never written to approvals.json.

How the suggested pattern is derived

The always (…) hint isn’t magic — it maps the tool + arguments to a reusable target.
apply_patch stays tool:apply_patch — it takes multi-file patch text, so there is no stable path to scope to. Pressing [a] persists tool:apply_patch, which covers every future apply_patch call regardless of file. If you want per-file scoping, use edit_file instead.

Session-only workflow

Press [s] to auto-approve a repeated call for the rest of the run — nothing is written to disk.
Press [a] instead when the grant should persist across runs.

Change Preview

Before you press [a] on a file-mutating tool, PraisonAI prints a preview so you approve the actual change — not just the tool name. For edit / apply_patch (unified diff supplied by the caller):
For write (up to 2000 chars, truncated after):
No preview is shown for read-only or non-file tools.

Approval modes

The CLI uses --approval bypass but the enum value is bypass_permissions.

Persistence

Press [a] to write an allow-rule to approvals.json via PermissionManager (scoped to the approving agent). The suggested pattern (e.g. bash:git status *, edit:utils.py) is what gets saved: [a] uses the shared suggest_scope_pattern helper so the CLI, YAML --allow/--deny, and Python PermissionManager all scope identically. Compound commands (&&, |, ;, $(...)) fall back to a literal single-use pattern so a persisted rule can only match the exact invocation you approved. For a blanket <tool>:* rule, author it directly with praisonai permissions allow "bash:*". Session grants live in an in-memory _session_scoped_targets set and are cleared by clear_approved() at run teardown. Always grants persist across restarts and survive clear_approved().
Tune the derived pattern with Reusable Approval Scopes — call PermissionManager.suggest_scope_pattern(target) for a custom UI, or hand-author bash:git * via praisonai permissions allow.
Manage rules with:
Each entry carries pattern, approved, scope, created_at, expires_at, agent_name, and a derived flag. derived: true marks approvals whose pattern was auto-generated by reusable command-prefix scopes — user-edited or hand-authored patterns save with derived: false. Old files without the field load cleanly (derived defaults to False).
When building a custom UI or CLI wrapper, call PermissionManager.suggest_scope_pattern(target) to get a derived prefix glob (e.g. bash:git status * for bash:git status -s) before saving a session or always approval. Show the suggestion to the user, let them tweak it, then pass the final value as pattern= to approve(). See Reusable Approval Scopes.

Non-interactive and CI

Without a TTY, prompts default to deny so CI pipelines fail closed.

Best Practices

Use --approval plan until you trust the agent’s behaviour in a codebase.
Tools marked external always prompt — verify third-party integrations before allowing.
Team-wide allow/deny patterns belong in version control.
The suggested pattern shown in parentheses (always (bash:git status *)) is the exact rule that will be saved — it covers every git status … variant but never expands to git push or other subcommands. There is no longer a blanket “allow ALL uses of bash” keystroke in the interactive prompt — grant blanket access explicitly via praisonai permissions allow "bash:*" when you actually want it.
[s] grants stay in memory and vanish when the process ends — ideal for a repeated call in a single task. Reserve [a] always for calls you want persisted across every future run.
The preview is your last chance to catch an unintended edit. It renders for edit, write, and apply_patch so you approve the actual change, not just the tool name.
A nameless always grant can’t be persisted — it would match any later agent, so the registry keeps it in-memory for this run only. Set Agent(name=...) so [a] writes a durable, agent-scoped rule.

Bot/chat-channel approvals

This page covers the CLI/terminal approval flow. When running PraisonAI on Telegram, Slack, or Discord, approvals render as interactive buttons and are actor-bound — only the requester and configured admins can resolve them.

Interactive Callback Authorization

Lock approval buttons to specific users in shared chats — covers Telegram, Slack, and Discord bots.

derive_pattern — shared narrow-pattern derivation used by CLI, YAML, and Python rules

Permissions CLI

praisonai permissions reference

Permission Modes

All modes for agents and CLI

Permissions Module

Python SDK API