Skip to content

feat(gateway): add Feishu/Lark adapter with WebSocket long-connection #703

@wangyuyan-agent

Description

@wangyuyan-agent

Description

Add a Feishu/Lark adapter to the Custom Gateway, enabling OpenAB to receive and reply to messages from Feishu (China) and Lark (international).

The adapter supports two connection modes:

  • WebSocket long-connection (default) — gateway connects outbound to Feishu, no public URL required
  • HTTP Webhook (fallback) — for environments where outbound WebSocket is blocked

This is the first gateway adapter that uses an outbound long-connection rather than inbound webhooks.

                     External                          Internal

Telegram  --POST-->  ┌─────────────────┐
LINE      --POST-->  │  OpenAB Gateway │ <--WS-- OAB Pod
Teams     --POST-->  │    :8080        │
                     │  ┌───────────┐  │
Feishu    <--WS----  │  │ Feishu WS │  │
(default)            │  │ Client    │  │
                     │  └───────────┘  │
Feishu    --POST-->  │  (fallback)     │
                     └─────────────────┘

Use Case

  1. Chinese enterprise teams — Feishu is where most Chinese tech teams collaborate daily. Without Feishu support, OpenAB cannot serve this market.
  2. Private deployment without public IP — WebSocket mode lets operators run behind NAT/firewall without HTTPS endpoints or Cloudflare Tunnel.
  3. Multi-platform agent — Teams using both Discord and Feishu can run the same OAB agent on both platforms with per-platform @mention gating.
  4. Lark international — Same adapter supports Lark by setting FEISHU_DOMAIN=lark.

Proposed Solution

Add gateway/src/adapters/feishu.rs following the existing adapter pattern:

Feishu Cloud <--WS--> Gateway (feishu.rs) <--WS--> OAB Core --> Agent

Key components:

  • WebSocket: POST /callback/ws/endpoint (AppID+AppSecret auth), protobuf frame decoding (prost), JSON event extraction
  • Webhook fallback: URL challenge, verification token, encrypt key (AES-256-CBC), signature verification, rate limiting
  • Token management: tenant_access_token with auto-refresh
  • Reactions: Map OAB emoji to Feishu reaction API on original messages
  • Mention gating: Gateway-side filtering (FEISHU_REQUIRE_MENTION) + OAB-side (bot_username = bot open_id)
  • Deduplication: event_id + message_id TTL cache
Inbound:
  Feishu WS push (protobuf binary frame)
    --> prost decode --> JSON payload
    --> parse_message_event (filter bot/empty/non-text)
    --> dedupe (event_id + message_id)
    --> GatewayEvent broadcast --> OAB

Outbound:
  OAB GatewayReply
    --> handle_reply (skip reactions cmds / send text)
    --> tenant_access_token (cached, auto-refresh)
    --> POST /open-apis/im/v1/messages
    --> Feishu user sees reply

New dependencies: prost 0.13, aes 0.8, cbc 0.1 (all pinned).

Prior Art

Project Approach Key Takeaway
OpenClaw Built-in channel, WS default WS long-connection is the standard path
Hermes Agent Python adapter, WS + webhook Full webhook security is essential
larksuite/openclaw-lark Official plugin (TypeScript) Gateway = message channel only

Related Issues

  • ADR: Custom Gateway (docs/adr/custom-gateway.md) — this adapter follows the ADR adapter interface
  • LINE adapter (gateway/src/adapters/line.rs) — pattern reference
  • Teams adapter (gateway/src/adapters/teams.rs) — aggregated state pattern reference

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions