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.
Migrate from Python: repair_gateway_config(path, fix=True).config_version_migrated — see Gateway Admin API.
PraisonAI auto-migrates legacy bot.yaml and BotOS platforms: configs to the canonical GatewayConfigSchema at load time — on both praisonai bot serve and praisonai gateway start — and praisonai doctor reports migration opportunities so you can persist them.
The user runs praisonai doctor; migration reports legacy bot.yaml or BotOS configs and normalises them to the gateway schema at load time.

How It Works

Quick Start

1

Detect legacy format

If your config is already canonical, you will see PASS — Config uses current format.
2

Review WARN output

Example when migration is available:
3

Persist canonical YAML

Rewrite your config to the canonical channels: form (see migration table below). At runtime, legacy shapes already load — persisting is optional but recommended for clarity.

Migration Table

Single-bot → multi-channel

Before (legacy bot.yaml):
After (canonical):

BotOS platforms:channels:

Before:
After:

String allowed_users → list

Before:
After:

Config version stamp

Gateway config now carries a canonical, integer config_version stamp. The runtime story is unchanged — the load-time shim still auto-migrates legacy shapes on every load — but the upgrade story is new: both praisonai gateway doctor --fix and praisonai gateway start apply the same declarative rule set, move an out-of-date config forward, and stamp the new version. start runs the gate before binding (PR #3884); doctor --fix runs it on demand.
Runtime load auto-migrates legacy shapes but does not write the stamp. The stamp is persisted to disk by praisonai gateway doctor --fix and — as of PR #3884 — by praisonai gateway start when it forward-migrates an out-of-date config before binding.
Import the public surface from praisonaiagents.gateway:

Rules currently in scope

GATEWAY_CONFIG_RULES holds two ordered migration steps.
Version safety. doctor refuses to downgrade a config written by a newer build — it never migrates a config whose stamp is newer than this build supports. A malformed stamp (true, "1", 1.0) is rejected as ConfigVersionError, not silently coerced.

Doctor-driven migration

praisonai gateway doctor inspects gateway.yaml and reports version drift; --fix applies the rules and stamps the file atomically. Two entry points now converge on the same version check and forward-migration path — doctor --fix and gateway start.

Start-time migration (new — PR #3884)

praisonai gateway start runs the same is_config_current check and migrate_config_with_doctor forward-migration before binding. If the stamped version is behind, start applies the same declarative rule set that doctor --fix uses. If the stamp is newer than this build supports (or malformed — bool / str / float), start refuses (ConfigVersionError, exit 78) rather than downgrading a config a newer build wrote. See Gateway CLI › Version validation.

Detection (no flag)

When the stamp is missing / stale, or any rule’s detect fires, doctor prints:
A newer or malformed stamp prints the error instead — doctor does not attempt to migrate:

--fix

--fix loads gateway.yaml, calls migrate_config_with_doctor, and rewrites the file atomically (tmpfile in the same dir + fsync + os.replace), so an interrupted --fix can never leave the file truncated. It prints one config: <reason> line per applied rule plus the version bump:

--fix --dry-run

Preview without writing — every line is prefixed with would:

JSON keys

--json adds these keys (alongside any existing ones):
If your installed praisonaiagents predates the migration API, doctor is a no-op for this check — the wrapper guards the import and logs no error. Upgrade praisonaiagents to get the config-version stamp.

At start time

praisonai gateway start runs the same config_version check doctor does — before binding — so start and doctor never disagree about whether a config is current. An out-of-date config is migrated forward in place; a config from a newer build (or with a malformed stamp) refuses to start rather than being downgraded. An out-of-date config migrates forward and prints the bump before binding:
A config written by a newer build refuses to start with exit 78:
Exit 78 (EX_CONFIG) is the do-not-restart contract the installed daemon units honour — a config from the future loops the daemon otherwise. See Gateway Exit Codes.
The start-time check runs against whichever config start resolved — including the auto-discovered ~/.praisonai/bot.yaml when --config is omitted. See Gateway Config Discovery.

Programmatic migration

Call migrate_config_with_doctor directly to migrate a config in memory — it copies the input (no mutation), applies the rules, and stamps the version. A second call returns applied == [] because it is idempotent.
is_config_current and migrate_config_with_doctor raise ConfigVersionError on a newer or malformed stamp — an older binary must never downgrade a config a newer build wrote. Catch it to surface a clear “upgrade this host” message.

Behaviour Notes

  • Load-time auto-migration of legacy shapes (channel-less BotOS, platforms:, CSV allowed_users) runs on both praisonai bot serve and praisonai gateway start — before PR #3019, only bot serve migrated.
  • Start-time config_version gate (new — PR #3884). praisonai gateway start now also runs the stamped config_version check + forward-migration rules that used to be doctor-only — before binding. This is separate from the load-time legacy-shape shim above: start applies the versioned rule set, not just the load-time auto-migration.
  • BotYamlSchema is an alias of GatewayConfigSchema — existing Python imports keep working.
  • group_policy defaults to mention_only for new channels without an explicit value. Configs that explicitly set respond_all keep that value.
  • observe is a newly-accepted group_policy value (PR #3381). Configs never migrate to observe automatically — set it explicitly. See observe: passive group context.
  • Comma-separated allowed_users strings are auto-converted to lists at load time.
  • All three YAML shapes (platform+token, agents+channels, platforms:) validate against one schema — see Gateway.
  • MultiChannelGatewayConfig and ChannelRouteConfig remain public exports — neither is deprecated. The config_version stamp does not retire them.
  • The --fix auto-repair also mints a strong gateway.auth_token when weak/missing, then re-validates — see Gateway CLI › Auto-repair and Pre-flight credential check.

Load-time validation of the gateway: block

Misspelled or wrong-typed keys under gateway: in gateway.yaml fail loudly at load time with the offending field named — no more silent-drop of settings you thought you’d overridden (#3050). Every gateway: sub-key is validated field-by-field via GatewayServerSchema (extra="forbid"), mirroring core’s typed praisonaiagents.gateway.config.GatewayConfig. The block itself stays a plain dict — downstream .get(...) access keeps working, so validation is fully backward-compatible.

What gets validated

Before / After

Before: validates fine; both settings silently ignored. After: rejected at load with a precise, field-named error:

Ranges worth knowing

A few common gateway: knobs carry constraints — a value outside the range fails at load with the field named:
The doc lists only the common knobs — see the SDK reference for the full, current field set rather than duplicating it here.

GatewayConfig SDK Reference

Full typed field list for the gateway server block

Best Practices

Use praisonai doctor --only gateway_config_migration after pulling a new PraisonAI release to see whether your persisted YAML can be simplified.
Runtime auto-migration is transparent, but persisting the canonical channels: form makes configs easier to diff and review in PRs.
group_policy defaults to mention_only for new channels only. If your bot should respond to every message, set respond_all explicitly rather than relying on legacy defaults.
Comma-separated strings still load, but list form is clearer and matches the schema validators.

Fleet Breaker

Stops fleet-wide reconnect storms when every channel restarts at once

Gateway

Full gateway and channel configuration reference

Config Discovery

Which config start and doctor resolve when --config is omitted

Exit Codes

Exit 78 — the do-not-restart contract for a config from a newer build