Skip to content

Repository files navigation

Claw Gateway

claw-gateway 是一个“单飞书机器人入口 -> 多 OpenClaw 实例”的网关服务。
目标是让用户只和一个飞书机器人交互,由网关按用户映射把请求转发到对应实例。

功能

  • 单机器人接入:飞书侧只暴露一个机器人应用入口。
  • 固定路由:按 open_id -> instance_id/instance_url 做 1:1 映射。
  • 异步任务:事件入队,worker 异步处理,支持重试和死信。
  • 幂等去重:飞书重复投递不会重复处理。
  • 消息类型:支持 text / markdown / post / interactive_card / file / image 回传飞书。
  • 文件链路:支持飞书文件/图片下载后转发到 OpenClaw;支持 OpenClaw 回传附件再上传飞书。
  • WebSocket 上游:当 instance_urlws://wss:// 时,自动使用 WS 调用并支持设备身份签名握手。
  • 管理面:提供 /admin/mappings API 和 /ui/ 管理页面。

项目结构

  • app/main.py:应用入口
  • app/api/:HTTP API(飞书事件、回调、管理、健康检查)
  • app/clients/:飞书与 OpenClaw 客户端
  • app/services/:路由、分发、任务处理、消息校验
  • app/workers/worker.py:异步消费进程
  • app/ui/:管理前端
  • tests/:测试
  • k8s/:Kubernetes 清单

使用方法

1. 本地开发

cp .env.example .env
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload

新开终端启动 worker:

source .venv/bin/activate
python -m app.workers.worker

2. Docker 部署(推荐)

cp .env.docker.example .env.docker
docker compose up --build -d
docker compose ps
curl http://localhost:18000/healthz

管理台地址:

http://localhost:18000/ui/

停止服务:

docker compose down

默认端口:

  • Gateway: 18000
  • Postgres: 15432
  • Redis: 16379

可通过 .env.docker 覆盖:

  • GATEWAY_PORT
  • POSTGRES_PORT
  • REDIS_PORT

接入步骤

1. 配置飞书事件回调

  • 回调地址:{GATEWAY_PUBLIC_BASE_URL}/feishu/events
  • 需要在环境变量中配置:
    • FEISHU_APP_ID
    • FEISHU_APP_SECRET
    • FEISHU_VERIFY_TOKEN
    • FEISHU_ENCRYPT_KEY(建议开启)

2. 配置 OpenClaw 回调地址

  • 回调地址:{GATEWAY_PUBLIC_BASE_URL}/gateway/openclaw/callback
  • 建议配置回调签名密钥:
    • OPENCLAW_CALLBACK_SECRET

3. 建立用户映射

curl -X POST http://localhost:18000/admin/mappings \
  -H "Content-Type: application/json" \
  -d '{
    "open_id":"ou_test_user",
    "instance_id":"inst_001",
    "instance_url":"ws://openclaw.internal:37707/307jao",
    "status":"ACTIVE",
    "gateway_token":"your_gateway_token"
  }'

查询映射:

curl http://localhost:18000/admin/mappings/ou_test_user

分页查询:

curl "http://localhost:18000/admin/mappings?limit=50&offset=0"

协议说明

飞书事件入口

  • POST /feishu/events
  • 支持 url_verification
  • 支持 im.message.receive_v1card.action.trigger

OpenClaw 回调入口

  • POST /gateway/openclaw/callback
  • multipart/form-data
  • 必填 part:payload(JSON)
  • 附件 part:使用 attachment_id 命名

payload 示例:

{
  "task_id": "task_x",
  "open_id": "ou_x",
  "chat_id": "oc_x",
  "messages": [
    {"type": "text", "text": "done"},
    {"type": "post", "content": {"zh_cn": {"title": "t", "content": []}}},
    {"type": "interactive_card", "content": {"config": {}, "elements": []}},
    {"type": "file", "attachment_id": "result_pdf", "file_name": "result.pdf", "mime_type": "application/pdf"},
    {"type": "image", "attachment_id": "plot_png", "file_name": "plot.png", "mime_type": "image/png"}
  ],
  "metadata": {}
}

关键配置项

  • USE_REDIS_QUEUE:生产建议 true
  • DATABASE_URL:数据库连接串
  • REDIS_URL:队列与缓存
  • GATEWAY_PUBLIC_BASE_URL:飞书/OpenClaw 回调可访问公网地址
  • DEFAULT_MESSAGE_MAX_BYTES:附件大小上限
  • ALLOWED_MIME_TYPES:允许的 MIME 白名单
  • OPENCLAW_STATE_DIR:WS 设备身份与 token 持久化目录
  • OPENCLAW_WS_REQUESTED_SCOPES:默认 operator.read,operator.write

局限性(当前版本)

  • WS 上游最小实现下,仅支持图片附件(image/*)透传;非图片文件走 WS 会失败。
  • Markdown 渲染依赖飞书消息能力,复杂语法会降级;网关会优先发卡片 markdown,失败后回退 post
  • 当前映射模型为 1 用户 : 1 实例,不支持会话级多实例选择。
  • gateway_token 仅在写入时接收,查询接口不会返回明文;若 token 权限不足,任务会失败并返回 task_id
  • 若未配置 FEISHU_ENCRYPT_KEYOPENCLAW_CALLBACK_SECRET,对应签名校验会退化为关闭状态。

安全与开源发布建议

  • 不要提交真实凭据(.env.env.docker、云厂商密钥、生产 token)。
  • 仅提交示例模板(如 .env.example.env.docker.example)。
  • 映射中的 gateway_token 应使用最小权限,并定期轮换。
  • 建议在 CI 增加 secret 扫描(例如 gitleaks/trufflehog)。

批量导入映射

python scripts/seed_mappings.py mappings.csv http://localhost:18000

CSV 表头:

open_id,instance_id,instance_url,status,gateway_token

Kubernetes

k8s/ 目录包含:

  • configmap.yaml
  • secret.yaml
  • deployment.yaml
  • service.yaml
  • hpa.yaml

About

一个“单飞书机器人入口 -> 多 OpenClaw 实例”的网关服务

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages