Gateway Admin API

Repair and provision a PraisonAI gateway config from Python — non-interactive, typed, and CI-friendly

Repair and provision a gateway config from Python — no shell-out, no interactive wizard, and a typed result you can assert on.

Diagram

🔧 repair_gateway_config

🩺 Repair lifecycle
detect → repair → re-validate

📦 provision_gateway_config

✅ GatewayRepairResult

Quick Start

  1. Repair a broken config
    python
    from praisonai_bot import repair_gateway_config
    
    result = repair_gateway_config("~/.praisonai/bot.yaml", fix=True)
    assert result.config_version_migrated is True or result.auth_token_minted is True
    assert not result.remaining_degraded_owners
  2. Provision a config from scratch
    python
    from praisonai_bot import provision_gateway_config
    
    path = provision_gateway_config(
        platform="telegram",
        token="${TELEGRAM_BOT_TOKEN}",   # persisted to ~/.praisonai/.env
        agents=["assistant"],
    )
    print(path)   # ~/.praisonai/bot.yaml
  3. Detect without repairing
    python
    result = repair_gateway_config("~/.praisonai/bot.yaml")   # fix=False by default
    for owner in result.remaining_degraded_owners:
        print(owner["owner_id"], "->", owner["reason"])

How It Works

Both entry points share the detect → repair → re-validate lifecycle behind praisonai gateway doctor --fix.

Diagram
~/.praisonai/.envgateway.yamlHealthRegistryrepair_gateway_configUser~/.praisonai/.envgateway.yamlHealthRegistryrepair_gateway_configUseralt[config out of date]alt[weak/missing token]repair_gateway_config(path, fix=True)run(config_path, fix, dry_run)detect config_version driftdetect weak/missing auth_tokenmigrate + stamp config_version (atomic write)mint strong token (0600)rewrite pinned weak token if presentre-validate findingsresults + residual findingsGatewayRepairResult

When to use which

Diagram

Fix a broken config

Just report what is wrong

Preview a repair

Create a config from scratch

Add, update, disable, or remove one channel

What do you need?

repair_gateway_config
fix=True

repair_gateway_config
fix=False

repair_gateway_config
fix=True, dry_run=True

provision_gateway_config

edit_gateway_channel


API Reference

Four symbols make up the whole public surface.

python
from praisonai_bot import (
    repair_gateway_config,
    provision_gateway_config,
    edit_gateway_channel,
    GatewayRepairResult,
)

repair_gateway_config

repair_gateway_config(config_path, *, fix=False, dry_run=False) -> GatewayRepairResult

ParameterTypeDefaultDescription
config_path`str \os.PathLike[str]`—Path to the gateway bot.yaml / gateway.yaml. ~ is expanded.
fixboolFalseApply safe repairs. Leave False for a detect-only report.
dry_runboolFalseWith fix=True, preview repairs without writing.

Runs the same detect → repair → re-validate lifecycle as praisonai gateway doctor --fix: forward-migrate an out-of-date config_version and mint/persist a strong gateway.auth_token when the configured one is weak or missing.

provision_gateway_config

provision_gateway_config(*, platform, token, agents=None, config_path=None) -> Path

ParameterTypeDefaultDescription
platformstr—Channel platform, e.g. "telegram". Must be a supported built-in / installed channel.
tokenstr—Channel token; persisted to ~/.praisonai/.env. Empty string raises ValueError.
agents`list[str] \None`None → ["assistant"]Agent names declared in agents:. The first is the channel’s default route.
config_path`str \os.PathLike[str] \None`None → ~/.praisonai/bot.yamlTarget path.

edit_gateway_channel

edit_gateway_channel(config_path, name, settings=None, *, remove=False) -> dict

Add, update, or remove one channels: entry in place. Other channels and top-level keys are untouched, and the edited document is validated against GatewayConfigSchema before the atomic write, so an invalid edit is rejected rather than persisted.

ParameterTypeDefaultDescription
config_path`str \os.PathLike[str]`—Path to bot.yaml / gateway.yaml.
namestr—Channel name.
settings`dict \None`NoneFields merged into channels[name]. platform defaults to name. Pass {"enabled": False} to disable. Ignored when remove=True.
removebool (keyword-only)FalseDelete the channel block instead of upserting it.

Returns the resulting channel block ({} when remove=True). Raises FileNotFoundError, KeyError (removing a missing channel), or ValueError (unknown platform, bad types, or no enabled channel left).

GatewayRepairResult

@dataclass(frozen=True) — the closed result shape returned by repair_gateway_config.

