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.
Ask a running gateway to finish in-flight turns and exit — without exposing any inbound port, and without a left-over signal wedging a restarted instance. The user drops a drain marker file; the gateway finishes in-flight turns and exits without exposing an inbound drain port.

Quick Start

1

Import the policy and epoch function

2

Build the policy once at startup

3

Run a watcher loop

The built-in marker watcher and praisonai gateway drain CLI are not yet merged — write your own watcher loop for now (pattern above). This page will be updated when the follow-up PR ships.

How It Works

Restart-Safety Story

The entire point of this feature: a marker stamped with current_epoch() is silently ignored by any other instance of the gateway — even if the marker file survives a reboot on a durable volume.

Decision Tree — When Is a Marker Honoured?


The Drain Marker Contract

Write this JSON to the marker path:
  • Default marker path (convention from PraisonAI #2390, not yet enforced in code): ~/.praisonai/gateway/.drain_request.json
  • action defaults to "drain" if absent. Any other value (including a non-string) is ignored.
  • Missing / empty / non-string epoch is ignored unless require_epoch=False is passed to the policy.

Configuration Options

DrainMarkerPolicy constructor

DrainMarkerPolicy.drain_requested() parameters

current_epoch() — what it returns


Common Patterns

1. Operator-side: write the marker

Writing to <path>.tmp then os.replace() makes the write atomic — a half-written JSON file is treated as malformed and ignored.

2. Gateway-side: minimal watcher loop

3. Accepting legacy markers without an epoch (advanced)

Only do this if you own both ends and have a different staleness story.

Best Practices

The whole restart-safety guarantee depends on it. Leave require_epoch=True (the default). An unstamped marker is silently ignored — this is intentional and protects newly started instances from stale files.
Write to <path>.tmp then os.replace() — a half-written JSON file is parsed as malformed and ignored, leaving the previous request still active. Atomic rename is the only safe pattern on most filesystems.
DrainMarkerPolicy only decides when to drain; the actual bounded wait still goes through gateway.stop(drain_timeout=...) documented on the Session Continuity page. Without a drain_timeout, shutdown cancels in-flight turns immediately.
The epoch is non-secret and opaque. Treat the marker file as world-readable convention metadata, not a control-plane secret. Anyone who can write to the marker path can trigger a drain.

The praisonai gateway drain CLI command and the built-in marker watcher in gateway/server.py are mentioned as the wrapper-side companions to this predicate in PraisonAI #2390 but are not yet merged. Until they land, the predicate is consumed by writing your own watcher (pattern 2 above). This page will be updated to document the CLI + YAML gateway.drain block when the follow-up PR ships.

Scale to Zero

ScaleToZeroPolicy — sibling idle-policy predicate

Session Continuity

drain_timeout and in-process drain

Bot Gateway

Bot Gateway overview

Gateway

Gateway and Control Plane top-level page