Skip to content

docs: Document unified ApprovalSpec for YAML/CLI/Python approval config (PraisonAI PR #1457) #181

@MervinPraison

Description

@MervinPraison

Source Change

PraisonAI PR #1457fix: 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

  • docs/features/approval.mdx opens with the new agent-centric approval=True / approval="<backend>" / approval={...} Quick Start.
  • All seven ApprovalSpec fields documented with type, default, and one-line description matching the SDK source exactly.
  • All shorthand YAML forms (true, false, null, string) shown.
  • Validation behaviour (unknown keys → ValueError) called out.
  • CLI ⇄ YAML ⇄ Python mapping table present.
  • Hero Mermaid diagram + sequence diagram added per AGENTS.md §3.
  • No edits to docs/concepts/approval.mdx (human-only folder per AGENTS.md §1.8).
  • docs/cli/tool-approval.mdx updated with YAML section and validation note.
  • Legacy aliases (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 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingclaudeTrigger Claude Code analysisdocumentationImprovements or additions to documentationenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions