2026-08-15 16:56:58 +08:00
2026-08-15 16:56:58 +08:00
2026-08-14 23:06:31 +08:00
2026-08-15 16:56:58 +08:00
2026-08-15 16:56:58 +08:00
2026-08-15 16:56:58 +08:00
2026-08-15 16:56:58 +08:00
2026-08-15 16:56:58 +08:00
2026-08-14 23:06:31 +08:00

gori-agent-gateway

Hermes-gateway-style multi-IM Agent Gateway for routing instant-message webhooks to configurable CLI agents. The primary product flow is gori-agent setup: discover local agents first, pick one, then choose the IM platform to connect.

Quick start

Requires Node.js 20+.

npm install
npm run build
./install.sh
gori-agent setup

install.sh installs the command wrapper under ~/.gori-agent/bin, stores runtime PID/log files under ~/.gori-agent/state and ~/.gori-agent/logs, and adds the command to ~/.bashrc. Open a new terminal or run source ~/.bashrc before using gori-agent directly.

If the package bin has not been linked, use the no-link fallback:

npm run gori-agent -- setup

The setup wizard writes config.json only after confirmation. config.json is ignored by git and should hold local secrets.

Start the gateway after setup:

gori-agent start --config ./config.json

Fallback:

npm run gori-agent -- start --config ./config.json

Convenience executable:

gori-agent setup
gori-agent start
gori-agent start-daemon
gori-agent status
gori-agent logs
gori-agent stop

If the command is not linked into PATH, run the project-local wrapper:

./gori-agent.sh status

Use --config path after the command to override the config path.

CLI commands

gori-agent setup
gori-agent discover-agents [--json]
gori-agent start [--config path]
gori-agent status [--config path]
gori-agent doctor [--config path]
gori-agent print feishu [--config path]
gori-agent --help

Package scripts mirror common commands:

npm run setup
npm run discover-agents
npm run doctor

Agent-first setup flow

gori-agent setup does the following:

  1. Discovers local CLI agents on PATH and always includes the built-in echo fallback.
  2. Lets you pick one agent.
  3. Lets you choose an IM platform: Feishu/Lark, WeChat external webhook, WeCom scaffold, QQ Bot webhook, or Generic webhook.
  4. Builds a focused config.json containing the chosen default agent, the chosen agent plus echo, and the chosen platform enabled.
  5. Asks before writing.

Detected ready agents with known safe prompt modes:

Agent Command Args Input mode Permission mode
Kimi kimi -p final argv kimi -p already runs non-interactively under Kimi Code's auto permission policy. --yolo cannot be combined with -p.
OpenCode opencode run final argv setup can append --auto.
Codex codex exec final argv default; add manual args if needed.
Claude claude -p final argv default; add manual args if needed.
Built-in echo node scripts/echo-agent.js stdin n/a

When you pick Kimi, setup asks which Kimi Code model to use. It reads your local Kimi model aliases at setup time with kimi provider list --json, so custom providers from your actual Kimi config appear in the menu. Choosing the default keeps Kimi Code's configured default_model; choosing a model writes -m <model> -p into that agent's args. You can also enter a custom model alias.

Gemini, Qwen/Qwen Code, Copilot, Pi, and Hermes are probed with --version then --help only. If found, they are shown as needs-config unless a safe prompt mode is known; the wizard asks you to confirm command, args, input mode, extra auto/yolo permission args, and working directory before enabling them.

Discovery never sends an actual prompt to an agent. Probes use child_process.spawn(..., { shell: false }), a 2s timeout, and a 4KB output cap.

Platform status

Platform Inbound Outbound Notes
Feishu/Lark Implemented Implemented Replies to im.message.receive_v1 via /im/v1/messages/{message_id}/reply.
WeCom 501 scaffold Implemented Uses gettoken and message/send; inbound callback verification/encryption is not in v1.
personal WeChat External webhook scaffold Synchronous webhook response Native iLink/personal WeChat integration is not included in v1.
QQ Implemented Implemented Supports QQ official Bot WebSocket gateway mode and optional HTTP callback mode.
Generic webhook Implemented Synchronous JSON HMAC-SHA256 signed JSON endpoint for local bridges and tests.

Hermes reference

This project follows the Hermes gateway pattern: platform adapters normalize inbound messages, a central gateway applies policy/session/concurrency handling, then replies are sent through the originating adapter. The Feishu adapter ports the key Hermes behavior for tenant token caching, URL challenge handling, token verification, im.message.receive_v1 parsing, mention cleanup, and message replies.

Endpoints

  • GET /health
  • GET /platforms
  • POST /webhook/feishu
  • POST /webhook/wecom
  • POST /webhook/qq
  • POST /webhook/generic
  • POST /webhook/weixin

Configuration

Server execution still supports the existing environment variable:

