Quick Start
Default-Deny Allowlist
Permit only specific targets — everything else is blocked.The agent can only send to
origin (the conversation it came from) or the ops-alerts alias. Any other target returns a clean denial string instead of delivering.Default-Allow with Denylist
Allow everything except specific channels you want to protect.The agent can send to any target except the protected executive channels.
How It Works
Denial is model-readable. A well-instructed agent reads the failure string and recovers gracefully — for example, routing to an allowed channel or asking the user to confirm before proceeding.
| Component | Role |
|---|---|
| SendPolicy | Config-driven allow/deny evaluator registered per turn |
| SendPolicyProtocol | Interface for custom policy back-ends (RBAC, time-windows, audit) |
| SendDecision | Immutable result from evaluate() — allow bool + optional reason |
| send_message tool | Checks the active policy before invoking the messenger |
praisonaiagents), so every messenger implementation is constrained — not just one adapter. Absent a policy, all sends are allowed (backwards compatible).
Configuration Options
SendPolicy
Import: from praisonaiagents.gateway.protocols import SendPolicy
| Argument | Type | Default | Description |
|---|---|---|---|
default | str | "allow" | Posture for targets not listed. "deny" blocks all except allow list; "allow" permits all except deny list. |
allow | list[str] | None | None | Targets explicitly permitted. Active allowlist when default="deny". |
deny | list[str] | None | None | Targets explicitly blocked. Takes precedence over allow. |
"origin", "slack:#ops", a friendly alias). Passing any value other than "allow" or "deny" for default raises ValueError at construction time.
SendDecision
Import: from praisonaiagents.gateway.protocols import SendDecision
| Field | Type | Default | Description |
|---|---|---|---|
allow | bool | — | True if the send is permitted; False blocks it. |
reason | str | "" | Optional explanation shown to the model when denied. |
SendDecision is a frozen dataclass — immutable once created.
SendPolicyProtocol
Import: from praisonaiagents.gateway.protocols import SendPolicyProtocol
SessionContext.
Common Patterns
Default-Deny Allowlist (Production)
Safest posture: only explicitly listed targets can receive messages.Default-Allow with Denylist
Lighter-weight for trusted environments where you only want to protect a few channels.Custom Protocol — Time-Window Restriction
SendPolicy:
Custom Protocol — Per-Agent RBAC
Threat Model
Concretely:- Prompt injection in a retrieved document instructs the agent to
send_message("slack:#exec", "<sensitive data>"). - Without a send policy, the message is delivered.
- With
SendPolicy(default="deny", allow=["origin"]), the call fails with a clean denial string. The agent reads it, cannot comply, and the data stays contained.
Best Practices
Prefer default='deny' for production deployments
Prefer default='deny' for production deployments
Start with the most restrictive posture and explicitly list every channel the agent legitimately needs. This gives you a clear audit trail and prevents unexpected delivery as new channels are added.
Always include 'origin' in the allowlist
Always include 'origin' in the allowlist
Unless you specifically want to prevent the agent from replying to the conversation it came from, include
"origin" in the allow list. Without it, default="deny" will block even simple replies.Keep policies in version control alongside gateway.yaml
Keep policies in version control alongside gateway.yaml
Whether you use Python or YAML config, commit your send policy alongside the rest of your gateway configuration. This ensures policy changes go through code review and are tracked in history.
Use SendPolicyProtocol for dynamic rules
Use SendPolicyProtocol for dynamic rules
If your rules depend on runtime state (user roles, time of day, session metadata), implement
SendPolicyProtocol rather than rebuilding a SendPolicy instance per request. The agent_id, session_id, and origin kwargs give you the context you need.Behaviour Reference
| Scenario | Result |
|---|---|
| No policy registered | All sends permitted (backwards-compatible) |
default="deny", target not in allow | Blocked — "Failed to send to <target>: target '<target>' is not permitted by send_policy" |
default="allow", target in deny | Blocked — same format |
Target in both allow and deny | deny takes precedence — blocked |
action="list" | Always allowed — policy does not affect target listing |
Policy .evaluate() raises an exception | Fails closed — send blocked, "send_policy evaluation error" |
Policy returns something other than SendDecision | Fails closed — treated as denial |
Related
Send Message Tool
Let agents proactively deliver messages to users mid-task.
Messaging Bots
Deploy AI agents to Telegram, Discord, Slack, and WhatsApp.
Bot Rate Limiting
Throttle how often agents can respond per user or channel.
Guardrails
Add input and output safety checks to your agents.

