https://github.com/erxes/erxes-ai-assistant-gateway
https://github.com/erxes/erxes-ai-assistant-gateway
Last synced: 14 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/erxes/erxes-ai-assistant-gateway
- Owner: erxes
- Created: 2026-06-05T04:49:06.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-06-25T08:54:34.000Z (30 days ago)
- Last Synced: 2026-06-25T10:22:17.723Z (30 days ago)
- Language: TypeScript
- Size: 183 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# erxes Ai Assistant Gateway
Central Discord gateway for the official erxes Ai Assistant bot.
## Architecture
This service uses one official Discord application and bot named `erxes Ai Assistant`.
```text
Discord guildId + channelId
-> erxes-ai-assistant-gateway
-> tenantId
-> assistantId
-> OpenClaw runtime URL
-> assistant answer
-> Discord reply
```
Customers do not create Discord applications, provide bot tokens, enable privileged intents, or calculate permissions. The gateway-generated installation URL requests the configured bot permission integer, and Erxes Admin owns tenant authorization and channel binding.
## Discord Application Setup
Create the Discord application manually in the Discord Developer Portal.
Use:
```text
Application name: erxes Ai Assistant
Bot name: erxes Ai Assistant
```
Collect:
```text
Application ID
Client ID
Client Secret
Public Key
Bot Token
```
Do not enable these privileged intents for the MVP:
```text
Presence Intent
Server Members Intent
Message Content Intent
```
Use OAuth installation scopes:
```text
bot
applications.commands
```
The gateway-generated installation flow requests Discord Administrator permission:
```text
Administrator permission integer: 8
```
Administrator grants the official erxes Ai Assistant bot full permissions in the selected Discord server. SaaS users do not use the Discord Developer Portal OAuth2 URL Generator directly; they use `/discord/oauth/start`, which generates the install URL with `permissions=8`.
Configure hosted URLs:
```text
Interactions Endpoint URL:
https:///discord/interactions
OAuth Redirect URI:
https:///discord/oauth/callback
```
For local Discord testing, expose port `3001` through an HTTPS tunnel and use the tunnel URLs for those two Discord settings.
## Environment
Copy `.env.example` to `.env` and fill the Discord credentials.
```env
NODE_ENV=development
PORT=3001
PUBLIC_BASE_URL=http://localhost:3001
MONGO_URL=mongodb://127.0.0.1:27017/erxes_ai_assistant_gateway
DISCORD_APPLICATION_ID=
DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
DISCORD_PUBLIC_KEY=
DISCORD_BOT_TOKEN=
DISCORD_REDIRECT_URI=http://localhost:3001/discord/oauth/callback
DISCORD_TEST_GUILD_ID=
DISCORD_BOT_PERMISSIONS=8
ENABLE_MOCK_OPENCLAW=false
ERXES_GATEWAY_ADMIN_SECRET=change-me
ERXES_ALLOWED_RETURN_URLS=http://localhost:3000
OPENCLAW_REQUEST_TIMEOUT_MS=120000
ERXES_ASSISTANT_REPLY_MAX_CHARS=1800
OPENCLAW_SHARED_SECRET=
```
Never commit `.env`. Never log Discord tokens, client secrets, gateway admin secrets, or OpenClaw shared secrets.
## Local Development
```bash
cd /home/batzorig/Erxes/erxes-ai-assistant-gateway
cp .env.example .env
docker compose -f infra/docker-compose.yml up -d
pnpm install
pnpm dev
```
Checks:
```bash
pnpm typecheck
pnpm test
pnpm build
```
Health:
```bash
curl http://localhost:3001/health
```
OAuth start:
```bash
curl -I "http://localhost:3001/discord/oauth/start?tenantId=test-saas-1&assistantId=support-assistant-1&erxesUserId=local-admin-1&returnUrl=http%3A%2F%2Flocalhost%3A3000%2Fsettings%2Fautomations%2Fagents%2Fsupport-assistant-1"
```
Register slash command:
```bash
pnpm register:commands
```
If `DISCORD_TEST_GUILD_ID` is set, this registers a guild command. Otherwise it registers the global command:
```text
/assistant question:
```
Mock OpenClaw is disabled by default. Enable it only for local development or a short-lived deployed mock test:
```env
ENABLE_MOCK_OPENCLAW=true
```
Do not enable the mock route in production. Startup validation rejects `ENABLE_MOCK_OPENCLAW=true` when `NODE_ENV=production`.
Mock OpenClaw:
```bash
curl -X POST http://localhost:3001/mock-openclaw/api/erxes-ai-assistant/ask \
-H 'content-type: application/json' \
-d '{
"tenantId": "test-saas-1",
"assistantId": "support-assistant-1",
"question": "hello",
"user": { "id": "discord-user-id", "username": "Discord Name" },
"discord": { "guildId": "guild-id", "channelId": "channel-id" },
"source": "discord"
}'
```
Create a test binding after a `DiscordInstallation` exists:
```bash
curl -X POST http://localhost:3001/api/bindings \
-H 'content-type: application/json' \
-H 'x-erxes-gateway-admin-secret: change-me' \
-d '{
"installationId": "",
"tenantId": "test-saas-1",
"assistantId": "support-assistant-1",
"assistantName": "Support Assistant",
"discordGuildId": "",
"discordChannelId": "",
"openclawUrl": "http://localhost:3001/mock-openclaw"
}'
```
List installations, channels, and bindings:
```bash
curl "http://localhost:3001/api/installations?tenantId=test-saas-1" \
-H 'x-erxes-gateway-admin-secret: change-me'
curl "http://localhost:3001/api/installations//channels" \
-H 'x-erxes-gateway-admin-secret: change-me'
curl "http://localhost:3001/api/bindings?tenantId=test-saas-1" \
-H 'x-erxes-gateway-admin-secret: change-me'
```
## Routes
Public:
```text
GET /health
GET /discord/oauth/start
GET /discord/oauth/callback
POST /discord/interactions
POST /mock-openclaw/api/erxes-ai-assistant/ask # only when ENABLE_MOCK_OPENCLAW=true
```
Protected with `x-erxes-gateway-admin-secret`:
```text
GET /api/installations
GET /api/installations/:id
GET /api/installations/:id/channels
GET /api/bindings
GET /api/bindings/:id
POST /api/bindings
PATCH /api/bindings/:id
DELETE /api/bindings/:id
```
## Security
Implemented:
- Discord Ed25519 request signature verification.
- Raw request body preservation for interactions.
- Secure expiring single-use OAuth state.
- OAuth callback only saves connected installations after OAuth code exchange succeeds, Discord returns the installed guild, the bot can fetch the guild, and returned permissions include Administrator.
- Erxes return URL allowlist.
- Protected internal APIs with `x-erxes-gateway-admin-secret`.
- No privileged Discord intents for MVP.
- The gateway-generated install URL requests Administrator permission with `permissions=8`.
- OAuth scopes remain only `bot` and `applications.commands`.
- No customer bot tokens.
- No secrets in redirect URLs.
- OpenClaw request timeout handling.
- Optional `x-erxes-ai-assistant-secret` forwarding.
- Tenant/guild installation validation before binding writes.
- One active binding per Discord guild/channel.
- Production startup rejects placeholder gateway admin secrets and refuses to enable the mock OpenClaw route.
TODO: replace the shared gateway admin secret with stronger service authentication, signed requests, and audit logging.
## Ubuntu 24.04 Hosting
Assumptions:
- A DNS record points `gateway-domain` to the server.
- MongoDB is either managed or reachable privately.
- Node.js 22, pnpm, PM2, Nginx, and Certbot are allowed.
Install packages:
```bash
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
sudo npm install -g pnpm pm2
```
Deploy:
```bash
git clone /opt/erxes-ai-assistant-gateway
cd /opt/erxes-ai-assistant-gateway
cp .env.example .env
pnpm install
pnpm test
pnpm build
pm2 start dist/src/main.js --name erxes-ai-assistant-gateway
pm2 save
pm2 startup
```
Nginx:
```nginx
server {
server_name ;
client_max_body_size 5m;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 130s;
}
}
```
Enable SSL:
```bash
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d
```
Verify:
```bash
curl https:///health
```
Configure Discord:
```text
Interactions Endpoint URL:
https:///discord/interactions
OAuth Redirect URI:
https:///discord/oauth/callback
```
Register global command:
```bash
cd /opt/erxes-ai-assistant-gateway
DISCORD_TEST_GUILD_ID= pnpm register:commands
```
Useful logs and rollback:
```bash
pm2 logs erxes-ai-assistant-gateway
pm2 restart erxes-ai-assistant-gateway
pm2 stop erxes-ai-assistant-gateway
```
Rollback by deploying the previous git revision, running `pnpm install && pnpm build`, then `pm2 restart erxes-ai-assistant-gateway`.
## End-To-End MVP Test
1. Create one official Discord application and bot named `erxes Ai Assistant`.
2. Configure this gateway with the official Discord credentials.
3. Register `/assistant question:`.
4. Start Erxes with `ERXES_AI_ASSISTANT_GATEWAY_URL` and `ERXES_AI_ASSISTANT_GATEWAY_SECRET`.
5. Open an Erxes AI assistant.
6. Click `Connect Discord`.
7. Approve the official bot in Discord.
8. Return to Erxes and select a Discord server/channel.
9. Click `Connect channel`.
10. Run `/assistant question: hello` in Discord.
11. The gateway resolves guild/channel to tenant/assistant/OpenClaw and edits the Discord reply with the final answer.