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.retry_after_seconds hint when they exceed it.
How It Works
Quick Start
Wire Response
Alimited decision maps to ConnectErrorCode.RATE_LIMITED on the handshake wire:
retry_after_seconds and back off before reconnecting. This keeps retry storms from amplifying the load that triggered limiting in the first place.
SlidingWindowRateLimitPolicy Reference
| Parameter | Type | Default | Description |
|---|---|---|---|
max_requests | int | 0 | Maximum requests per window. 0 disables limiting — every request is allowed (legacy always-allow behaviour). |
window_seconds | float | 60.0 | Rolling window duration in seconds. Must be > 0. |
lockout_seconds | float | 0.0 | Cooldown after exceeding the ceiling. 0 means no cooldown — the key is denied until the window expires naturally. |
RateLimitDecision Fields
RateLimitDecision is a frozen dataclass — immutable by design so it can be safely returned across threads.
| Field | Type | Description |
|---|---|---|
allowed | bool | Whether the request may proceed |
retry_after_seconds | float | None | Backoff hint when allowed=False; None when allowed |
RateLimitDecision is frozen (@dataclass(frozen=True)). Never try to mutate it — create a new instance instead.Bring Your Own Limiter
ImplementRateLimitPolicyProtocol for per-tenant, distributed, or cost-based limiting:
RateLimitPolicy is a backward-compatible alias for RateLimitPolicyProtocol. Both names import from praisonaiagents.gateway.The Gateway Policy Family
Rate limiting completes the gateway’s symmetric policy-protocol family:| Protocol | What it decides |
|---|---|
SendPolicyProtocol | Whether to send an outbound frame now |
GatewayIdlePolicyProtocol | Whether the gateway is idle enough to scale to zero |
GatewayDrainPolicyProtocol | Timing and order of graceful drain |
GatewayConcurrencyPolicyProtocol | Bound on concurrent in-flight turns |
RateLimitPolicyProtocol (new) | Bound on inbound request rate per identity/scope |
Best Practices
Start with the sliding-window default
Start with the sliding-window default
SlidingWindowRateLimitPolicy is dependency-free and covers the common case. Only inject a custom policy when you need per-tenant fairness, shared state (Redis), or cost-based limits.Use lockout_seconds for abusive clients
Use lockout_seconds for abusive clients
A 5-minute lockout after 5 exceeded requests in a minute prevents a script from hammering the gateway every 60 s. The
retry_after_seconds hint in the response lets well-behaved clients back off cleanly.Return realistic retry_after_seconds
Return realistic retry_after_seconds
Clients respect
retry_after_seconds. A hint of 0 invites immediate retry; a hint matching your actual window (window_seconds) gives the client a correct backoff. Use lockout_seconds when you want a longer penalty than the window naturally provides.Related
Gateway
WebSocket control plane — full YAML and Python reference
Reliability Preset
One-switch production posture (includes admission control)
Admission Control
Bound concurrent turns with a fair queue and overflow policy
Gateway Security
Operator authentication and scope-based access control

