Source Change
PraisonAI PR #1457 — fix: resolve wrapper gaps - nested asyncio.run, hot-path logging, fragmented approval schema (merged 2026-04-18).
The PR introduces three new modules in src/praisonai/praisonai/:
| Module |
Surface |
Doc Impact |
_approval_spec.py |
User-facing (via YAML/CLI normalization) |
Required — new content + updates |
_async_bridge.py |
Internal (private) |
Optional changelog mention only |
_logging.py |
Internal (private) |
Update any docs that reference logging.basicConfig patterns |
This issue covers the ApprovalSpec documentation, which is the only user-visible change.
What Changed (User-Visible)
A new unified ApprovalSpec dataclass replaces the previously fragmented approval configuration that was scattered across CLI flags, YAML keys, and Python kwargs with inconsistent field names. The same shape now drives all three surfaces.
YAML Schema (NEW — must be documented)
approval:
enabled: true # bool, default false
backend: "console" # console | slack | telegram | discord | webhook | http | agent | auto | none
approve_all_tools: false # bool, default false
timeout: 60 # float seconds, default null (no timeout); accepts "none"
approve_level: "high" # low | medium | high | critical, default null
guardrails: "..." # optional guardrail description
Shorthand forms also accepted:
approval: true # → enabled, console backend
approval: false # → disabled
approval: slack # → enabled, slack backend
approval: null # → disabled
Legacy YAML aliases (backward compatible — should be noted but discouraged)
| Legacy key |
New key |
backend_name |
backend |
all_tools |
approve_all_tools |
approval_timeout |
timeout |
Primary keys win when both are present (verified by tests/unit/test_approval_spec.py).
Validation (NEW behaviour to document)
Unknown keys now raise ValueError with the list of allowed keys — silent typos no longer pass. Document this so users know misspelled keys will fail loudly.
CLI → ApprovalSpec mapping
| CLI flag |
Maps to |
--trust |
backend="auto", enabled=True |
--approval <backend> |
backend=<backend>, enabled=True |
--approve-all-tools |
approve_all_tools=True |
--approval-timeout <sec> |
timeout=<sec> |
--approve-level <level> |
approve_level=<level> |
--guardrail "<text>" |
guardrails="<text>" |
Required Documentation Updates
1. Update docs/features/approval.mdx (existing — 264 lines)
Currently focuses on Python decorator/callback APIs. Add a new top section showing the unified config-first approach (agent-centric, per AGENTS.md rule 9):
from praisonaiagents import Agent
# Simplest: enable approval with defaults
agent = Agent(name="Admin", instructions="...", approval=True)
# String shorthand: pick a backend
agent = Agent(name="Admin", instructions="...", approval="slack")
# Full config: all options
agent = Agent(
name="Admin",
instructions="...",
approval={
"enabled": True,
"backend": "slack",
"approve_all_tools": False,
"timeout": 120,
"approve_level": "high",
},
)
Then keep the existing decorator/callback content lower in the page as advanced usage.
2. Update docs/cli/tool-approval.mdx (existing — 235 lines)
- Add a section "YAML configuration" showing the
approval: block with all fields, shorthand forms, and the validation behaviour.
- Add a "CLI ⇄ YAML ⇄ Python" mapping table so users can translate between surfaces.
- Note that unknown
approval: keys now raise ValueError.
3. Update docs/features/approval-protocol.mdx (existing — 588 lines)
Add a short note linking to the new ApprovalSpec section explaining that backend selection is the same string used in --approval and YAML backend:.
4. Do NOT modify docs/concepts/approval.mdx
Per AGENTS.md §1.8: docs/concepts/ is HUMAN-APPROVED ONLY. Place all new content under docs/features/.
Suggested Page Skeleton (for the agent that picks this up)
Add the new content into docs/features/approval.mdx as a leading "Quick Start" section, following the AGENTS.md template:
---
title: "Approval"
sidebarTitle: "Approval"
description: "Require human approval before agents run dangerous tools"
icon: "shield-check"
---
Approval pauses an agent before it runs a risky tool and asks a human (or another channel) to allow or deny it.
```mermaid
graph LR
Agent[🤖 Agent] --> Tool{🔧 Tool Call}
Tool -->|risky| Approve[🛡️ Approval]
Approve -->|✅ allow| Run[▶️ Execute]
Approve -->|❌ deny| Skip[⏹️ Skip]
Tool -->|safe| Run
classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff
classDef gate fill:#F59E0B,stroke:#7C90A0,color:#fff
classDef ok fill:#10B981,stroke:#7C90A0,color:#fff
class Agent agent
class Tool,Approve gate
class Run,Skip ok
```
## Quick Start
<Steps>
<Step title="Enable approval">
\`\`\`python
from praisonaiagents import Agent
agent = Agent(name="Admin", instructions="Manage the server", approval=True)
agent.start("Clean up old logs")
\`\`\`
</Step>
<Step title="Pick a backend">
\`\`\`python
agent = Agent(name="Admin", instructions="...", approval="slack")
\`\`\`
</Step>
<Step title="Full configuration">
\`\`\`python
agent = Agent(
name="Admin",
instructions="...",
approval={
"enabled": True,
"backend": "slack",
"approve_all_tools": False,
"timeout": 120,
"approve_level": "high",
},
)
\`\`\`
</Step>
</Steps>
## How users approve
```mermaid
sequenceDiagram
participant Agent
participant Approval
participant User
Agent->>Approval: Tool call (write_file)
Approval->>User: Allow write_file? (Slack/console/...)
User-->>Approval: Yes / No
Approval-->>Agent: Decision
Agent->>Agent: Execute or skip
```
## Configuration
| Option | Type | Default | Description |
|---|---|---|---|
| `enabled` | `bool` | `false` | Turn approval on/off |
| `backend` | `str` | `"console"` | One of: `console`, `slack`, `telegram`, `discord`, `webhook`, `http`, `agent`, `auto`, `none` |
| `approve_all_tools` | `bool` | `false` | If true, every tool needs approval (not just risky ones) |
| `timeout` | `float` | `null` | Seconds to wait for a decision; `null` = no timeout |
| `approve_level` | `str` | `null` | Auto-approve up to this risk level: `low`, `medium`, `high`, `critical` |
| `guardrails` | `str` | `null` | Free-text guardrail description |
## YAML
\`\`\`yaml
agents:
admin:
role: Server admin
approval:
enabled: true
backend: slack
timeout: 120
approve_level: high
\`\`\`
Shorthands: `approval: true` (console), `approval: slack` (named backend), `approval: false` / `null` (off).
> Unknown keys raise `ValueError` — typos like `approve_levels:` will fail loudly.
## CLI
\`\`\`bash
praisonai "deploy" --approval slack --approval-timeout 120 --approve-level high
\`\`\`
| CLI flag | YAML / Python field |
|---|---|
| `--trust` | `backend: auto` |
| `--approval <name>` | `backend: <name>` |
| `--approve-all-tools` | `approve_all_tools: true` |
| `--approval-timeout <s>` | `timeout: <s>` |
| `--approve-level <l>` | `approve_level: <l>` |
| `--guardrail "<txt>"` | `guardrails: "<txt>"` |
## Best practices
<AccordionGroup>
<Accordion title="Use the default `console` backend during development">
No env vars needed; you see the prompt directly in the terminal.
</Accordion>
<Accordion title="Use `slack` / `telegram` for production teams">
Routes approval requests to a channel humans already watch.
</Accordion>
<Accordion title="Set a `timeout` for unattended runs">
Without a timeout, the agent blocks indefinitely waiting for a decision.
</Accordion>
<Accordion title="Prefer `approve_level` over `approve_all_tools`">
`approve_level: high` lets safe tools run without prompts and only gates the dangerous ones.
</Accordion>
</AccordionGroup>
## Related
<CardGroup cols={2}>
<Card title="Approval Protocol" icon="plug" href="/features/approval-protocol">
All backend protocols (Slack, Telegram, Discord, Webhook, HTTP, Agent)
</Card>
<Card title="CLI tool approval" icon="terminal" href="/cli/tool-approval">
Full CLI flag reference
</Card>
</CardGroup>
Source-of-Truth References
For the implementing agent — read these before writing:
- New module:
src/praisonai/praisonai/_approval_spec.py (140 lines, on main branch of MervinPraison/PraisonAI after PR #1457 merge)
- CLI mapping site:
src/praisonai/praisonai/cli/main.py
- YAML normalization site:
src/praisonai/praisonai/agents_generator.py — function _run_praisonai and _merge_cli_config
- Test fixtures:
src/praisonai/tests/unit/test_approval_spec.py
- Existing protocol docs:
praisonai-package/src/praisonai-agents/praisonaiagents/approval/protocols.py
Acceptance Criteria
Out of Scope (no doc changes needed)
_async_bridge.py — private internal helper for safe asyncio.run. Users never import or call it.
_logging.py — private internal helper that namespaces praisonai.* loggers and stops library code mutating the root logger. Only worth a one-line mention in the changelog if one exists.
If an existing docs page tells users to call logging.basicConfig(...) to control PraisonAI log output, update it to recommend setting the LOGLEVEL env var or logging.getLogger("praisonai").setLevel(...) instead, since library code no longer touches the root logger.
Source Change
PraisonAI PR #1457 — fix: resolve wrapper gaps - nested asyncio.run, hot-path logging, fragmented approval schema (merged 2026-04-18).
The PR introduces three new modules in
src/praisonai/praisonai/:_approval_spec.py_async_bridge.py_logging.pylogging.basicConfigpatternsThis issue covers the
ApprovalSpecdocumentation, which is the only user-visible change.What Changed (User-Visible)
A new unified
ApprovalSpecdataclass replaces the previously fragmented approval configuration that was scattered across CLI flags, YAML keys, and Python kwargs with inconsistent field names. The same shape now drives all three surfaces.YAML Schema (NEW — must be documented)
Shorthand forms also accepted:
Legacy YAML aliases (backward compatible — should be noted but discouraged)
backend_namebackendall_toolsapprove_all_toolsapproval_timeouttimeoutPrimary keys win when both are present (verified by
tests/unit/test_approval_spec.py).Validation (NEW behaviour to document)
Unknown keys now raise
ValueErrorwith the list of allowed keys — silent typos no longer pass. Document this so users know misspelled keys will fail loudly.CLI → ApprovalSpec mapping
--trustbackend="auto",enabled=True--approval <backend>backend=<backend>,enabled=True--approve-all-toolsapprove_all_tools=True--approval-timeout <sec>timeout=<sec>--approve-level <level>approve_level=<level>--guardrail "<text>"guardrails="<text>"Required Documentation Updates
1. Update
docs/features/approval.mdx(existing — 264 lines)Currently focuses on Python decorator/callback APIs. Add a new top section showing the unified config-first approach (agent-centric, per AGENTS.md rule 9):
Then keep the existing decorator/callback content lower in the page as advanced usage.
2. Update
docs/cli/tool-approval.mdx(existing — 235 lines)approval:block with all fields, shorthand forms, and the validation behaviour.approval:keys now raiseValueError.3. Update
docs/features/approval-protocol.mdx(existing — 588 lines)Add a short note linking to the new ApprovalSpec section explaining that
backendselection is the same string used in--approvaland YAMLbackend:.4. Do NOT modify
docs/concepts/approval.mdxPer AGENTS.md §1.8:
docs/concepts/is HUMAN-APPROVED ONLY. Place all new content underdocs/features/.Suggested Page Skeleton (for the agent that picks this up)
Add the new content into
docs/features/approval.mdxas a leading "Quick Start" section, following the AGENTS.md template:Source-of-Truth References
For the implementing agent — read these before writing:
src/praisonai/praisonai/_approval_spec.py(140 lines, onmainbranch ofMervinPraison/PraisonAIafter PR #1457 merge)src/praisonai/praisonai/cli/main.pysrc/praisonai/praisonai/agents_generator.py— function_run_praisonaiand_merge_cli_configsrc/praisonai/tests/unit/test_approval_spec.pypraisonai-package/src/praisonai-agents/praisonaiagents/approval/protocols.pyAcceptance Criteria
docs/features/approval.mdxopens with the new agent-centricapproval=True/approval="<backend>"/approval={...}Quick Start.ApprovalSpecfields documented with type, default, and one-line description matching the SDK source exactly.true,false,null, string) shown.ValueError) called out.docs/concepts/approval.mdx(human-only folder per AGENTS.md §1.8).docs/cli/tool-approval.mdxupdated with YAML section and validation note.backend_name,all_tools,approval_timeout) noted as deprecated but still supported.Out of Scope (no doc changes needed)
_async_bridge.py— private internal helper for safeasyncio.run. Users never import or call it._logging.py— private internal helper that namespacespraisonai.*loggers and stops library code mutating the root logger. Only worth a one-line mention in the changelog if one exists.If an existing docs page tells users to call
logging.basicConfig(...)to control PraisonAI log output, update it to recommend setting theLOGLEVELenv var orlogging.getLogger("praisonai").setLevel(...)instead, since library code no longer touches the root logger.