2026-08-14 23:06:31 +08:00
2026-08-14 23:06:31 +08:00
2026-08-14 23:06:31 +08:00
2026-08-14 23:06:31 +08:00
2026-08-14 23:06:31 +08:00
2026-08-14 23:06:31 +08:00
2026-08-14 23:06:31 +08:00
2026-08-14 23:06:31 +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. It is intentionally standalone and not tied to Pi.

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.

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 501 scaffold Implemented Uses QQ Bot access token and user/group text-message heuristics.
Generic webhook Implemented Synchronous JSON HMAC-SHA256 signed JSON endpoint for local bridges and tests.

Install and run

Requires Node.js 20+.

npm install
cp config.example.json config.json
GORI_GATEWAY_CONFIG=./config.json npm run dev

Build and run compiled output:

npm run typecheck
npm run build
GORI_GATEWAY_CONFIG=./config.json npm start

Endpoints:

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

Configuration

Config is loaded from GORI_GATEWAY_CONFIG. If the variable is not set, the gateway loads config.example.json from the current working directory.

Important sections:

  • 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.

Commands

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

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

Feishu setup

  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": "..." }.

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%