Gateway Windows Deployment

Complete guide for deploying PraisonAI Gateway on Windows with multi-channel bots

Diagram

Gateway Windows Deployment

📋 User Request

⚙️ Gateway Windows Deployment

✅ Result

Diagram
Gateway Windows DeploymentAgentUserGateway Windows DeploymentAgentUserRequestProcess requestResultResponse
python
from praisonaiagents import Agent

agent = Agent(name="windows-agent", instructions="Deploy the gateway on Windows.")
agent.start("Deploy and start the gateway service on Windows Server.")

Deploy the PraisonAI Gateway on Windows with multiple Telegram bots, proper encoding, and production-ready configuration.

bash
# After UTF-8 env setup (see below), start the gateway from your config
praisonai gateway start --config gateway.yaml

The user runs the gateway on Windows; deployment settings handle paths, services, and encoding.

Diagram

Gateway on Windows

📝 gateway start

⚙️ Load gateway.yaml

🌐 Gateway Process

🤖 Bot Agent

✅ Channel Reply

How It Works

Diagram
AgentGatewayWindowsUserAgentGatewayWindowsUserpraisonai gateway start –config gateway.yamlLaunch with UTF-8 envRoute inbound channel messageReply on Telegram / channel

Deployment Steps

Diagram
graph TB
    subgraph "Windows Environment Setup"
        subgraph "Step 1: Dependencies"
            PY[🐍 Python 3.9+]
            PKG[📦 praisonai[bot,api]]
            ENV[🔧 UTF-8 Environment]
        end

        subgraph "Step 2: Configuration"
            YML[📄 gateway.yaml]
            ENVF[🔐 .env file]
            TOK[🔑 Bot Tokens]
        end

        subgraph "Step 3: Deployment"
            GW[🌐 Gateway Process]
            HEALTH[💚 Health Check]
            LOGS[📋 Monitoring]
        end
    end

    PY --> PKG
    PKG --> ENV
    ENV --> YML
    YML --> ENVF
    ENVF --> TOK
    TOK --> GW
    GW --> HEALTH
    HEALTH --> LOGS

    classDef setup fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef config fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef deploy fill:#10B981,stroke:#7C90A0,color:#fff

    class PY,PKG,ENV setup
    class YML,ENVF,TOK config
    class GW,HEALTH,LOGS deploy

Quick Start

  1. Install Dependencies

    Install Python dependencies with both extras required for gateway:

    powershell
    pip install "praisonai[bot,api]"

    Why both extras are needed:

    ExtraProvidesRequired For
    [bot]python-telegram-bot, discord.py, slack SDKsPlatform integrations
    [api]uvicorn, fastapi, starletteGateway HTTP/WebSocket server
    [all]Both + search tools + storage backendsComplete installation

    Without [api] you’ll get:

    ImportError: Gateway requires starlette and uvicorn.
    Install with: pip install praisonai[api]
  2. Configure Windows UTF-8

    Mandatory for Windows gateway deployments:

    powershell
    $env:PYTHONUTF8 = "1"
    # Alternative:
    $env:PYTHONIOENCODING = "utf-8"

    Why this is required:

    Without UTF-8 configuration, you’ll see encoding errors:

    Error: 'charmap' codec can't encode character '\u26a0' in position 1: character maps to <undefined>

    This often appears after API failures (OpenAI 429 quota exceeded). Fix billing first, then encoding.

  3. Create Gateway Configuration

    Create gateway.yaml:

    yaml
    gateway:
      host: "127.0.0.1"
      port: 8765
    
    agents:
      assistant:
        model: gpt-4o-mini
        instructions: "You are a helpful AI assistant."
        tools: [search_knowledge]
    
    channels:
      telegram:
        platform: telegram
        token: ${TELEGRAM_BOT_TOKEN}
        routes:
          default: assistant

    Create .env file:

    env
    TELEGRAM_BOT_TOKEN=your_bot_token_here
    OPENAI_API_KEY=${OPENAI_API_KEY:?Set OPENAI_API_KEY in your shell}
    GATEWAY_AUTH_TOKEN=optional_auth_token
    PYTHONUTF8=1
  4. Start Gateway

    Launch the gateway with configuration:

    powershell
    praisonai gateway start --config gateway.yaml

    Expected output:

    Gateway starting (host=127.0.0.1 port=8765 config=gateway.yaml agents=-)
    Loading gateway config from gateway.yaml
    Starting gateway on ws://127.0.0.1:8765
    Press Ctrl+C to stop

Windows-Specific Configuration

Environment Variables

Windows PowerShell environment setup:

powershell
# Session variables (temporary)
$env:TELEGRAM_BOT_TOKEN = "123456:ABC-DEF1234"
$env:OPENAI_API_KEY = "sk-..."
$env:PYTHONUTF8 = "1"

# Persistent variables (permanent)
[Environment]::SetEnvironmentVariable("PYTHONUTF8", "1", "User")
[Environment]::SetEnvironmentVariable("TELEGRAM_BOT_TOKEN", "123456:ABC-DEF1234", "User")

UTF-8 Encoding Setup

Three ways to configure UTF-8 on Windows:

Environment Variable

powershell
$env:PYTHONUTF8 = "1"

Recommended approach – works for current session.

System Environment

powershell
[Environment]::SetEnvironmentVariable("PYTHONUTF8", "1", "Machine")

System-wide setting – requires admin privileges.

Per-Process

powershell
$env:PYTHONIOENCODING = "utf-8"

Alternative encoding setting.

Windows Service Installation

For production deployment as Windows service:

powershell
# Install NSSM (Non-Sucking Service Manager)
choco install nssm

# Create service
nssm install PraisonAIGateway "C:\Python\python.exe"
nssm set PraisonAIGateway Arguments "-m praisonai gateway start --config C:\PraisonAI\gateway.yaml"
nssm set PraisonAIGateway AppDirectory "C:\PraisonAI"
nssm set PraisonAIGateway AppEnvironmentExtra "PYTHONUTF8=1"

# Start service
sc start PraisonAIGateway

Multi-Channel Windows Setup

Hermes-Style Workforce Example

Complete gateway.yaml for 3-bot Hermes workforce:

yaml
gateway:
  host: "127.0.0.1"
  port: 8765

agents:
  cfo:
    model: gpt-4o-mini
    instructions: "You are a CFO assistant. Help with financial analysis and reporting."
    tools: [search_knowledge]
  ops:
    model: gpt-4o-mini  
    instructions: "You are an operations assistant. Help with process optimization."
    tools: [search_knowledge]
  content:
    model: gpt-4o-mini
    instructions: "You are a content assistant. Help with writing and marketing."
    tools: [search_knowledge]

channels:
  telegram_cfo:
    platform: telegram
    token: ${TELEGRAM_CFO_TOKEN}
    routes:
      default: cfo
  telegram_ops:
    platform: telegram
    token: ${TELEGRAM_OPS_TOKEN}
    routes:
      default: ops  
  telegram_content:
    platform: telegram
    token: ${TELEGRAM_CONTENT_TOKEN}
    routes:
      default: content

Matching .env file:

env
# Bot tokens - create 3 separate bots in @BotFather
TELEGRAM_CFO_TOKEN=<cfo-bot-token-from-botfather>
TELEGRAM_OPS_TOKEN=<ops-bot-token-from-botfather>
TELEGRAM_CONTENT_TOKEN=<content-bot-token-from-botfather>

# API keys
OPENAI_API_KEY=<your-openai-key>
GATEWAY_AUTH_TOKEN=<optional-auth-token>

# Windows UTF-8 setup
PYTHONUTF8=1
PYTHONIOENCODING=utf-8

Creating Multiple Telegram Bots

Important: Each channel needs its own Telegram bot token.

  1. Create CFO Bot:
  2. Message @BotFather
  3. /newbot
  4. Name: “CFO Assistant Bot”
  5. Username: “your_company_cfo_bot”
  6. Save token as TELEGRAM_CFO_TOKEN
  1. Create Ops Bot:
  2. /newbot (same BotFather)
  3. Name: “Operations Assistant Bot”
  4. Username: “your_company_ops_bot”
  5. Save token as TELEGRAM_OPS_TOKEN
  1. Create Content Bot:
  2. /newbot (same BotFather)
  3. Name: “Content Assistant Bot”
  4. Username: “your_company_content_bot”
  5. Save token as TELEGRAM_CONTENT_TOKEN

