Gateway Reliability Preset

One switch that composes graceful drain + admission control for the bot gateway

A BotOS(agent=..., ...) or praisonai gateway start with no reliability= argument is now safe by default — the gateway picks a bounded admission ceiling, a fair wait queue, strict outbound ordering, and a drain window sized to the bind (loopback → 5s, real interface → 15s). The reliability= preset is still there for callers who want to override that.

python
from praisonaiagents import Agent
from praisonai_bot.bots.botos import BotOS

agent = Agent(name="assistant", instructions="Help the user.")

# Safe by default: admission ceiling + fair queue + drain, bind-aware.
bot = BotOS(agent=agent, platforms=["telegram", "discord"])
bot.start()
Diagram

None

production

default

off

loopback / localhost / 127.x / ::1

0.0.0.0 / real interface / hostname

reliability=

bind_host

15s drain + admission + fair queue + strict

5s drain, no admission, best-effort

0s drain, no admission, best-effort

5s drain + admission + fair queue + strict

15s drain + admission + fair queue + strict

Quick Start

  1. Simplest — safe by default

    No reliability= needed. The gateway resolves admission, a fair queue, strict ordering, and a bind-aware drain:

    python
    from praisonaiagents import Agent
    from praisonai_bot.bots.botos import BotOS
    
    agent = Agent(name="assistant", instructions="Help the user.")
    
    # Safe by default: admission ceiling + fair queue + drain, bind-aware.
    bot = BotOS(agent=agent, platforms=["telegram", "discord"])
    bot.start()
  2. Force the full production window even on loopback
    python
    bot = BotOS(
        agent=agent,
        platforms=["telegram", "discord"],
        reliability="production",  # 15s drain regardless of bind
    )
  3. Explicit opt-out (revert to pre-#3438 immediate teardown)
    python
    bot = BotOS(
        agent=agent,
        platforms=["telegram", "discord"],
        reliability="off",  # no drain, no admission — you asked for it
    )
  4. YAML — set reliability: at the top level
    yaml
    # gateway.yaml
    reliability: production
    
    agents:
      assistant:
        instructions: "Help the user."
    
    channels:
      telegram:
        token: "${TELEGRAM_TOKEN}"

    Run with:

    bash
    praisonai gateway start --config gateway.yaml
  5. CLI flag — override any YAML value
    bash
    praisonai gateway start --config gateway.yaml --reliability production

    The CLI flag takes the highest precedence and overrides whatever is in the YAML file.

  6. Override individual settings after the preset

    Explicit kwargs on BotOS always win over the preset:

    python
    from praisonaiagents import Agent
    from praisonai_bot.bots.botos import BotOS
    
    agent = Agent(name="assistant", instructions="Help the user.")
    
    bot = BotOS(
        agent=agent,
        platforms=["telegram"],
        reliability="production",
        drain_timeout=30.0,   # overrides the preset's 15 s
    )
    bot.start()

Profiles

Four distinct postures. The unset posture is bind-aware, so it appears twice.

PresetDrainAdmission ceilingWait queueOutbound orderingWhen to use
Unset (None, loopback bind)5 sYes (CPU-scaled)Yes (bounded, fair)strictLocal dev on 127.0.0.1 / localhost
Unset (None, non-loopback bind)15 sYes (CPU-scaled)Yes (bounded, fair)strictAn actual deployment (0.0.0.0, real hostname)
"production"15 sYes (CPU-scaled)Yes (bounded, fair)strictPin the production window regardless of bind
"default"5 sNoNobest_effortExplicit legacy posture — the pre-#3438 shape
"off"0 sNoNobest_effortExplicit opt-out — immediate teardown, no backpressure

The safe posture (unset) and production both enable strict per-conversation FIFO delivery on the outbox — see Outbound Ordering. "default" and "off" keep best_effort for backward compatibility.


How It Works

Diagram
WebSocketGatewayBotOS.__init___reliability resolverCLI / Python / YAMLWebSocketGatewayBotOS.__init___reliability resolverCLI / Python / YAMLExplicit kwargs override resolver valuesreliability=”production”drain_timeout=15, max_concurrent_runs=<cpu-scaled>, admission_policy=queueBuild gateway with resolved settingsRunning

The resolver _reliability.py converts the profile string into concrete values for drain_timeout, max_concurrent_runs, and admission_policy. Those values are passed directly to the underlying WebSocketGateway build step.

Precedence (highest → lowest):

  1. Explicit kwargs on BotOS.__init__ — e.g. drain_timeout=30, outbound_ordering="strict"
  2. reliability= preset — e.g. "production"
  3. SDK defaults

outbound_ordering= is also an explicit kwarg that overrides the preset. Passing outbound_ordering="strict" (or "best_effort") always wins over the profile’s choice; unknown values raise ValueError at resolve time.


Configuration Surfaces

Python

python
from praisonai_bot.bots.botos import BotOS

# Minimal — safe by default, no reliability= needed
bot = BotOS(agent=agent, platforms=["telegram"])

# From a YAML config file (reads top-level `reliability:` or `gateway.reliability`)
bot = BotOS.from_config("gateway.yaml")

YAML

Both placements are accepted:

yaml
# Top-level
reliability: production

# Or nested under gateway:
gateway:
  reliability: production
  max_concurrent_runs: 8   # explicit override still respected

CLI

bash
praisonai gateway start --config gateway.yaml --reliability production
praisonai gateway start --config gateway.yaml --reliability off
praisonai gateway start --config gateway.yaml --reliability default

Common Patterns

Production deployment

A non-loopback bind auto-selects the full production window — no reliability= argument needed:

python
from praisonaiagents import Agent
from praisonai_bot.bots.botos import BotOS

agent = Agent(name="support", instructions="Answer customer questions.")
bot = BotOS(
    agent=agent,
    platforms=["telegram", "discord", "slack"],
)
bot.start()  # bound to a real interface → 15s drain + admission + fair queue

Extend the drain window for slow agents

python
bot = BotOS(
    agent=agent,
    platforms=["telegram"],
    reliability="production",
    drain_timeout=45.0,   # 45s instead of preset 15s
)

Production preset with per-thread ordering

The production preset enables strict ordering; pass a custom lane_key to order sends within a shared channel:

python
from praisonaiagents import Agent
from praisonai.bots import BotOS

agent = Agent(name="support", instructions="Answer customer questions.")
bot = BotOS(agent=agent, platforms=["slack"], reliability="production")

# Later, when enqueuing on the outbox, group by thread:
await bot.outbox.enqueue(
    idempotency_key=f"reply-{msg_id}",
    target="slack:C0123456",
    payload={"text": reply},
    lane_key=f"slack:C0123456:thread:{thread_ts}",
)

Disable all backpressure for development

yaml
reliability: off

Best Practices

Recommended: pass nothing — the unset posture is now production-safe

On a non-loopback bind the unset posture is equivalent to production — same admission ceiling, fair queue, strict ordering, and 15 s drain. Most operators don’t need to pass anything. Use reliability="production" only to pin the 15 s window even on a loopback bind.

I want the pre-3438 behaviour back

Pass reliability="off" for no drain and no admission, or reliability="default" for a 5 s drain with no admission ceiling. Neither is a recommended default — they exist for callers who explicitly want the pre-#3438 shape.

Never mix reliability= with manual drain/admission in YAML unless intentional

Explicit YAML keys like gateway.drain_timeout override the preset. That is correct behaviour when you need to tune a single value, but it can surprise you if you forget the preset was set.

Unknown profile names raise immediately — do not catch the error

An unrecognised profile (e.g. reliability: "fast") raises at startup, not at first request. This fail-fast behaviour is intentional — silent fallback to default would hide misconfiguration.

Use –reliability CLI flag for canary deployments

Deploying a new preset to a single pod via the CLI flag lets you validate behaviour before updating the shared gateway.yaml.


Related