@gamalan/pi-gateway
Multi-platform chat bridge for pi — connect your AI agent to Telegram, Discord, Slack, and more. Real-time streaming, per-chat sessions, and role-based access control.
Package details
Install @gamalan/pi-gateway from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@gamalan/pi-gateway- Package
@gamalan/pi-gateway- Version
1.9.0- Published
- Jul 9, 2026
- Downloads
- not available
- Author
- gamalan
- License
- MIT
- Types
- extension
- Size
- 578.7 KB
- Dependencies
- 2 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./dist/index.js"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-gateway
Multi-platform chat bridge for pi — connect your AI agent to Telegram, Discord, Slack, and more. Real-time streaming, per-chat sessions, background tasks, and role-based access control.
Fork of 0xKobold/pi-gateway with config-based UID allowlisting.
Features
- Multi-platform adapters — Discord, Telegram, Slack, Twitch, WhatsApp, WebSocket
- Real-time streaming — responses appear token-by-token via live message editing
- Per-chat sessions — isolated conversations with configurable reset policies (daily / idle)
- Background tasks — spawn async work from chats, results delivered when ready
- Allowlist security — DB-based and config-file pre-approved UIDs, admin roles, tool access policies
- Detached daemon mode —
/gateway start -dorpi-gateway start -dkeeps the gateway alive after pi closes - HTTP + WebSocket API — connect external clients, send prompts, receive streaming responses
- pi-native — runs as a pi extension with
/gatewayslash commands and registered tools
Installation
Install from npm (recommended):
pi install npm:@gamalan/pi-gateway
Or clone and build manually:
git clone https://github.com/gamalan/pi-gateway.git
cd pi-gateway
npm install && npm run build
pi install .
Requires pi coding agent (@earendil-works/pi-coding-agent >= 0.80.3) and @sinclair/typebox >= 0.32.0.
Quick Start
# Start the gateway
/gateway start
# Check status
/gateway status
# Stop
/gateway stop
The gateway starts on http://localhost:3847 by default. See /gateway config for current settings.
Configuration
Configuration lives at ~/.pi/gateway/config.json:
{
"port": 3847,
"host": "localhost",
"tokens": [], // Bearer tokens for API auth (empty = allow all)
"corsOrigins": ["*"],
"enableWebSocket": true,
"enableHttp": true,
"security": {
"allowAll": true, // false = enforce allowlist
"requirePairing": false,
"allowedUids": {}, // pre-approved users (see Security)
"adminUids": {}, // users with full access (see Admin Users)
"rateLimit": {
"maxRequests": 60,
"windowMs": 60000
}
},
"sessions": {
"resetPolicy": "idle", // "daily" | "idle" | "both"
"dailyHour": 4, // hour (0-23) for daily reset
"idleMinutes": 1440 // minutes before idle reset
},
"platforms": {
"discord": {
"enabled": true,
"botToken": "your-token",
"guildId": "optional-guild-id"
},
"twitch": {
"enabled": true,
"clientId": "your-client-id",
"clientSecret": "your-secret",
"channels": ["channel-name"]
},
"telegram": {
"enabled": true,
"token": "your-bot-token",
"webhookUrl": "https://..." // omit for long polling
},
"slack": {
"enabled": true,
"webhookUrl": "https://...",
"botToken": "optional-bot-token"
},
"whatsapp": {
"enabled": true,
"sessionPath": "~/.pi/whatsapp-session",
"printQr": true
}
}
}
When the gateway starts for the first time with no config file, it
automatically seeds ~/.pi/gateway/config.json from the default
template shipped with the package. You can also find it at
node_modules/pi-gateway/config/config.default.json.
Telegram: webhook vs long polling
The gateway auto-detects the mode based on whether webhookUrl is set:
webhookUrl |
Mode | How it works |
|---|---|---|
| Set | Webhook | Telegram POSTs updates to /webhook/telegram on the gateway's HTTP server. Lowest latency, requires a public URL. |
| Omitted | Long polling | The gateway opens a persistent connection to Telegram's getUpdates endpoint (30s timeout). Telegram holds it open and returns immediately when a message arrives — near-real-time, no public URL needed. |
Both modes are real-time. Long polling is NOT interval-based — it keeps one connection alive at all times.
Security
Allowlist (DB)
Manage users at runtime via /gateway commands:
# List allowlisted users
/gateway allow
# Add a user
/gateway allow discord 123456789
# Revoke a user (via tool or directly)
Config-file pre-approved UIDs
Skip pairing entirely by listing UIDs in the security block of config.json:
{
"security": {
"allowAll": false,
"allowedUids": {
"discord": ["123456789", "987654321"],
"telegram": ["1234567890"],
"*": ["cross-platform-admin"]
},
"adminUids": {
"discord": ["123456789"],
"*": ["cross-platform-admin-uid"]
},
"rateLimit": {
"maxRequests": 60,
"windowMs": 60000
}
}
}
- Platform-specific keys match that platform only
- The
"*"wildcard matches any platform - Users in this list are auto-allowed on first contact — no pairing code needed
adminUidsgrants full unrestricted access (bypasses all tool policies)- All security settings live in the main
config.json— no separate security file
Admin Users
Admin users have full unrestricted access — they bypass all tool policies and can use every tool pi offers (bash, write, edit, subagent, etc.).
Admins can be set at runtime or via config's security.adminUids block:
{
"security": {
"adminUids": {
"discord": ["123456789"],
"*": ["cross-platform-admin-uid"]
}
}
}
# List all admins (DB + config)
/gateway admin list
# Grant admin to a user on a specific platform
/gateway admin add discord 123456789
# Grant admin on ALL platforms
/gateway admin add * 123456789
# Revoke admin
/gateway admin remove discord 123456789
Admin users are listed in the status panel and their messages carry a "FULL ACCESS" guard.
Tool Policy
By default, external users are restricted to read-only tools when their messages reach pi: they can search code, inspect files, and ask questions, but cannot write files, execute shell commands, spawn subagents, or modify system state.
The policy is enforced via a system directive prepended to every forwarded message. It is tunable per platform, per user, or globally.
Default allowed tools: read, web_search, fetch_content, fffind, ffgrep, module_report, read_symbol, code search tools, lsp_diagnostics, lsp_navigation, image_generate, gateway_*
Default denied tools: bash, write, edit, subagent, todo, goal_complete, mcp, ast_grep_replace, agent_browser, wait, intercom, wiki_*, lens_diagnostics
Managing Policies
# List all explicit policies
/gateway tool-policy list
# See the default baseline
/gateway tool-policy defaults
# Allow bash for a specific user
/gateway tool-policy set discord U123456 bash allow
# Deny write for all users on Discord
/gateway tool-policy set discord * write deny
# Allow everything for an admin user (glob)
/gateway tool-policy set * admin-uid * allow
# Remove a policy by ID
/gateway tool-policy remove 3
# Reset all custom policies to defaults
/gateway tool-policy reset
Policies can also be managed from within pi sessions via the gateway_tool_policy tool.
Resolution order (highest wins): user-specific > platform-specific > global. Ties break deny-first (secure by default). The * glob matches any tool name. Admin users always bypass all restrictions.
Note: All security configuration (allowlist, admin UIDs, rate limits) lives in the
securityblock of~/.pi/gateway/config.json. There is no separate security config file. On first run, the gateway auto-seeds a complete default config so you don't have to write one from scratch.
Pairing Flow
When requirePairing is enabled and a user is not in the allowlist:
- User sends a message → blocked, receives a pairing code
- Admin approves with
/gateway pair <code> - User is added to the DB allowlist
Commands
| Command | Description |
|---|---|
/gateway start [port] |
Start the gateway |
/gateway stop |
Stop the gateway |
/gateway restart |
Restart the gateway |
/gateway status |
Show running status, platforms, sessions |
/gateway pair [code] |
List pending codes or approve one |
/gateway allow [platform] [userId] |
List allowlist or add a user |
/gateway revoke <platform> <userId> |
Remove a user from the DB allowlist |
/gateway sessions |
List active chat sessions |
/gateway tasks |
List background tasks |
/gateway config |
Show current configuration |
/gateway admin list |
List admin users (DB + config) |
/gateway admin add <p|*> <uid> |
Grant admin privileges |
/gateway admin remove <p|*> <uid> |
Revoke admin |
/gateway admin list |
List admin users |
/gateway admin add <p|*> <uid> |
Grant admin privileges |
/gateway admin remove <p|*> <uid> |
Revoke admin |
/gateway tool-policy list |
List explicit tool policies |
/gateway tool-policy defaults |
Show default policy baseline |
/gateway tool-policy set <p> <u> <t> allow|deny |
Add/update a tool policy |
/gateway tool-policy remove <id> |
Delete a policy |
/gateway tool-policy reset |
Clear all, back to defaults |
HTTP API
Available when the gateway is running:
| Endpoint | Method | Description |
|---|---|---|
/api/status |
GET | Gateway status (running, adapters, clients, sessions) |
/api/sessions |
GET | Active sessions |
/api/background |
GET | Background tasks |
/api/allowlist |
GET | Allowlisted users |
/api/pairing |
GET | Pending pairing codes |
Authenticate with Authorization: Bearer <token> if tokens are configured.
WebSocket API
Connect to ws://localhost:3847. Messages are JSON:
// Send a prompt
{ "type": "prompt", "data": { "message": "Hello" } }
// Start a background task
{ "type": "background", "data": { "sessionId": "...", "command": "..." } }
// Ping
{ "type": "ping" }
Receive responses, background task updates, and agent events as server-pushed messages.
Registered Tools
The extension registers these tools for use in pi sessions:
gateway_status— Check if gateway is running and which adapters are activegateway_sessions— List active chat sessionsgateway_background_tasks— List and manage background tasksgateway_pairing— Generate or approve pairing codesgateway_tool_policy— Manage tool access policies for external users
Sessions
Each chat gets an isolated session with configurable reset policies:
- daily — Session resets at a specific hour each day (default: 4 AM)
- idle — Session resets after N minutes of inactivity
- both — Whichever triggers first
Sessions persist across gateway restarts in ~/.pi/gateway/gateway-sessions.db.
Background Tasks
Long-running work is spawned in isolated background sessions. Results are delivered back to the parent chat when complete. Managed via /gateway tasks.
Architecture
┌─────────────┐ ┌─────────────────────────────┐
│ pi agent │◄───►│ pi-gateway │
│ (RPC) │ │ │
└─────────────┘ │ ┌─────────────────────┐ │
│ │ Platform Adapters │ │
┌─────────────┐ │ │ Discord · Telegram │ │
│ HTTP / WS │────►│ │ Slack · Twitch │ │
│ Clients │ │ │ WhatsApp · WebSocket │ │
└─────────────┘ │ └─────────────────────┘ │
│ │
│ ┌─────────────────────┐ │
│ │ Sessions Store │ │
│ │ Background Manager │ │
│ │ Security Layer │ │
│ └─────────────────────┘ │
└─────────────────────────────┘
- Platform adapters translate incoming platform messages into a unified format
- Sessions store (
SQLite) persists per-chat state with reset policies - Background manager spawns async child processes, delivers results via chat
- Security layer checks allowlists, manages pairing codes, and enforces rate limits
License
MIT