websocket— recommended; Mibyan opens the outbound connection and you do not need a public webhook endpointwebhook— useful when you want Feishu/Lark to push events into your gateway over HTTP
How Mibyan Behaves
This shared-chat behavior is controlled by
config.yaml:
false only if you explicitly want one shared conversation per chat.
Step 1: Create a Feishu / Lark App
Recommended: Scan-to-Create (one command)
Alternative: Manual Setup
If scan-to-create is not available, the wizard falls back to manual input:- Open the Feishu or Lark developer console:
- Feishu: https://open.feishu.cn/
- Lark: https://open.larksuite.com/
- Create a new app.
- In Credentials & Basic Info, copy the App ID and App Secret.
- Enable the Bot capability for the app.
- Run
mibyan gateway setup, select Feishu / Lark, and enter the credentials when prompted.
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:
Recommended permissions (for full functionality):
Configure Events
In Events and Callbacks:- Set the connection mode to Long Connection (WebSocket) (recommended) or configure a webhook URL
- In the Event Configuration tab, subscribe to:
im.message.receive_v1— required for receiving messages
- In the Callback Configuration tab (a separate tab from events), set the same connection mode and add the
card.action.triggercallback — required for the approval / update-prompt buttons. See 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.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.aiohttp) and serves a Feishu endpoint at:
aiohttp Python package must be installed.
You can customize the webhook server bind address and path:
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
Option B: Manual Configuration
Add the following to~/.mibyan/.env:
FEISHU_DOMAIN accepts:
feishufor Feishu Chinalarkfor Lark international
Step 4: Start the Gateway
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:
Security
User Allowlist
For production use, set an allowlist of Feishu Open IDs:Webhook Encryption Key
When running in webhook mode, set an encryption key to enable signature verification of inbound webhook payloads:x-lark-signature header using timing-safe comparison. Requests with invalid or missing signatures are rejected with HTTP 401.
Verification Token
An additional layer of authentication that checks thetoken field inside webhook payloads:
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
TheFEISHU_GROUP_POLICY environment variable controls whether and how Mibyan responds in group chats:
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, 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:
require_mention on a group_rules entry — see Per-Group Access Control below.
Bot Identity
Mibyan auto-detects the bot’sopen_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:
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.
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
valuepayload from the card definition is included as JSON. - Card actions are deduplicated with a 15-minute window to prevent double processing.
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.-
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_v1lives — and addcard.action.triggerunder Subscribed Callbacks. Adding it as an event does not deliver button clicks. -
Set the callback delivery mode:
On the same tab choose Long Connection when Mibyan runs in
websocketmode (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. - Enable the Interactive Card capability: In App Features > Bot, ensure the Interactive Card toggle is enabled.
- 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”.
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_drivetoolsets 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):- Exact doc — rule scoped to a specific document token.
- Wildcard — rule that matches a pattern of docs.
- Top-level — default rule for the workspace.
allowlist— a static list of users / tenants.pairing— static list ∪ runtime-approved store. Useful for rollouts where moderators can grant access live.
~/.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:
Required Feishu App Configuration
On top of the chat/card permissions already granted, add the drive comment event:- Subscribe to
drive.notice.comment_add_v1in Event Subscriptions. - Grant the
docs:doc:readonlyanddrive:drive:readonlyscopes 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 thevc.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.
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_v1in Event Subscriptions. - Enable the Video Conferencing permission scope prompted by the Feishu/Lark developer console for that event.
- Keep
im:messageandim:message:send_as_botenabled 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:
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)
File upload routing is automatic based on extension:
.ogg,.opus→ uploaded asopusaudio.mp4,.mov,.avi,.m4v→ uploaded asmp4media.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 embeddedmd 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 aTyping 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:Media Batching
Multiple media attachments sent in quick succession (e.g., dragging several images) are merged into a single event: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)
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/jsonis accepted
WebSocket Tuning
When usingwebsocket mode, you can customize reconnect and ping behavior:
Per-Group Access Control
Beyond the globalFEISHU_GROUP_POLICY, you can set fine-grained rules per group chat using group_rules in config.yaml:
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.
All Environment Variables
WebSocket and per-group ACL settings are configured via
config.yaml under platforms.feishu.extra (see WebSocket Tuning and Per-Group Access Control above).
Troubleshooting
Toolset
Feishu / Lark uses themibyan-feishu platform preset, which includes the same core tools as Telegram and other gateway-based messaging platforms.
