2026-03-17-feishu-websocket-integration-design.md 13 KB

Feishu WebSocket Integration - Design Document

Date: 2026-03-17 Author: Sisyphus AI Agent Status: Draft for Review

Executive Summary

Add WebSocket long-connection support for Feishu bot integration, enabling internal network deployment without requiring public domain or internet-facing endpoints. The system will support both existing webhook mode and new WebSocket mode, allowing users to choose their preferred connection method.


1. Architecture Overview

Current Architecture (Webhook Mode)

Feishu Cloud → Public Domain → NAT/Firewall → Internal Server
                                    └→ POST /api/feishu/webhook/:appId

Limitations:

  • Requires public domain with SSL certificate
  • Requires NAT/firewall port forwarding or reverse proxy
  • Not suitable for pure internal network deployment

New Architecture (WebSocket Mode)

Feishu Cloud ←──────── WebSocket (wss://open.feishu.cn) ──────── Internal Server
                                         ↑
Feishu Cloud → Webhook (optional backup) → Internal Server

Advantages:

  • No public domain required
  • No NAT/firewall configuration needed
  • Direct connection from internal network to Feishu cloud
  • Real-time message delivery (milliseconds vs minutes)
  • Connection复用,资源效率更高

Architecture Diagram

┌─────────────────────────────────────────────────────────────┐
│                     Feishu Open Platform                    │
│                  (WebSocket Event Subscription)             │
└───────────────────────┬─────────────────────────────────────┘
                        │
          ┌─────────────┴─────────────┐
          │                           │
    ┌─────▼──────┐            ┌──────▼─────┐
    │   Bot A    │            │   Bot B    │
    │ ws://.../A │            │ ws://.../B │
    └─────┬──────┘            └──────┬─────┘
          │                          │
    ┌─────▼──────────────────────────▼──────┐
    │            AuraK Server                │
    │  ┌──────────────────────────────────┐  │
    │  │      FeishuModule               │  │
    │  │  ┌────────────────────────────┐ │  │
    │  │  │  FeishuWsManager           │ │  │
    │  │  │  - per-bot connections     │ │  │
    │  │  │  - auto-reconnect         │ │  │
    │  │  │  - message routing        │ │  │
    │  │  └────────────────────────────┘ │  │
    │  │  ┌────────────────────────────┐ │  │
    │  │  │  FeishuService            │ │  │
    │  │  │  - existing logic        │ │  │
    │  │  │  - new ws connect/disconnect│ │  │
    │  │  └────────────────────────────┘ │  │
    │  │  ┌────────────────────────────┐ │  │
    │  │  │  FeishuController         │ │  │
    │  │  │  - webhook endpoints     │ │  │
    │  │  │  - ws management APIs    │ │  │
    │  │  └────────────────────────────┘ │  │
    │  └──────────────────────────────────┘  │
    └──────────────────────────────────────────┘

2. Implementation Plan

2.1 New Components

2.1.1 FeishuWsManager

Purpose: Manage WebSocket connections for each bot

Responsibilities:

  • Establish and maintain WebSocket connections
  • Handle connection lifecycle (connect, disconnect, reconnect)
  • Route incoming messages to appropriate bot handlers
  • Manage connection state per bot

Location: server/src/feishu/feishu-ws.manager.ts

Key Methods:

class FeishuWsManager {
  // Start WebSocket connection for a bot
  async connect(bot: FeishuBot): Promise<void>
  
  // Stop WebSocket connection for a bot
  async disconnect(botId: string): Promise<void>
  
  // Get connection status
  getStatus(botId: string): ConnectionStatus
  
  // Get all active connections
  getAllConnections(): Map<string, ConnectionStatus>
}

2.1.2 ConnectionStatus Type

enum ConnectionState {
  DISCONNECTED = 'disconnected',
  CONNECTING = 'connecting',
  CONNECTED = 'connected',
  ERROR = 'error'
}

interface ConnectionStatus {
  botId: string
  state: ConnectionState
  connectedAt?: Date
  lastHeartbeat?: Date
  error?: string
}

2.2 Modified Components

2.2.1 FeishuService

New Methods:

class FeishuService {
  // Start WebSocket connection for a bot
  async startWsConnection(botId: string): Promise<void>
  
  // Stop WebSocket connection for a bot
  async stopWsConnection(botId: string): Promise<void>
  
  // Get connection status
  async getWsStatus(botId: string): Promise<ConnectionStatus>
  
  // List all connection statuses
  async getAllWsStatuses(): Promise<ConnectionStatus[]>
}

2.2.2 FeishuController

New Endpoints:

// POST /feishu/bots/:id/ws/connect - Start WebSocket connection
// POST /feishu/bots/:id/ws/disconnect - Stop WebSocket connection  
// GET  /feishu/bots/:id/ws/status - Get connection status
// GET  /feishu/ws/status - Get all connection statuses

Modified Endpoints:

  • Keep existing webhook endpoints unchanged
  • Add WebSocket status indicator in bot list response

2.2.3 FeishuBot Entity

New Fields:

@Entity('feishu_bots')
export class FeishuBot {
  // ... existing fields ...
  
  @Column({ default: false })
  useWebSocket: boolean
  
  @Column({ nullable: true })
  wsConnectionState: string
}

2.3 Feishu SDK Integration

Package: @larksuiteoapi/node-sdk

Installation:

cd server && yarn add @larksuiteoapi/node-sdk

Configuration:

import { EventDispatcher, Conf } from '@larksuiteoapi/node-sdk'

const client = new EventDispatcher({
  appId: bot.appId,
  appSecret: bot.appSecret,
  verificationToken: bot.verificationToken,
}, {
  logger: console
})

2.4 Event Handling

Flow for WebSocket Mode:

Feishu Cloud ──WebSocket──> FeishuWsManager.on('message')
                                    │
                                    ▼
                            Parse event type
                                    │
                    ┌───────────────┼───────────────┐
                    │               │               │
              im.message.   im.message.      other
              receive_v1    p2p_msg_received
                    │               │
                    ▼               ▼
            FeishuService.processChatMessage()
                                    │
                                    ▼
                            Send response via
                            FeishuService.sendTextMessage()

2.5 Configuration Changes

Feishu Open Platform:

Users need to configure in Feishu developer console:

  1. Go to "Event Subscription" (事件与回调)
  2. Select "Use long connection to receive events" (使用长连接接收事件)
  3. Add event: im.message.receive_v1
  4. Important: Must start local WebSocket client first before saving

3. Data Flow

WebSocket Message Flow

1. User triggers connect API
       │
       ▼
2. FeishuController.connect(botId)
       │
       ▼
3. FeishuService.startWsConnection(botId)
       │
       ▼
4. FeishuWsManager.connect(bot)
       │
       ▼
5. SDK establishes WebSocket to open.feishu.cn
       │
       ▼
6. Connection established, events flow:
       │
       ├─> on('message') ──> _processEvent() ──> _handleMessage()
       │                                              │
       │                                              ▼
       │                                    FeishuService.processChatMessage()
       │                                              │
       │                                              ▼
       │                                    FeishuService.sendTextMessage() (via SDK)
       │
       ├─> on('error') ──> log error ──> trigger reconnect
       │
       └─> on('close') ──> trigger auto-reconnect

4. Error Handling

Connection Errors

Error Type Handling
Network timeout Retry with exponential backoff (max 5 attempts)
Invalid credentials Mark bot as error state, notify user
Token expired Refresh token, reconnect
Feishu server error Wait 30s, retry

Auto-Reconnect Strategy

Initial delay: 1 second
Max delay: 60 seconds
Backoff multiplier: 2x
Max attempts: 5
Reset on successful connection

5. API Design

5.1 Connect WebSocket

POST /api/feishu/bots/:id/ws/connect

Response 200:
{
  "success": true,
  "botId": "bot_xxx",
  "status": "connecting"
}

Response 400:
{
  "success": false,
  "error": "Bot not found or disabled"
}

5.2 Disconnect WebSocket

POST /api/feishu/bots/:id/ws/disconnect

Response 200:
{
  "success": true,
  "botId": "bot_xxx",
  "status": "disconnected"
}

5.3 Get Connection Status

GET /api/feishu/bots/:id/ws/status

Response 200:
{
  "botId": "bot_xxx",
  "state": "connected",
  "connectedAt": "2026-03-17T10:00:00Z",
  "lastHeartbeat": "2026-03-17T10:05:00Z"
}

5.4 Get All Statuses

GET /api/feishu/ws/status

Response 200:
{
  "connections": [
    {
      "botId": "bot_xxx",
      "state": "connected",
      "connectedAt": "2026-03-17T10:00:00Z"
    },
    {
      "botId": "bot_yyy",
      "state": "disconnected"
    }
  ]
}

6. Security Considerations

  1. Credential Storage: App ID and App Secret stored encrypted in database
  2. Connection Validation: Verify bot belongs to authenticated user before connect
  3. Rate Limiting: Implement per-bot message rate limiting
  4. Connection Limits: Max 10 concurrent WebSocket connections per server instance

7. Testing Strategy

Unit Tests

  • FeishuWsManager connection lifecycle
  • Message routing logic
  • Error handling and reconnection

Integration Tests

  • Full WebSocket connection flow
  • Message send/receive cycle
  • Reconnection after network failure

Manual Testing

  • Local development without ngrok
  • Verify webhook still works alongside WebSocket

8. Backward Compatibility

  • Existing webhook endpoints: Unchanged, continue to work
  • Bot configuration: Existing bots keep webhook mode by default
  • Migration path: Users can switch to WebSocket anytime via API
  • Dual mode: Both modes can run simultaneously for different bots

9. Migration Guide

For Existing Users

  1. Update AuraK to new version (with WebSocket support)
  2. Install Feishu SDK: yarn add @larksuiteoapi/node-sdk
  3. In Feishu Developer Console:
    • Start local WebSocket server
    • Change event subscription to "Use long connection"
  4. Call POST /api/feishu/bots/:id/ws/connect to activate

10. Limitations

  1. Outbound Network Required: Server must be able to reach open.feishu.cn via WebSocket
  2. Single Connection Per Bot: Each bot needs its own WebSocket connection
  3. Feishu SDK Required: Must install official SDK, cannot use raw WebSocket
  4. Private Feishu: Does not support Feishu private deployment (自建飞书)

11. File Changes Summary

New Files

  • server/src/feishu/feishu-ws.manager.ts - WebSocket connection manager
  • server/src/feishu/dto/ws-status.dto.ts - WebSocket status DTOs

Modified Files

  • server/src/feishu/feishu.service.ts - Add WS methods
  • server/src/feishu/feishu.controller.ts - Add WS endpoints
  • server/src/feishu/entities/feishu-bot.entity.ts - Add WS fields
  • server/src/feishu/feishu.module.ts - Register new manager

Dependencies

  • Add: @larksuiteoapi/node-sdk

12. Success Criteria

  • Server can establish WebSocket connection to Feishu
  • Messages received via WebSocket are processed correctly
  • Responses sent back to Feishu via SDK
  • Auto-reconnect works after network interruption
  • Webhook mode continues to work unchanged
  • Both modes can coexist for different bots
  • Internal network deployment works without public domain