Never reuse tokens – each bot must be separate.


Health Monitoring

Health Check Commands

Monitor gateway status:

powershell
# PowerShell health check
Invoke-RestMethod -Uri "http://127.0.0.1:8765/health"

# Using curl (if installed)
curl http://127.0.0.1:8765/health

# Using Python
python -c "import urllib.request, json; print(json.loads(urllib.request.urlopen('http://127.0.0.1:8765/health').read()))"

Expected healthy response:

json
{
  "status": "healthy",
  "uptime": 3600.5,
  "agents": 3,
  "sessions": 12,
  "clients": 8,
  "channels": {
    "telegram_cfo": { "platform": "telegram", "running": true },
    "telegram_ops": { "platform": "telegram", "running": true },
    "telegram_content": { "platform": "telegram", "running": true }
  }
}

Process Management

Check running gateway processes:

powershell
# Find gateway processes
Get-Process | Where-Object {$_.ProcessName -match "python" -and $_.MainWindowTitle -match "gateway"}

# Alternative: check port usage
netstat -ano | findstr ":8765"

# Kill gateway processes if needed
taskkill /F /IM python.exe /FI "WINDOWTITLE eq *gateway*"

Security Configuration

User Access Control

Configure allowed users to prevent unauthorized access:

yaml
# In gateway.yaml
channels:
  telegram_cfo:
    platform: telegram
    token: ${TELEGRAM_CFO_TOKEN}
    allowed_users: ${TELEGRAM_ALLOWED_USERS}
    routes:
      default: cfo

.env configuration:

env
TELEGRAM_ALLOWED_USERS=123456789,987654321,555666777

Security caveat: Current gateway Telegram polling path may not enforce allowlist until PraisonAI security fix ships. Verify access control after update.

Token Security

Secure token storage on Windows:

powershell
# Use Windows Credential Manager (recommended)
cmdkey /add:TELEGRAM_BOT_TOKEN /user:praisonai /pass:"123456:ABC-DEF"

# Retrieve token in script
$token = cmdkey /list:TELEGRAM_BOT_TOKEN

# Encrypted environment file
# Use tools like sops or age for production

Troubleshooting Windows Issues

Common Windows Errors

gateway install fails: 'startup folder path still contains an unexpanded variable'

Symptoms:

Scheduled Task install path raises a RuntimeError:

startup folder path still contains an unexpanded variable
('%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup'); refusing to create it.

Startup-folder fallback path returns {"ok": False, "error": "..."}:

startup folder path still contains an unexpanded variable
('%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup'); refusing to create it.
This happens off Windows, or when APPDATA is unset.

Cause: APPDATA is not set in the current shell. This is normal on macOS/Linux, common in WSL where APPDATA isn’t inherited from the Windows host, and can happen inside containerised CI runners. The autostart installer expands %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup; with APPDATA unset the variable stays literal, so the installer refuses rather than write a stray path.

Diagram

praisonai gateway install (Windows autostart)

Yes

Yes

No

📦 install

🔍 APPDATA set?

🗓️ Scheduled Task

📁 Startup folder

⛔ refuse: unexpanded variable

✅ installed

Solutions:

  1. On native Windows, verify APPDATA is set
    powershell
    # cmd
    echo %APPDATA%
    
    # PowerShell
    $env:APPDATA

    If empty, log out and back in, or set it explicitly to C:\Users\<user>\AppData\Roaming.

  2. Off Windows, use the native autostart mechanism

    The Scheduled Task and Startup-folder mechanisms are Windows-only. Use launchd (macOS) or systemd --user (Linux) instead — see Platform-Specific Notes.

  3. Clean up a stray directory from an older install

    Installs that ran before PR #4996 could silently create a directory named %APPDATA%\Microsoft\... in the working tree. Check for it and remove it:

    bash
    git status

    On Windows this is an invalid path that breaks actions/checkout if committed. Delete it if found.

charmap codec error

Symptoms:

Error: 'charmap' codec can't encode character '\u26a0' in position 1: character maps to <undefined>

Causes:

  1. Missing UTF-8 environment configuration
  2. OpenAI API failure (429 quota) + encoding issue

Solutions:

powershell
# Set UTF-8 environment
$env:PYTHONUTF8 = "1"

# Check OpenAI billing
# Visit platform.openai.com/billing

