> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mibyanai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Feishu / Lark

> Set up Mibyan as a Feishu or Lark bot

Python dependency commands on this page use a
[PM-prepared source checkout](/desktop/reference/package-management#developer-workflow).
After a dependency change, reactivate the checkout and restart Mibyan.

Mibyan integrates with Feishu and Lark as a full-featured bot. Once connected, you can chat with the agent in direct messages or group chats, receive cron job results in a home chat, and send text, images, audio, and file attachments through the normal gateway flow.

The integration supports both connection modes:

* `websocket` — recommended; Mibyan opens the outbound connection and you do not need a public webhook endpoint
* `webhook` — useful when you want Feishu/Lark to push events into your gateway over HTTP

## How Mibyan Behaves

| Context | Behavior |
| - | - |
| Direct messages | Mibyan responds to every message. |
| Group chats | Mibyan responds only when the bot is @mentioned in the chat. |
| Shared group chats | By default, session history is isolated per user inside a shared chat. |

This shared-chat behavior is controlled by `config.yaml`:

```yaml theme={null}
group_sessions_per_user: true
```

Set it to `false` only if you explicitly want one shared conversation per chat.

## Step 1: Create a Feishu / Lark App

### Recommended: Scan-to-Create (one command)

```bash theme={null}
mibyan gateway setup
```

Select **Feishu / Lark** and scan the QR code with your Feishu or Lark mobile app. Mibyan will automatically create a bot application with the correct permissions and save the credentials.

### Alternative: Manual Setup

If scan-to-create is not available, the wizard falls back to manual input:

1. Open the Feishu or Lark developer console:
   * Feishu: [https://open.feishu.cn/](https://open.feishu.cn/)
   * Lark: [https://open.larksuite.com/](https://open.larksuite.com/)
2. Create a new app.
3. In **Credentials & Basic Info**, copy the **App ID** and **App Secret**.
4. Enable the **Bot** capability for the app.
5. Run `mibyan gateway setup`, select **Feishu / Lark**, and enter the credentials when prompted.

<Warning>
  Keep the App Secret private. Anyone with it can impersonate your app.
</Warning>

### Configure Permissions

In the Feishu developer console, go to **Permission Management** and add the following scopes. You can bulk-import them in the permissions page.

**Required permissions:**

| Scope | Purpose |
| - | - |
| `im:message` | Receive and read messages |
| `im:message:send_as_bot` | Send messages as the bot |
| `im:resource` | Access images, files, and audio sent by users |
| `im:chat` | Access chat/group metadata |
| `im:chat:readonly` | Read chat list and membership |

**Recommended permissions (for full functionality):**

| Scope | Purpose |
| - | - |
| `im:message.reactions:readonly` | Receive emoji reaction events |
| `admin:app.info:readonly` | Auto-detect bot identity for @mention gating |
| `contact:user.id:readonly` | Resolve user IDs for allowlist matching |

### Configure Events

In **Events and Callbacks**:

1. Set the connection mode to **Long Connection (WebSocket)** (recommended) or configure a webhook URL
2. In the **Event Configuration** tab, subscribe to:
   * `im.message.receive_v1` — required for receiving messages
3. In the **Callback Configuration** tab (a separate tab from events), set the same connection mode and add the `card.action.trigger` callback — required for the approval / update-prompt buttons. See [Required Feishu App Configuration](#required-feishu-app-configuration).

### Publish the App

After configuring permissions and events, go to **Version Management** and publish a new version of the app. The permissions won't take effect until a version is published and approved (for enterprise apps, this may require admin approval).

## Step 2: Choose a Connection Mode

### Recommended: WebSocket mode

Use WebSocket mode when Mibyan runs on your laptop, workstation, or a private server. No public URL is required. The official Lark SDK opens and maintains a persistent outbound WebSocket connection with automatic reconnection.

```bash theme={null}
FEISHU_CONNECTION_MODE=websocket
```

**Requirements:** The `websockets` Python package must be installed. The SDK handles connection lifecycle, heartbeats, and auto-reconnection internally.

**How it works:** The adapter runs the Lark SDK's WebSocket client in a background executor thread. Inbound events (messages, reactions, card actions) are dispatched to the main asyncio loop. On disconnect, the SDK will attempt to reconnect automatically. If the link dies outright (the SDK's retry ladder gives up or the client thread exits), Mibyan' supervisor rebuilds the client with capped backoff. While a link is down, `mibyan gateway status` shows the platform as `retrying` until the connection is re-established.

### Optional: Webhook mode

Use webhook mode only when you already run Mibyan behind a reachable HTTP endpoint.

```bash theme={null}
FEISHU_CONNECTION_MODE=webhook
```

In webhook mode, Mibyan starts an HTTP server (via `aiohttp`) and serves a Feishu endpoint at:

```text theme={null}
/feishu/webhook
```

**Requirements:** The `aiohttp` Python package must be installed.

You can customize the webhook server bind address and path:

```bash theme={null}
FEISHU_WEBHOOK_HOST=127.0.0.1   # default: 127.0.0.1
FEISHU_WEBHOOK_PORT=8765         # default: 8765
FEISHU_WEBHOOK_PATH=/feishu/webhook  # default: /feishu/webhook
```

When Feishu sends a URL verification challenge (`type: url_verification`), the webhook responds automatically so you can complete the subscription setup in the Feishu developer console. The challenge response is gated on `FEISHU_VERIFICATION_TOKEN` when set — challenge requests with a missing or mismatched token are rejected so an unauthenticated remote cannot prove endpoint control by echoing attacker-controlled challenge data.

## Step 3: Configure Mibyan

### Option A: Interactive Setup

```bash theme={null}
mibyan gateway setup
```

Select **Feishu / Lark** and fill in the prompts.

### Option B: Manual Configuration

Add the following to `~/.mibyan/.env`:

```bash theme={null}
FEISHU_APP_ID=cli_xxx
FEISHU_APP_SECRET=secret_xxx
FEISHU_DOMAIN=feishu
FEISHU_CONNECTION_MODE=websocket

# Optional but strongly recommended
FEISHU_ALLOWED_USERS=ou_xxx,ou_yyy
FEISHU_HOME_CHANNEL=oc_xxx
```

`FEISHU_DOMAIN` accepts:

* `feishu` for Feishu China
* `lark` for Lark international

## Step 4: Start the Gateway

```bash theme={null}
mibyan gateway
```

Then message the bot from Feishu/Lark to confirm that the connection is live.

## Home Chat

Use `/set-home` in a Feishu/Lark chat to mark it as the home channel for cron job results and cross-platform notifications.

You can also preconfigure it:

```bash theme={null}
FEISHU_HOME_CHANNEL=oc_xxx
```

## Security

### User Allowlist

For production use, set an allowlist of Feishu Open IDs:

```bash theme={null}
FEISHU_ALLOWED_USERS=ou_xxx,ou_yyy
```

If you leave the allowlist empty, anyone who can reach the bot may be able to use it. In group chats, the allowlist is checked against the sender's open\_id before the message is processed.

### Webhook Encryption Key

When running in webhook mode, set an encryption key to enable signature verification of inbound webhook payloads:

```bash theme={null}
FEISHU_ENCRYPT_KEY=your-encrypt-key
```

This key is found in the **Event Subscriptions** section of your Feishu app configuration. When set, the adapter verifies every webhook request using the signature algorithm:

```
SHA256(timestamp + nonce + encrypt_key + body)
```

The computed hash is compared against the `x-lark-signature` header using timing-safe comparison. Requests with invalid or missing signatures are rejected with HTTP 401.

<Tip>
  In WebSocket mode, signature verification is handled by the SDK itself, so `FEISHU_ENCRYPT_KEY` is optional. In webhook mode, it is strongly recommended for production.
</Tip>

### Verification Token

An additional layer of authentication that checks the `token` field inside webhook payloads:

```bash theme={null}
FEISHU_VERIFICATION_TOKEN=your-verification-token
```

This token is also found in the **Event Subscriptions** section of your Feishu app. When set, every inbound webhook payload must contain a matching `token` in its `header` object. Mismatched tokens are rejected with HTTP 401.

Both `FEISHU_ENCRYPT_KEY` and `FEISHU_VERIFICATION_TOKEN` can be used together for defense in depth.

## Group Message Policy

The `FEISHU_GROUP_POLICY` environment variable controls whether and how Mibyan responds in group chats:

```bash theme={null}
FEISHU_GROUP_POLICY=allowlist   # default
```

| Value | Behavior |
| - | - |
| `open` | Mibyan responds to @mentions from any user in any group. |
| `allowlist` | Mibyan only responds to @mentions from users listed in `FEISHU_ALLOWED_USERS`. |
| `disabled` | Mibyan ignores all group messages entirely. |

In all modes, the bot must be explicitly @mentioned (or @all) in the group before the message is processed. Direct messages always bypass this gate.

With the default `allowlist` policy and an empty `FEISHU_ALLOWED_USERS`, every human group message is rejected while DMs keep working. The first such drop is logged once at `WARNING` with the keys to set; later drops are `DEBUG`. Under a [multiplexed gateway](/desktop/user-guide/multi-profile-gateways), each profile reads only its **own** `.env` — a `FEISHU_GROUP_POLICY=open` in the default profile's `.env` does not apply to a secondary profile's bot. Put `FEISHU_GROUP_POLICY` / `FEISHU_ALLOWED_USERS` in `profiles/<name>/.env`, or use `group_rules` in that profile's `config.yaml`.

Set `FEISHU_REQUIRE_MENTION=false` to let Mibyan read all group traffic without requiring an @mention:

```bash theme={null}
FEISHU_REQUIRE_MENTION=false
```

For per-chat control, set `require_mention` on a `group_rules` entry — see [Per-Group Access Control](#per-group-access-control) below.

### Bot Identity

Mibyan auto-detects the bot's `open_id` and display name on startup. You only need to set these manually when auto-detection cannot reach the Feishu API, or when your app uses tenant-scoped user IDs:

```bash theme={null}
FEISHU_BOT_OPEN_ID=ou_xxx     # only when auto-detection fails
FEISHU_BOT_USER_ID=xxx        # required if your app uses sender_id_type=user_id
FEISHU_BOT_NAME=MyBot         # only when auto-detection fails
```

## Bot-to-Bot Messaging

By default Mibyan ignores messages sent by other bots. Enable bot-to-bot messaging when you want Mibyan to participate in A2A orchestration or receive notifications from other bots in the same group.

```bash theme={null}
FEISHU_ALLOW_BOTS=mentions   # default: none
```

| Value | Behavior |
| - | - |
| `none` | Ignore all messages from other bots (default). |
| `mentions` | Accept only when the peer bot @mentions Mibyan. |
| `all` | Accept every peer bot message. |

Also configurable as `feishu.allow_bots` in `config.yaml` (env wins when both are set).

Peer bots do not need to be added to `FEISHU_ALLOWED_USERS` — that allowlist applies to human senders only.

Grant the `application:bot.basic_info:read` scope to display peer bot names; without it, peer bots still route correctly but appear as their `open_id`.

## Interactive Card Actions

When users click buttons or interact with interactive cards sent by the bot, the adapter routes these as synthetic `/card` command events:

* Button clicks become: `/card button {"key": "value", ...}`
* The action's `value` payload from the card definition is included as JSON.
* Card actions are deduplicated with a 15-minute window to prevent double processing.

Gateway-driven update prompts use a native Feishu `Yes` / `No` card instead of falling back to plain text replies. When `mibyan update --gateway` needs confirmation, the adapter records the selected answer in Mibyan's `.update_response` file and replaces the card inline with a resolved state.

Card action events are dispatched with `MessageType.COMMAND`, so they flow through the normal command processing pipeline.

This is also how **command approval** works — when the agent needs to run a dangerous command, it sends an interactive card with Allow Once / Session / Always / Deny buttons. The user clicks a button, and the card action callback delivers the approval decision back to the agent.

### Required Feishu App Configuration

Interactive cards need the following configuration in the Feishu Developer Console. The usual symptom of a gap here is error **200340** when users click card buttons.

1. **Subscribe to the card action callback (not an event):**
   In **Development Configuration > Events and Callbacks**, open the **Callback Configuration** tab — it is separate from the **Event Configuration** tab where `im.message.receive_v1` lives — and add `card.action.trigger` under *Subscribed Callbacks*. Adding it as an event does not deliver button clicks.

2. **Set the callback delivery mode:**
   On the same tab choose **Long Connection** when Mibyan runs in `websocket` mode (the Lark SDK receives the callback on the existing connection), or enter the request URL in webhook mode (the same endpoint as your event webhook, e.g. `https://your-server:8765/feishu/webhook`). Feishu must be able to reach and resolve that URL; otherwise clicks fail with 200342/200343.

3. **Enable the Interactive Card capability:**
   In **App Features > Bot**, ensure the **Interactive Card** toggle is enabled.

4. **Publish a new app version:**
   Callback changes only take effect after **Version Management > Create version** is published (and approved, for enterprise apps). Feishu's own description of 200340 is "the application has not configured the card callback address or the configured address is invalid … ensure that you have created and published the latest version of the app".

<Warning>
  Without a published card callback, Feishu will still successfully *send* interactive cards (sending only requires `im:message:send` permission), but clicking any button returns error 200340. The card appears to work — the error only surfaces when a user interacts with it, and the click never reaches Mibyan (nothing is logged), because Feishu rejects it before delivering the callback.
</Warning>

Error codes 200672 / 200673 indicate the callback *did* reach Mibyan and Feishu rejected the response; if you see them, please file an issue with the matching `gateway.log` lines.

## Document Comment Intelligent Reply

Beyond chat, the adapter can also answer `@`-mentions left on **Feishu/Lark documents**. When a user comments on a document (local text selection or whole-doc comment) and @-mentions the bot, Mibyan reads the document plus the surrounding comment thread and posts an LLM reply inline on the thread.

Powered by the `drive.notice.comment_add_v1` event, the handler:

* Fetches the document content and comment timeline in parallel (20 messages for whole-doc threads, 12 for local-selection threads).
* Runs the agent with the `feishu_doc` + `feishu_drive` toolsets scoped to that single comment session.
* Chunks replies at 4000 chars and posts them back as threaded replies.
* Caches per-document sessions for 1 hour with a 50-message cap so follow-up comments on the same doc keep context.

### 3-Tier Access Control

Document-comment replies are **explicit-grant only** — there is no implicit allow-all mode. Permissions resolve in this order (first match wins, per field):

1. **Exact doc** — rule scoped to a specific document token.
2. **Wildcard** — rule that matches a pattern of docs.
3. **Top-level** — default rule for the workspace.

Two policies are available per rule:

* **`allowlist`** — a static list of users / tenants.
* **`pairing`** — static list ∪ runtime-approved store. Useful for rollouts where moderators can grant access live.

Rules live in `~/.mibyan/feishu_comment_rules.json` (pairing grants in `~/.mibyan/feishu_comment_pairing.json`) with mtime-cached hot-reload — edits take effect on the next comment event without restarting the gateway.

CLI:

```bash theme={null}
# Inspect current rules and pairing state
python -m gateway.platforms.feishu_comment_rules status

# Simulate an access check for a specific doc + user
python -m gateway.platforms.feishu_comment_rules check <fileType:fileToken> <user_open_id>

# Manage pairing grants at runtime
python -m gateway.platforms.feishu_comment_rules pairing list
python -m gateway.platforms.feishu_comment_rules pairing add <user_open_id>
python -m gateway.platforms.feishu_comment_rules pairing remove <user_open_id>
```

### Required Feishu App Configuration

On top of the chat/card permissions already granted, add the drive comment event:

* Subscribe to `drive.notice.comment_add_v1` in **Event Subscriptions**.
* Grant the `docs:doc:readonly` and `drive:drive:readonly` scopes so the handler can read document content.

## Meeting Invitation Events

You can invite the Mibyan Feishu/Lark bot into a video meeting the same way you invite a human participant. When the bot receives the meeting invitation event, Mibyan can automatically start an agent turn that attempts to join the meeting.

Powered by the `vc.bot.meeting_invited_v1` event, the flow is:

* A user invites the bot to a Feishu/Lark video meeting.
* Feishu/Lark sends Mibyan the meeting invitation event.
* Mibyan extracts the inviter, meeting topic, and meeting number.
* If the inviter is authorized by the normal gateway allowlist or pairing policy, the agent receives the meeting number and tries to join automatically.
* If the invite is malformed, or the agent cannot join, Mibyan drops the event or replies to the inviter with a concise explanation.

Malformed invitations that do not include both an inviter and a `meeting_no` are ignored.

### Required Feishu App Configuration

On top of the chat/card permissions already granted, add the video-meeting invitation event:

* Subscribe to `vc.bot.meeting_invited_v1` in **Event Subscriptions**.
* Enable the Video Conferencing permission scope prompted by the Feishu/Lark developer console for that event.
* Keep `im:message` and `im:message:send_as_bot` enabled so Mibyan can reply to the inviter.
* Ensure the gateway user allowlist or pairing policy authorizes the inviter. Meeting invitations do not bypass normal gateway access checks.

## Media Support

### Inbound (receiving)

The adapter receives and caches the following media types from users:

| Type | Extensions | How it's processed |
| - | - | - |
| **Images** | .jpg, .jpeg, .png, .gif, .webp, .bmp | Downloaded via Feishu API and cached locally |
| **Audio** | .ogg, .mp3, .wav, .m4a, .aac, .flac, .opus, .webm | Downloaded and cached; small text files are auto-extracted |
| **Video** | .mp4, .mov, .avi, .mkv, .webm, .m4v, .3gp | Downloaded and cached as documents |
| **Files** | .pdf, .doc, .docx, .xls, .xlsx, .ppt, .pptx, and more | Downloaded and cached as documents |

Media from rich-text (post) messages is also extracted and cached — both inline images/files inside the post body and attachments the composer sends in the top-level `files` list (a caption plus a file in one bubble). Every attachment is collected; folder entries are skipped, and each one leaves an `[Attachment: <name>]` marker in the text.

For small text-based documents (.txt, .md), the file content is automatically appended after the message text so the agent can read it directly without needing tools — the caption you typed alongside the file stays in place.

### Outbound (sending)

| Method | What it sends |
| - | - |
| `send` | Text or rich post messages (auto-detected based on markdown content) |
| `send_image` / `send_image_file` | Uploads image to Feishu, then sends as native image bubble (with optional caption) |
| `send_document` | Uploads file to Feishu API, then sends as file attachment |
| `send_voice` | Uploads audio file as a Feishu file attachment |
| `send_video` | Uploads video and sends as native media message |
| `send_animation` | GIFs are downgraded to file attachments (Feishu has no native GIF bubble) |

File upload routing is automatic based on extension:

* `.ogg`, `.opus` → uploaded as `opus` audio
* `.mp4`, `.mov`, `.avi`, `.m4v` → uploaded as `mp4` media
* `.pdf`, `.doc(x)`, `.xls(x)`, `.ppt(x)` → uploaded with their document type
* Everything else → uploaded as a generic stream file

## Markdown Rendering and Post Fallback

When outbound text contains markdown formatting (headings, bold, lists, code blocks, links, etc.), the adapter automatically sends it as a Feishu **post** message with an embedded `md` tag rather than as plain text. This enables rich rendering in the Feishu client.

If the Feishu API rejects the post payload (e.g., due to unsupported markdown constructs), the adapter automatically falls back to sending as plain text with markdown stripped. This two-stage fallback ensures messages are always delivered.

Plain text messages (no markdown detected) are sent as the simple `text` message type.

## Processing Status Reactions

While the agent is working, the bot shows a `Typing` reaction on your message. It's cleared when the reply arrives, or replaced with `CrossMark` if processing failed.

Set `FEISHU_REACTIONS=false` to turn it off.

## Burst Protection and Batching

The adapter includes debouncing for rapid message bursts to avoid overwhelming the agent:

### Text Batching

When a user sends multiple text messages in quick succession, they are merged into a single event before being dispatched:

| Setting | Env Var | Default |
| - | - | - |
| Quiet period | `mibyan_FEISHU_TEXT_BATCH_DELAY_SECONDS` | 0.6s |
| Max messages per batch | `mibyan_FEISHU_TEXT_BATCH_MAX_MESSAGES` | 8 |
| Max characters per batch | `mibyan_FEISHU_TEXT_BATCH_MAX_CHARS` | 4000 |

### Media Batching

Multiple media attachments sent in quick succession (e.g., dragging several images) are merged into a single event:

| Setting | Env Var | Default |
| - | - | - |
| Quiet period | `mibyan_FEISHU_MEDIA_BATCH_DELAY_SECONDS` | 0.8s |

### Per-Chat Serialization

Messages within the same chat are processed serially (one at a time) to maintain conversation coherence. Each chat has its own lock, so messages in different chats are processed concurrently.

## Rate Limiting (Webhook Mode)

In webhook mode, the adapter enforces per-IP rate limiting to protect against abuse:

* **Window:** 60-second sliding window
* **Limit:** 120 requests per window per (app\_id, path, IP) triple
* **Tracking cap:** Up to 4096 unique keys tracked (prevents unbounded memory growth)

Requests that exceed the limit receive HTTP 429 (Too Many Requests).

### Webhook Anomaly Tracking

The adapter tracks consecutive error responses per IP address. After 25 consecutive errors from the same IP within a 6-hour window, a warning is logged. This helps detect misconfigured clients or probing attempts.

Additional webhook protections:

* **Body size limit:** 1 MB maximum
* **Body read timeout:** 30 seconds
* **Content-Type enforcement:** Only `application/json` is accepted

## WebSocket Tuning

When using `websocket` mode, you can customize reconnect and ping behavior:

```yaml theme={null}
platforms:
  feishu:
    extra:
      ws_reconnect_interval: 120   # Seconds between reconnect attempts (default: 120)
      ws_ping_interval: 30         # Seconds between WebSocket pings (optional; SDK default if unset)
```

| Setting | Config key | Default | Description |
| - | - | - | - |
| Reconnect interval | `ws_reconnect_interval` | 120s | How long to wait between reconnection attempts |
| Ping interval | `ws_ping_interval` | *(SDK default)* | Frequency of WebSocket keepalive pings |

## Per-Group Access Control

Beyond the global `FEISHU_GROUP_POLICY`, you can set fine-grained rules per group chat using `group_rules` in config.yaml:

```yaml theme={null}
platforms:
  feishu:
    extra:
      default_group_policy: "open"     # Default for groups not in group_rules
      admins:                          # Users who can manage bot settings
        - "ou_admin_open_id"
      group_rules:
        "oc_group_chat_id_1":
          policy: "allowlist"          # open | allowlist | blacklist | admin_only | disabled
          allowlist:
            - "ou_user_open_id_1"
            - "ou_user_open_id_2"
        "oc_group_chat_id_2":
          policy: "admin_only"
        "oc_group_chat_id_3":
          policy: "blacklist"
          blacklist:
            - "ou_blocked_user"
        "oc_free_chat":
          policy: "open"
          require_mention: false       # overrides FEISHU_REQUIRE_MENTION for this chat
```

| Policy | Description |
| - | - |
| `open` | Anyone in the group can use the bot |
| `allowlist` | Only users in the group's `allowlist` can use the bot |
| `blacklist` | Everyone except users in the group's `blacklist` can use the bot |
| `admin_only` | Only users in the global `admins` list can use the bot in this group |
| `disabled` | Bot ignores all messages in this group |

Set `require_mention: false` on a `group_rules` entry to skip the @-mention requirement for that specific chat. When omitted, the chat inherits the global `FEISHU_REQUIRE_MENTION` value.

Groups not listed in `group_rules` fall back to `default_group_policy` (defaults to the value of `FEISHU_GROUP_POLICY`).

## Deduplication

Inbound messages are deduplicated using message IDs with a 24-hour TTL. The dedup state is persisted across restarts to `~/.mibyan/feishu_seen_message_ids.json`.

| Setting | Env Var | Default |
| - | - | - |
| Cache size | `mibyan_FEISHU_DEDUP_CACHE_SIZE` | 2048 entries |

## All Environment Variables

| Variable | Required | Default | Description |
| - | - | - | - |
| `FEISHU_APP_ID` | ✅ | — | Feishu/Lark App ID |
| `FEISHU_APP_SECRET` | ✅ | — | Feishu/Lark App Secret |
| `FEISHU_DOMAIN` | — | `feishu` | `feishu` (China) or `lark` (international) |
| `FEISHU_CONNECTION_MODE` | — | `websocket` | `websocket` or `webhook` |
| `FEISHU_ALLOWED_USERS` | — | *(empty)* | Comma-separated open\_id list for user allowlist |
| `FEISHU_ALLOW_BOTS` | — | `none` | Accept messages from other bots: `none`, `mentions`, or `all` |
| `FEISHU_REQUIRE_MENTION` | — | `true` | Whether group messages must @mention the bot |
| `FEISHU_HOME_CHANNEL` | — | — | Chat ID for cron/notification output |
| `FEISHU_ENCRYPT_KEY` | — | *(empty)* | Encrypt key for webhook signature verification |
| `FEISHU_VERIFICATION_TOKEN` | — | *(empty)* | Verification token for webhook payload auth |
| `FEISHU_GROUP_POLICY` | — | `allowlist` | Group message policy: `open`, `allowlist`, `disabled` |
| `FEISHU_BOT_OPEN_ID` | — | *(empty)* | Bot's open\_id (for @mention detection) |
| `FEISHU_BOT_USER_ID` | — | *(empty)* | Bot's user\_id (for @mention detection) |
| `FEISHU_BOT_NAME` | — | *(empty)* | Bot's display name (for @mention detection) |
| `FEISHU_WEBHOOK_HOST` | — | `127.0.0.1` | Webhook server bind address |
| `FEISHU_WEBHOOK_PORT` | — | `8765` | Webhook server port |
| `FEISHU_WEBHOOK_PATH` | — | `/feishu/webhook` | Webhook endpoint path |
| `mibyan_FEISHU_DEDUP_CACHE_SIZE` | — | `2048` | Max deduplicated message IDs to track |
| `mibyan_FEISHU_TEXT_BATCH_DELAY_SECONDS` | — | `0.6` | Text burst debounce quiet period |
| `mibyan_FEISHU_TEXT_BATCH_MAX_MESSAGES` | — | `8` | Max messages merged per text batch |
| `mibyan_FEISHU_TEXT_BATCH_MAX_CHARS` | — | `4000` | Max characters merged per text batch |
| `mibyan_FEISHU_MEDIA_BATCH_DELAY_SECONDS` | — | `0.8` | Media burst debounce quiet period |

WebSocket and per-group ACL settings are configured via `config.yaml` under `platforms.feishu.extra` (see [WebSocket Tuning](#websocket-tuning) and [Per-Group Access Control](#per-group-access-control) above).

## Troubleshooting

| Problem | Fix |
| - | - |
| `lark-oapi not installed` | Install the SDK: `python -c "import pm; pm.sync_venv(['feishu'], explicit=True)"` |
| `websockets not installed; websocket mode unavailable` | Install websockets: `mibyan pm repair` |
| `aiohttp not installed; webhook mode unavailable` | Install aiohttp: `python -c "import pm; pm.sync_venv(['messaging'], explicit=True)"` |
| `FEISHU_APP_ID or FEISHU_APP_SECRET not set` | Set both env vars or configure via `mibyan gateway setup` |
| `Another local Mibyan gateway is already using this Feishu app_id` | Only one Mibyan instance can use the same app\_id at a time. Stop the other gateway first. |
| Bot doesn't respond in groups | Ensure the bot is @mentioned, check `FEISHU_GROUP_POLICY`, and verify the sender is in `FEISHU_ALLOWED_USERS` if policy is `allowlist` |
| `Webhook rejected: invalid verification token` | Ensure `FEISHU_VERIFICATION_TOKEN` matches the token in your Feishu app's Event Subscriptions config |
| `Webhook rejected: invalid signature` | Ensure `FEISHU_ENCRYPT_KEY` matches the encrypt key in your Feishu app config |
| Post messages show as plain text | The Feishu API rejected the post payload; this is normal fallback behavior. Check logs for details. |
| Images/files not received by bot | Grant `im:message` and `im:resource` permission scopes to your Feishu app |
| Bot identity not auto-detected | Usually a transient network issue reaching Feishu's bot info endpoint. Set `FEISHU_BOT_OPEN_ID` and `FEISHU_BOT_NAME` manually as a workaround. |
| Peer bot messages still ignored after enabling `FEISHU_ALLOW_BOTS` | Mibyan can't identify itself yet — set `FEISHU_BOT_OPEN_ID` (and `FEISHU_BOT_USER_ID` if your app uses `sender_id_type=user_id`). |
| Peer bots show as `ou_xxxxxx` instead of by name | Grant the `application:bot.basic_info:read` scope. |
| Error 200340 (also seen as 220340) when clicking approval buttons | Feishu has no valid card callback for the published app version: add `card.action.trigger` under the **Callback Configuration** tab (not Event Configuration), pick Long Connection / the request URL, enable **Interactive Card**, then publish a new version. See [Required Feishu App Configuration](#required-feishu-app-configuration). The click never reaches Mibyan, so nothing appears in `gateway.log`. |
| Error 200342 / 200343 when clicking approval buttons | Webhook mode: Feishu cannot connect to / resolve the callback request URL. Fix the URL or switch to Long Connection. |
| `Webhook rate limit exceeded` | More than 120 requests/minute from the same IP. This is usually a misconfiguration or loop. |

## Toolset

Feishu / Lark uses the `mibyan-feishu` platform preset, which includes the same core tools as Telegram and other gateway-based messaging platforms.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.