Skip to main content
--approval secure is a hardened approval backend that persists decisions across restarts, authorises approvers against an allowlist, and binds each decision to an unguessable approval ID — not to a message ID that anyone could race.
For the high-level approval lifecycle model, see the Approval concept page.
The user triggers a risky tool; the secure backend stores the request until an authorised actor approves or denies via the channel callback.

How It Works

A risky tool call is stored durably until an authorised actor resolves it by unguessable approval ID.

Telegram: zero-config wiring

When the transport is a Telegram bot, Agent(approval="secure") (alias "presentation") is auto-wired on TelegramBot.start() — the bot supplies the channel renderer and target, and calls rehydrate() to restore pending approvals. No register_approval_backend() call is required. See Telegram Durable Approval.

Quick Start

1

Enable via CLI

Run the gateway with the secure approval backend:
The alias --approval presentation is equivalent.
2

Set Allowed Approvers

PRAISONAI_APPROVAL_ACTORS is required and must be non-empty when using --approval secure. The gateway fails closed if this variable is not set:
Values are comma-separated actor (user) IDs from your chat platform.
3

Programmatic Usage

4

Rehydrate on Restart

After a restart, rehydrate pending approvals so late decisions still resolve:

Security Properties

The secure backend fixes four gaps in the per-channel backends (TelegramApproval, SlackApproval, etc.):

Unguessable Approval ID

Each approval request carries a cryptographically unguessable approval_id in the button callback payload. A deny or approve decision binds to that specific ID — not to the Telegram/Slack message ID, which an attacker could observe or guess. Replays are rejected: once an ID is resolved it cannot be re-used.

Persistence and Rehydration

Pending approvals are written to ~/.praisonai/state/approvals.sqlite (honouring PRAISONAI_HOME). On restart, rehydrate() restores all pending approvals with the original allowed_actors re-applied — a restored approval cannot become unrestricted just because the process restarted.

CLI Flags


Environment Variables

PRAISONAI_APPROVAL_ACTORS must be set and non-empty. The gateway fails closed (refuses to run) if this variable is missing or empty when --approval secure is active.

Storage

Approvals persist to SQLite at:
Override with PRAISONAI_HOME:

API Reference


Best Practices

The backend is fail-closed: without an allowlist it cannot authorise any actor and will reject all approvals. Set this variable in your deployment environment before starting the gateway.
In a long-lived gateway, call await backend.rehydrate() after construction so any approval that was pending when the process last stopped can still be resolved. Without rehydration, pending approvals are invisible.
Passing a store=ApprovalStore(...) makes approvals durable across restarts. Without a store, the backend uses in-memory state only and pending approvals are lost on restart.
Actor IDs are platform-specific strings (Telegram user IDs, Slack user IDs, etc.). If you run bots on multiple platforms, ensure the IDs in PRAISONAI_APPROVAL_ACTORS match the platform your approvers use.

Approval (Concept)

High-level approval lifecycle model

Durable Approvals

Durable approval storage

Message Presentation

Interactive buttons and keyboards

Interactive Approval

Approval via chat interactions