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.Quick Start
Simplest setup — 5-minute idle timeout
_on_quiesce hook (if set). The next POST /_wake brings it back.How It Works
Key behaviours:| Behaviour | Detail |
|---|---|
| Evaluation tick | Every 30 seconds — lightweight, zero LLM calls |
| Guard 1 — in-flight turns | running_turns > 0 blocks dormancy; a message being processed can never be dropped |
| Guard 2 — background work | Any enabled scheduled job keeps the gateway resident |
| Guard 3 — idle timeout | elapsed < idle_timeout_seconds blocks dormancy |
| Arm gating | should_arm returns False when wake_url=None — the policy logs and stays always-on rather than quiescing into an unrecoverable state |
| Wake idempotency | wake() is a no-op when the gateway is already running |
Configuration Options
ScaleToZeroPolicy constructor
| Option | Type | Default | Description |
|---|---|---|---|
idle_timeout_minutes | float | 5.0 | Minutes of inbound silence before quiescing. Must be > 0 — raises ValueError on 0 or negative. |
wake_url | Optional[str] | None | The HTTP endpoint your compute host will POST to wake the gateway. Required to arm — without it the policy refuses to arm and the gateway stays always-on. |
enabled | bool | True | When False, is_idle always returns idle=False and should_arm returns False. Useful for env-var-driven kill switches. |
| Property | Type | Description |
|---|---|---|
idle_timeout_seconds | float | idle_timeout_minutes * 60 — the value is_idle checks against elapsed time. |
BotOS — idle policy field
| Field | Type | Default | Description |
|---|---|---|---|
idle_policy | Optional[GatewayIdlePolicyProtocol] | None | When set, BotOS schedules an idle-dormancy loop that ticks every 30 s and quiesces when the policy says so. Default None = always-on (unchanged behaviour). |
BotOS runtime activity hooks
| Method | Description |
|---|---|
notify_inbound() | Stamp _last_inbound_ts. Optional explicit hook — the idle loop also passively probes session managers. |
turn_started() | Increment in-flight turn counter (blocks dormancy). |
turn_finished() | Decrement in-flight turn counter. |
wake() (async) | Idempotent resume — reconnects transports. Call from your wake endpoint handler. |
Imports
These names export from
praisonaiagents.gateway. Top-level praisonaiagents does not re-export them. BotOS itself imports from praisonai.bots.Common Patterns
Fly Machines auto-suspend
/_wake route in your web framework calls await botos.wake(), which reconnects all transports and the gateway is live again within seconds.
Env-var kill switch
SCALE_TO_ZERO=1 in production. In dev, leave it unset — the policy stays disabled and the gateway runs always-on with zero overhead.
Tighter timeout for prototype bots
1 minute for disposable demo bots. Bump to 5+ minutes for production where users expect instant responses.
Best Practices
Always set wake_url before deploying
Always set wake_url before deploying
Without a
wake_url, should_arm returns False and the gateway logs "idle policy not armed (no wake path); staying always-on". This is intentional — the policy refuses to quiesce into a state it cannot recover from. Set wake_url to the URL your compute host will POST to when a new inbound message arrives.Keep idle_timeout_minutes ≥ 2 for chat bots
Keep idle_timeout_minutes ≥ 2 for chat bots
Humans pause between messages in the same conversation — typing, thinking, copy-pasting. A timeout under 2 minutes can spin transports down mid-conversation, adding a cold-start delay the user will feel. Start at 5 minutes for interactive bots and tune down once you have usage data.
Wire _on_quiesce after testing your wake path
Wire _on_quiesce after testing your wake path
Test that
curl -X POST https://your-bot.example.com/_wake successfully brings the bot back before you wire _on_quiesce to actually suspend the host. That way you can recover from a broken suspend hook without needing to redeploy.Don't disable scheduled jobs to force idle
Don't disable scheduled jobs to force idle
The policy already blocks dormancy whenever any enabled scheduled job exists. If you want true scale-to-zero, audit
praisonai schedule list and disable jobs that should not keep the bot resident. Never rely on a long timeout to “outlast” a scheduled job — the job will prevent quiescing for as long as it is enabled.Related
Gateway Overview
The gateway architecture this feature layers on top of.
Session Continuity
Sessions survive the suspend — what makes resume after wake work.
BotOS
The multi-platform orchestrator that hosts the idle policy.
Bot Gateway
Run multiple bots from a single gateway server.