GORI_GATEWAY_CONFIG=./config.json npm start

The CLI resolves config in this order:

  1. --config path
  2. GORI_GATEWAY_CONFIG
  3. ./config.json
  4. seed from config.example.json and write to ./config.json if confirmed

Important sections:

  • server.host: bind address, default 0.0.0.0.
  • server.port: gateway port, default 3000.
  • server.publicBaseUrl: public HTTPS base URL used by print/setup hints, for example https://agent.example.com.
  • policy.allowedUsers: allow only listed normalized user IDs when non-empty.
  • policy.allowedChats: allow only listed normalized chat IDs when non-empty.
  • policy.requireMentionInGroup: if true, group messages are ignored unless the adapter reports a bot mention.
  • defaultAgent: selected when a chat has not chosen an agent.
  • agents[]: named CLI agents using child_process.spawn(command, args) with shell: false.

CLI agent options:

  • inputMode: "stdin": sends the message text to stdin.
  • inputMode: "arg": appends the message text as the final argv item.
  • timeoutMs: kills slow processes.
  • outputMaxBytes: caps captured stdout/stderr.
  • cwd: optional working directory for the agent process.

Chat commands

The gateway handles these commands per chat before invoking an agent:

  • /help
  • /status
  • /agents
  • /agent <name>
  • /new

Feishu setup

The wizard can collect Feishu values and gori-agent print feishu --config ./config.json prints the webhook URL and checklist.

Manual steps:

  1. Create a Feishu/Lark custom app and enable bot messaging.
  2. Configure event subscription for im.message.receive_v1.
  3. Set the request URL to https://<host>/webhook/feishu.
  4. Put appId, appSecret, and verificationToken into your config.
  5. Add bot display names to platforms.feishu.botNames so group mention detection can also work from flattened text.

The adapter accepts Feishu URL verification challenges and returns { "challenge": "..." }.

QQ setup

QQ has two connection modes:

  • websocket (default/recommended): the gateway actively connects to QQ with OAuth access token and WebSocket. No public domain or callback URL is needed.
  • webhook: QQ posts events to a public HTTPS callback URL.

Manual WebSocket steps:

  1. Create a QQ official Bot.
  2. Put appId and clientSecret into your config.
  3. Keep platforms.qq.connectionMode as "websocket".
  4. Keep the default intents value 33554432 (1 << 25, GROUP_AND_C2C_EVENT) to receive GROUP_AT_MESSAGE_CREATE and C2C_MESSAGE_CREATE.
  5. Run gori-agent start --config ./config.json; the process should log QQ websocket ready after successful authentication.

Manual HTTP callback steps:

  1. Set platforms.qq.connectionMode to "webhook".
  2. Configure the callback URL to https://<host>/webhook/qq. QQ callback URLs must use an allowed public HTTPS port such as 443, 8443, 8080, or 80.
  3. Put botSecret into your config and keep verifySignature enabled so X-Signature-Ed25519 callbacks are verified.

The webhook adapter handles QQ op: 13 callback URL validation and returns { "plain_token": "...", "signature": "..." }. GROUP_AT_MESSAGE_CREATE and C2C_MESSAGE_CREATE callbacks return QQ HTTP callback ACK { "op": 12 } immediately, then reply through the QQ Bot group/C2C message APIs.

Generic webhook

Payload:

{
  "chat_id": "demo-chat",
  "user_id": "demo-user",
  "text": "hello",
  "message_id": "optional-message-id",
  "is_group": false,
  "mentions_bot": true
}

Signature header:

  • Header name: X-Gori-Signature
  • Format: sha256=<hex> or just <hex>
  • Input: exact JSON request body bytes as sent by the client
  • Algorithm: HMAC-SHA256 using platforms.webhook.secret

Example:

body='{"chat_id":"demo-chat","user_id":"demo-user","text":"/status"}'
sig=$(printf '%s' "$body" | openssl dgst -sha256 -hmac 'replace-me' -hex | awk '{print $2}')
curl -sS http://localhost:3000/webhook/generic \
  -H 'Content-Type: application/json' \
  -H "X-Gori-Signature: sha256=$sig" \
  -d "$body"

Response shape:

{ "ok": true, "output": "...agent or command output..." }

Security notes

  • Do not expose the gateway publicly without HTTPS and upstream authentication/rate limits.
  • Keep platform secrets outside source control; use a copied config file or secret manager.
  • CLI agents are spawned without a shell, but they can still execute arbitrary local code. Only configure trusted commands.
  • Use allowedUsers and allowedChats in production.
  • Keep requireMentionInGroup enabled for group chats to avoid accidental agent invocation.
  • Set conservative timeoutMs and outputMaxBytes values for external-facing agents.
S
Description
No description provided
Readme 1.1 MiB
Languages
TypeScript 96.1%
JavaScript 3.3%
Shell 0.6%