FieldTypeDefaultDescription
auth_token_mintedboolFalseSet when a strong gateway.auth_token was minted and persisted.
config_version_migratedboolFalseSet when config_version was forward-migrated.
changeslist[str][]Operator-facing lines describing what was repaired.
remaining_degraded_ownerslist[dict[str, str]][]Redacted {owner_kind, owner_id, state, reason, retry_hint} dicts. Empty on a clean verify.

.to_dict() returns a shallow JSON-safe copy of all four fields.

python
result = repair_gateway_config("~/.praisonai/bot.yaml", fix=True)
print(result.to_dict())

Precedence & Fallbacks

The auth-token repair interacts with ${ENV} references and explicit YAML tokens as follows.

SituationBehaviour
gateway.yaml pins a weak literal auth_tokenRepair rewrites the YAML and the env var.
auth_token is a ${ENV} referenceNot rewritten — operator indirection is preserved; only ~/.praisonai/.env is written.
Weak token on a loopback bindWarning to stderr, no error; remaining_degraded_owners stays empty.
Weak token on an external bindFail-closed finding; fix=True mints a strong token.
Config from a newer build than the installed coreReported once as unsupported; the migrator does not downgrade.

CLI parity

The Python API, CLI, and YAML surfaces run the same helpers.

What you wantPythonCLIYAML
Detect onlyrepair_gateway_config(path)praisonai gateway doctor(n/a — inspection command)
Detect + repairrepair_gateway_config(path, fix=True)praisonai gateway doctor --fix(n/a — inspection command)
Preview a repairrepair_gateway_config(path, fix=True, dry_run=True)praisonai gateway doctor --fix --dry-run(n/a)
Provision a configprovision_gateway_config(platform=..., token=..., agents=[...])praisonai onboard (interactive)ships as bot.yaml
Add / update / remove one channeledit_gateway_channel(path, "telegram", {...})praisonai gateway channels {add,update,disable,remove}edits channels: in place

Common Patterns

CI-driven per-tenant provisioning

python
from praisonai_bot import provision_gateway_config, repair_gateway_config

tenants = {
    "acme": "${ACME_TELEGRAM_TOKEN}",
    "globex": "${GLOBEX_TELEGRAM_TOKEN}",
}

for tenant, token in tenants.items():
    path = provision_gateway_config(
        platform="telegram",
        token=token,
        agents=["assistant"],
        config_path=f"/etc/praisonai/{tenant}/bot.yaml",
    )
    result = repair_gateway_config(path, fix=True)
    assert not result.remaining_degraded_owners, (tenant, result.remaining_degraded_owners)

Post-deploy self-healing check

python
import sys
from praisonai_bot import repair_gateway_config

result = repair_gateway_config("~/.praisonai/bot.yaml", fix=False)
if result.remaining_degraded_owners:
    for owner in result.remaining_degraded_owners:
        print(owner["owner_id"], "->", owner["reason"], file=sys.stderr)
    sys.exit(1)

Testing the fixed gateway in pytest

python
from praisonai_bot import repair_gateway_config

def test_gateway_self_heals(tmp_path):
    config = tmp_path / "bot.yaml"
    config.write_text("gateway:\n  auth_token: changeme\n  bind_host: 0.0.0.0\n")

    result = repair_gateway_config(config, fix=True)

    assert result.auth_token_minted or result.config_version_migrated
    assert not result.remaining_degraded_owners

Explicit path vs default location

python
from praisonai_bot import provision_gateway_config

# Default location: ~/.praisonai/bot.yaml
default_path = provision_gateway_config(platform="telegram", token="${TELEGRAM_BOT_TOKEN}")

# Explicit override
custom_path = provision_gateway_config(
    platform="telegram",
    token="${TELEGRAM_BOT_TOKEN}",
    config_path="/etc/praisonai/bot.yaml",
)

Best Practices

🧪 Verify with the detect pass first

Run without fix=True, review remaining_degraded_owners, then re-run with fix=True. A detect-only pass never writes to disk.

🔁 Re-run after every deploy

Config-version drift and weak tokens are silent until you check. Wire repair_gateway_config(path, fix=False) into your post-deploy smoke test.

🔒 Never commit the token

provision_gateway_config(token=...) persists the credential to ~/.praisonai/.env (0600). Pass a ${VAR} reference in your YAML so the secret stays out of source control.

🧭 Keep the CLI and Python in sync

Both surfaces run the same helpers in admin.py — a repair from either is identical. Use the CLI interactively, the Python API in CI and tests.

🛑 Treat ValueError as fail-closed

An unsupported platform or empty token refuses to write, preventing a “starts degraded” outcome. Do not catch and ignore it.


Related