# Restart gateway after both fixes
gateway status PID-lock line (PID lock status: Unavailable)

Symptoms:

PID lock status: Unavailable (kill returned a result with an exception set)
Gateway Status: healthy

Cause: On Windows, os.kill(pid, 0) can raise SystemError. From PraisonAI ≥ v4.6.141 the message is advisory only — the /health probe still runs and shows the real gateway status.

POSIX behaviour (since PR #4197): On Linux/macOS, os.kill(pid, 0) raising PermissionError — a gateway owned by another user — is now treated as running rather than silently swallowed. The lock is preserved and a second gateway is refused, instead of the foreign-uid gateway being displaced.

Solution:

powershell
# Confirm the gateway is up regardless of the PID-lock line
curl http://127.0.0.1:8765/health

See Windows: gateway status shows PID lock status: Unavailable and PraisonAI #2844 / PR #2849 for the underlying cause.

ImportError: Gateway requires starlette

Error:

ImportError: Gateway requires starlette and uvicorn.
Install with: pip install praisonai[api]

Solution:

powershell
pip uninstall praisonai
pip install "praisonai[bot,api]"
Bot stops responding (409 Conflict)

Symptoms:

  • Bot works initially, then stops mid-session
  • Log shows: Conflict: terminated by other getUpdates request
  • Health check still shows "running": true

Cause: Duplicate gateway processes polling same token

  • Since PR #4197, the cross-uid cause of this conflict is removed on POSIX: a gateway owned by another user is now treated as running, so its lock is preserved and a second gateway is refused instead of being started on the same token.

Solution:

powershell
# Stop all gateway processes
Get-Process | Where-Object {$_.ProcessName -match "python"} | Stop-Process -Force

# Verify port is free
netstat -ano | findstr ":8765"

# Start single gateway instance
praisonai gateway start --config gateway.yaml
Error starting gateway: invalid attr name 'connections' (psutil 7)

Symptom:

Error starting gateway: invalid attr name 'connections'

on praisonai gateway start with a busy port on psutil ≥ 6.

Cause: Older versions used the removed Process.connections attribute to identify the process holding the port.

Fix: PR #4197 switches to net_connections() (with a connections() fallback) and wraps the lookup so a diagnostic can never break startup. Upgrade praisonai-bot to the merged version — the friendly port-collision message (Another gateway may be running (PID ...). Stop it: praisonai gateway stop) renders again.

25-30 second response delay

Symptoms:

  • Telegram typing indicator disappears after 5 seconds
  • Reply comes 20-30 seconds later
  • No error messages

Explanation: This is normal behavior for RAG + LLM processing.

User guidelines:

  • Do not send duplicate messages during wait
  • Do not restart gateway during response window
  • Typing indicator renewal fix is pending in PraisonAI
gateway install fails: 'startup folder path still contains an unexpanded variable'

Symptoms:

Scheduled Task path — raised as a RuntimeError from install():

startup folder path still contains an unexpanded variable
('%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup'); refusing to create it.

Startup-folder fallback path — returned in install()‘s aggregated result as {"ok": False, "error": "..."}:

startup folder path still contains an unexpanded variable
('%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup'); refusing to create it.
This happens off Windows, or when APPDATA is unset.

Cause: APPDATA is not set in the current shell. The autostart installer builds the Startup-folder path from %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup, and %APPDATA% only expands on Windows with the variable set. This is the norm on macOS/Linux, common in WSL where APPDATA isn’t inherited from the Windows host, and can happen inside containerised CI runners.

Diagram

praisonai gateway install (Windows autostart)

Yes

Yes

No

📦 install

🔍 APPDATA set?

🗓️ Scheduled Task

📁 Startup folder

⛔ refuse: unexpanded variable

✅ installed

Solution:

  1. On native Windows, verify APPDATA is set
    powershell
    # PowerShell
    $env:APPDATA
    
    # cmd
    echo %APPDATA%

    If empty, log out and back in, or set it explicitly to C:\Users\<user>\AppData\Roaming.

  2. Off Windows, use the native autostart mechanism

    The Scheduled Task and Startup-folder mechanisms are Windows-only. Do not run praisonai gateway install on macOS/Linux — use launchd (macOS) or systemd --user (Linux) instead. See Platform-Specific Notes.

  3. Clean up a stray directory from a pre-fix install

    An install that ran before PR #4996 may have created a literal directory named %APPDATA%\Microsoft\... in the working tree. On Windows this is an invalid path that breaks actions/checkout if committed.

    powershell
    git status
    git clean -fdn   # preview; drop -n to delete

Behaviour since PR #4996: rather than silently creating a %APPDATA%\Microsoft\... directory in the current working directory, the installer now refuses cleanly and writes nothing.

Windows-Specific Debugging

Enable detailed logging:

powershell
# Set debug environment
$env:PRAISONAI_LOG_LEVEL = "DEBUG"

# Start with verbose output
praisonai gateway start --config gateway.yaml --verbose

# View logs
Get-Content ~/.praisonai/logs/gateway.log -Tail 50 -Wait

Check Windows firewall:

powershell
# Allow Python through firewall
New-NetFirewallRule -DisplayName "PraisonAI Gateway" -Direction Inbound -Protocol TCP -LocalPort 8765 -Action Allow

# Test connectivity
Test-NetConnection -ComputerName 127.0.0.1 -Port 8765

Performance Optimization

Windows Resource Configuration

Optimize for Windows deployment:

yaml
# gateway.yaml - Windows optimizations
gateway:
  host: "127.0.0.1"
  port: 8765
  max_connections: 50        # Lower for Windows
  worker_processes: 1        # Single process on Windows
  keep_alive_timeout: 30
  client_timeout: 120

# Environment variables for performance
UVICORN_WORKERS=1
UVICORN_KEEP_ALIVE=30
PRAISONAI_CACHE_SIZE=1000

PowerShell performance script:

powershell
# Optimize Python process priority
$proc = Get-Process | Where-Object {$_.ProcessName -eq "python" -and $_.MainWindowTitle -match "gateway"}
$proc.PriorityClass = "High"

# Set power plan to high performance
powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c

Production Deployment

Windows Server Configuration

For production Windows Server deployment:

powershell
# Install as Windows Service
sc create "PraisonAI Gateway" binPath="C:\Python\python.exe -m praisonai gateway start --config C:\PraisonAI\gateway.yaml"
sc config "PraisonAI Gateway" start=auto
sc description "PraisonAI Gateway" "PraisonAI Multi-Channel Bot Gateway"

# Configure service recovery
sc failure "PraisonAI Gateway" reset=86400 actions=restart/30000/restart/60000/restart/60000

# Start service
sc start "PraisonAI Gateway"

IIS reverse proxy (optional):

xml
<!-- web.config for IIS reverse proxy -->
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Gateway WebSocket" stopProcessing="true">
          <match url="ws" />
          <action type="Rewrite" url="http://127.0.0.1:8765/ws" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Best Practices

Use Windows Task Scheduler for monitoring

Create monitoring task:

powershell
# Create health check script
@'
$response = Invoke-RestMethod -Uri "http://127.0.0.1:8765/health" -ErrorAction SilentlyContinue
if ($response.status -ne "healthy") {
    Restart-Service "PraisonAI Gateway"
    Write-EventLog -LogName Application -Source "PraisonAI" -EventID 1001 -Message "Gateway restarted"
}
'@ | Out-File -FilePath C:\PraisonAI\health-check.ps1

# Schedule every 5 minutes
schtasks /create /sc minute /mo 5 /tn "PraisonAI Health Check" /tr "powershell.exe C:\PraisonAI\health-check.ps1"
Configure Windows Event Logging

Enable application logging:

powershell
# Create event source
New-EventLog -LogName Application -Source "PraisonAI Gateway"

# Log gateway events
Write-EventLog -LogName Application -Source "PraisonAI Gateway" -EventID 1000 -Message "Gateway started successfully"
Use Windows Subsystem for Linux (WSL) alternative

For development, consider WSL:

bash
# In WSL Ubuntu
sudo apt update && sudo apt install python3-pip
pip3 install "praisonai[bot,api]"

# UTF-8 is default in WSL
praisonai gateway start --config gateway.yaml

This avoids Windows-specific encoding issues during development.


Related

See Command-Aware Permissions → Windows / PowerShell dialect for how PraisonAI gates PowerShell/cmd commands under your permission rules.