--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.
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
Enable via CLI
Run the gateway with the secure approval backend:The alias
--approval presentation is equivalent.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:Security Properties
The secure backend fixes four gaps in the per-channel backends (TelegramApproval, SlackApproval, etc.):
| Property | Default backends | --approval secure |
|---|---|---|
| Actor authorisation | ❌ Anyone can approve | ✅ PRAISONAI_APPROVAL_ACTORS allowlist |
| Pending state | In-memory (lost on restart) | ✅ SQLite persistence |
| Decision binding | By message ID | ✅ By unguessable approval ID |
| LLM classifier in decision path | ✅ (some) | ❌ Removed |
| Unknown decision values | Silently treated as deny | ✅ Rejected at the Telegram callback boundary (fail-closed) |
Unguessable Approval ID
Each approval request carries a cryptographically unguessableapproval_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
| Flag | Description |
|---|---|
--approval secure | Enable PresentationApprovalBackend |
--approval presentation | Alias for --approval secure |
Environment Variables
| Variable | Required | Description |
|---|---|---|
PRAISONAI_APPROVAL_ACTORS | Yes — must be non-empty | Comma-separated user IDs allowed to approve tool calls |
PRAISONAI_HOME | No | Override base directory; approval store defaults to $PRAISONAI_HOME/state/approvals.sqlite |
Storage
Approvals persist to SQLite at:PRAISONAI_HOME:
API Reference
| Method | Description |
|---|---|
rehydrate() | Restore pending approvals from the store; returns count |
handle_callback(approval_id, decision, actor) | Resolve a button tap; returns True when handled, False when unknown/replay/unauthorised |
request_approval(request) | ApprovalProtocol implementation — wait for a decision |
Best Practices
Always set PRAISONAI_APPROVAL_ACTORS
Always set PRAISONAI_APPROVAL_ACTORS
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.
Call rehydrate() at startup
Call rehydrate() at startup
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.Use SQLite persistence for production
Use SQLite persistence for production
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.Scope actor IDs to one platform
Scope actor IDs to one platform
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.Related
Approval (Concept)
High-level approval lifecycle model
Durable Approvals
Durable approval storage
Message Presentation
Interactive buttons and keyboards
Interactive Approval
Approval via chat interactions

