Skip to main content
The gateway now ships in the praisonai-bot package. praisonai serve gateway still works exactly as documented here; for a standalone install see praisonai-bot Migration.
Untrusted inbound routes never even see dangerous tools — the model is offered a scoped subset for that turn, then the agent’s original toolset is restored.
from praisonaiagents import Agent

agent = Agent(name="assistant", tools=["read_file", "search_web"])
# Gateway bindings with trust: untrusted scope which tools the model sees per route
The user asks the agent to run tools; gateway tool policy allows or blocks tools before execution.

Quick Start

1

Lock down stranger DMs with one YAML line

Add trust: untrusted to any binding. Dangerous tools (shell, file mutation, delegation, scheduling) are automatically withheld from the model for that route.
gateway:
  routes:
    - { chat_type: dm, agent: assistant, trust: untrusted }
2

Give your operator full power

from praisonaiagents import Agent
from praisonaiagents.gateway import RouteBinding

assistant = Agent(name="assistant", instructions="Help users.")

bindings = [
    RouteBinding(agent="assistant", chat_type="dm", trust="untrusted"),
    RouteBinding(agent="assistant", peer="operator-123", trust="trusted"),
]
Stranger DMs get the safe subset. Your operator peer gets everything.
3

Add explicit allow/deny overrides

from praisonaiagents.gateway import RouteBinding

RouteBinding(
    agent="assistant",
    channel_id="ops",
    deny_tools=["shell", "delete_file"],
)
Layer deny_tools on top of any trust tier for project-specific tools not covered by the default substrings.

How It Works

The apply/restore step happens inside the per-agent lock and is guaranteed to run even when the agent turn raises an exception — so a failed run can never leave an agent permanently hobbled.
StepWhat happens
Route resolverMatches the binding with highest priority + specificity
tool_policy()Builds a ToolPolicy from trust, allow_tools, deny_tools
_apply_tool_policy()Swaps agent.tools to the allowed subset for this turn
Agent turnModel only sees the scoped tool list
Restoreagent.tools reset to original regardless of outcome

Configuration Options

RouteBinding security fields

For routing fields (peer, role, channel_id, account, chat_type, priority) see Gateway Route Bindings.
FieldTypeDefaultDescription
trustOptional[str]None"untrusted" | "standard" | "trusted". Unknown values normalise to "untrusted" (fail-closed).
allow_toolsOptional[List[str]]NoneWhitelist by exact tool name. None = allow all except deny rules. Accepts a YAML scalar or list.
deny_toolsOptional[List[str]]NoneExact tool names removed before the run. Layers on top of the trust tier’s deny-list. Accepts a YAML scalar or list.

ToolPolicy dataclass

FieldTypeDefaultDescription
allow_toolsOptional[Set[str]]NoneWhitelist by exact name. None = allow all except deny rules.
deny_toolsSet[str]set()Exact names removed.
deny_substringsList[str][]Case-insensitive substrings; a tool whose name contains any of these is removed. Used by the untrusted tier.

Module constants

ConstantTypeDescription
UNTRUSTED_DENY_SUBSTRINGSList[str]The 12 substrings the untrusted tier seeds: shell, exec, command, subprocess, write_file, edit_file, delete_file, rm_file, delegate, handoff, cronjob, schedule.
TRUST_TIERSList[str]["untrusted", "standard", "trusted"] (least → most privileged).
Import from praisonaiagents.gateway:
from praisonaiagents.gateway import (
    RouteBinding, ToolPolicy, TRUST_TIERS, UNTRUSTED_DENY_SUBSTRINGS,
)

Common Patterns

Lock down stranger DMs, keep operator at full power
from praisonaiagents import Agent
from praisonaiagents.gateway import RouteBinding

assistant = Agent(name="assistant", instructions="Help users.")

bindings = [
    RouteBinding(agent="assistant", chat_type="dm", trust="untrusted"),
    RouteBinding(agent="assistant", peer="operator-123", trust="trusted"),
]
Or in YAML:
gateway:
  routes:
    - { chat_type: dm, agent: assistant, trust: untrusted }
    - { peer: "operator-123", agent: assistant, trust: trusted }
Channel-scoped policy — deny specific tools on #ops
from praisonaiagents.gateway import RouteBinding

RouteBinding(
    agent="assistant",
    channel_id="ops",
    deny_tools=["shell", "delete_file"],
)
Whitelist mode — only search on a public-facing route
from praisonaiagents.gateway import RouteBinding

RouteBinding(
    agent="assistant",
    chat_type="group",
    allow_tools=["search"],
)
Only the search tool is offered. Everything else is withheld.

Best Practices

Opt in to power, not out of safety. Add trust: untrusted to every new route you create; promote to standard or trusted only when you have a clear need.
gateway:
  routes:
    - { chat_type: dm, agent: assistant, trust: untrusted }   # safe by default
UNTRUSTED_DENY_SUBSTRINGS covers the 12 common dangerous families. Custom tools with names like purge_cache or flush_queue won’t match any substring — add them explicitly.
RouteBinding(
    agent="assistant",
    chat_type="dm",
    trust="untrusted",
    deny_tools=["purge_cache", "flush_queue"],
)
Pair trust: trusted (or omit trust) with your operator’s stable peer: id. If you put an operator peer on untrusted, they will hit the conservative deny-list on every message.
bindings:
  - { peer: "operator-123", agent: assistant }          # trusted by default (no trust field)
  - { chat_type: dm, agent: assistant, trust: untrusted }   # everyone else
Import the constant and check your tool names against it before deploying:
from praisonaiagents.gateway import UNTRUSTED_DENY_SUBSTRINGS

my_tools = ["search_web", "read_file", "send_email", "run_python"]
for tool in my_tools:
    blocked = any(sub in tool.lower() for sub in UNTRUSTED_DENY_SUBSTRINGS)
    print(f"{tool}: {'BLOCKED on untrusted' if blocked else 'allowed'}")
Anything that bypasses the 12 substrings will leak through trust: untrusted unless you add an explicit deny_tools entry.

Gateway Route Bindings

The routing surface this layers on — match by peer, role, channel, or chat type.

Approval

The second line of defence — require human confirmation before risky tool calls execute.