# How to Integrate Feishu Bot with OpenDeepWiki: A Complete Implementation Guide

> Learn how to integrate Feishu Bot with OpenDeepWiki using the FeishuProvider class. This guide covers authentication, webhook validation, and message formatting for seamless integration. Get started today!

- Repository: [AIDotNet/OpenDeepWiki](https://github.com/aidotnet/opendeepwiki)
- Tags: how-to-guide
- Published: 2026-02-16

---

**OpenDeepWiki integrates Feishu Bot through a unified Message Provider architecture that handles authentication, webhook validation, and message formatting via the `FeishuProvider` class in the `AIDotNet/OpenDeepWiki` repository.**

The `AIDotNet/OpenDeepWiki` project provides a modular chat infrastructure that abstracts platform-specific bot implementations into reusable providers. When you integrate Feishu Bot with OpenDeepWiki, you leverage the **Message Provider** mechanism located in `src/OpenDeepWiki/Chat/Providers/Feishu/` to handle tenant access tokens, webhook security verification, and bidirectional message parsing.

## Understanding the Feishu Provider Architecture

### Core Components and File Structure

The Feishu integration resides in the `src/OpenDeepWiki/Chat/Providers/Feishu/` directory and consists of four primary files:

- **[`FeishuProvider.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/FeishuProvider.cs)** — The main implementation class inheriting from `BaseMessageProvider`, containing `InitializeAsync`, `ValidateWebhookAsync`, `ParseMessageAsync`, and `SendMessageAsync` methods.
- **[`FeishuProviderOptions.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/FeishuProviderOptions.cs)** — The configuration model mapping [`appsettings.json`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/appsettings.json) values to strongly-typed properties.
- **[`FeishuModels.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/FeishuModels.cs)** — POCO definitions for Feishu webhook events, API responses, and card structures.
- **[`ChatServiceExtensions.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/ChatServiceExtensions.cs)** — Dependency injection registration logic located at [`src/OpenDeepWiki/Chat/ChatServiceExtensions.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/src/OpenDeepWiki/Chat/ChatServiceExtensions.cs).

### Configuration Options (FeishuProviderOptions)

The **FeishuProviderOptions** class in [`FeishuProviderOptions.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/FeishuProviderOptions.cs) exposes the following configuration properties under the `Chat:Providers:Feishu` section:

- `AppId` and `AppSecret` — Tenant credentials from the Feishu Open Platform.
- `VerificationToken` — Used to validate incoming webhook requests.
- `EncryptKey` — Optional AES key for decrypting encrypted webhook payloads.
- `ApiBaseUrl` — Defaults to `https://open.feishu.cn/open-apis`.
- `TokenCacheSeconds` — Access token cache duration (default 7000 seconds).

## Configuring Feishu Bot Integration in OpenDeepWiki

### appsettings.json Configuration

Add the Feishu provider configuration to your [`appsettings.json`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/appsettings.json) or secure configuration source:

```json
{
  "Chat": {
    "Providers": {
      "Feishu": {
        "AppId": "<your_app_id>",
        "AppSecret": "<your_app_secret>",
        "VerificationToken": "<your_verification_token>",
        "EncryptKey": "<your_encrypt_key>",
        "ApiBaseUrl": "https://open.feishu.cn/open-apis",
        "TokenCacheSeconds": 7000,
        "Enabled": true,
        "MessageInterval": "00:00:01"
      }
    }
  }
}

```

Store sensitive values in environment variables or Azure Key Vault rather than committing them to source control.

### Service Registration in Program.cs

Register the chat services and Feishu provider in your [`Program.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/Program.cs):

```csharp
builder.Services.AddChatServices(builder.Configuration);

```

The `AddChatServices` extension method in [`ChatServiceExtensions.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/ChatServiceExtensions.cs) performs the following registrations:

1. Binds `FeishuProviderOptions` to the configuration section `Chat:Providers:Feishu`.
2. Adds a named `HttpClient` for `FeishuProvider` with base address and default headers.
3. Registers `FeishuProvider` as a scoped service implementing `IMessageProvider`.
4. Adds the provider instance to the `IMessageProvider` collection for automatic discovery during startup.

## Implementing the Feishu Bot Workflow

### Initialization and Access Token Management

During application startup, the `ProviderInitializationService` calls `FeishuProvider.InitializeAsync`, which invokes `GetAccessTokenAsync` (lines 50-71 in [`FeishuProvider.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/FeishuProvider.cs)). This method:

- Posts `app_id` and `app_secret` to `auth/v3/tenant_access_token/internal`.
- Caches the returned token for `TokenCacheSeconds` (default 7000 seconds) in memory.
- Uses `SemaphoreSlim` to prevent concurrent token refresh requests.

```csharp
// Internal implementation detail from FeishuProvider.cs
private async Task<string> GetAccessTokenAsync(CancellationToken ct)
{
    // Checks cache first, then requests new token if expired
    // Uses SemaphoreSlim for thread safety
}

```

### Webhook Validation and Security

Incoming webhook requests from Feishu pass through `ValidateWebhookAsync` (lines 95-124), which handles:

- **URL Verification**: Returns the `challenge` parameter for Feishu platform verification.
- **Token Validation**: Compares the request token against `VerificationToken`.
- **Decryption**: If `EncryptKey` is configured, decrypts AES-encrypted payloads before validation.

### Parsing Incoming Messages

The `ParseMessageAsync` method (lines 74-132) converts Feishu-specific payloads into the unified `ChatMessage` model:

1. Deserializes the raw JSON into `FeishuWebhookEvent`.
2. Decrypts if necessary using the configured `EncryptKey`.
3. Identifies event types (`im.message.receive_v1` or `message`).
4. Extracts `message_type` and content via `ParseFeishuMessageContent`.
5. Returns a `ChatMessage` containing `MessageId`, `SenderId`, `ReceiverId`, `Content`, `MessageType`, `Timestamp`, and `Metadata`.

### Sending Replies and Cards

The `SendMessageAsync` method (lines 140-191) handles outbound communication:

- Retrieves a valid AccessToken via `GetAccessTokenAsync`.
- Calls `DegradeMessage` to convert unsupported message types to text.
- Uses `ConvertToFeishuFormat` to generate Feishu-specific `msg_type` and `content` JSON.
- POSTs to `im/v1/messages` via `HttpClient`.
- Implements retry logic via `IsRetryableError` and `SendWithRetryAsync` for transient failures.

For interactive cards, use the static helper methods:

```csharp
// Create a simple text card
var cardJson = FeishuProvider.CreateTextCard(
    title: "系统通知",
    content: "OpenDeepWiki 已成功接收到你的请求。",
    headerColor: "indigo");

// Create a multi-section card
var multiCard = FeishuProvider.CreateMultiSectionCard(
    title: "任务进度",
    sections: new[] { 
        new { title = "步骤 1", content = "已完成" },
        new { title = "步骤 2", content = "进行中" }
    });

```

## Building a Custom Feishu Bot Handler

Implement the `IMessageHandler` interface to create custom bot logic:

```csharp
public class EchoBot : IMessageHandler
{
    private readonly IMessageRouter _router;
    private readonly ILogger<EchoBot> _logger;

    public EchoBot(IMessageRouter router, ILogger<EchoBot> logger)
    {
        _router = router;
        _logger = logger;
    }

    public async Task HandleAsync(IChatMessage message, CancellationToken ct)
    {
        if (message.Platform != "feishu") return;

        var reply = new ChatMessage
        {
            MessageId = Guid.NewGuid().ToString(),
            SenderId = message.ReceiverId,          // 机器人自己的 OpenId
            ReceiverId = message.SenderId,
            Content = $"你刚才说: {message.Content}",
            MessageType = ChatMessageType.Text,
            Platform = "feishu",
            Timestamp = DateTimeOffset.UtcNow
        };

        var provider = _router.GetProvider("feishu");
        var result = await provider.SendMessageAsync(reply, reply.ReceiverId, ct);
        if (!result.Success)
        {
            _logger.LogWarning("发送回显失败: {Error}", result.ErrorMessage);
        }
    }
}

```

## Summary

- OpenDeepWiki uses a **Message Provider** pattern to abstract platform-specific bot implementations, with Feishu support located in `src/OpenDeepWiki/Chat/Providers/Feishu/`.
- The **FeishuProvider** class handles the complete lifecycle: tenant access token caching, webhook validation, message parsing, and sending with automatic retry logic.
- Configuration requires `AppId`, `AppSecret`, and `VerificationToken` from the Feishu Open Platform, stored securely in [`appsettings.json`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/appsettings.json) under the `Chat:Providers:Feishu` section.
- Register services using `builder.Services.AddChatServices(builder.Configuration)` in [`Program.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/Program.cs) to automatically discover and initialize the Feishu provider.
- Implement **IMessageHandler** to build custom bot logic, using the provider's static methods like `CreateTextCard` for rich interactive messages.

## Frequently Asked Questions

### What configuration values do I need from the Feishu Open Platform?

You need four critical values from your Feishu application's credentials page: **App ID** and **App Secret** for OAuth authentication, **Verification Token** for webhook security validation, and optionally **Encrypt Key** if you enable message encryption. Map these to `FeishuProviderOptions` in your [`appsettings.json`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/appsettings.json) under the `Chat:Providers:Feishu` section.

### How does OpenDeepWiki handle Feishu access token expiration?

The **FeishuProvider** implements automatic token caching in `GetAccessTokenAsync` (lines 61-71 of [`FeishuProvider.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/FeishuProvider.cs)). It caches the tenant access token for 7000 seconds by default (configurable via `TokenCacheSeconds`) and uses a `SemaphoreSlim` to prevent concurrent refresh requests when the token expires. The initialization service automatically refreshes tokens during application startup.

### Can I send interactive cards instead of plain text?

Yes, the **FeishuProvider** includes static helper methods `CreateTextCard` and `CreateMultiSectionCard` (lines 81-135) that generate JSON payloads for Feishu's interactive card format. Set your `ChatMessage.MessageType` to `ChatMessageType.Card` and pass the generated JSON string as the `Content` property. The provider automatically converts this to Feishu's `msg_type: interactive` format when sending via `SendMessageAsync`.

### How do I verify the Feishu webhook is working locally?

Use the `ValidateWebhookAsync` method (lines 95-124 in [`FeishuProvider.cs`](https://github.com/AIDotNet/OpenDeepWiki/blob/main/FeishuProvider.cs)) to handle Feishu's URL verification challenge. When Feishu sends a verification request containing a `challenge` parameter, this method returns the challenge value for you to echo back. For local development, ensure your endpoint is publicly accessible via tools like ngrok, and verify that your `VerificationToken` matches the value in your Feishu app settings to pass signature validation.