Lark (international) and Feishu (China) are the same platform on different domains — Lark lives atDocumentation Index
Fetch the complete documentation index at: https://agents.craft.do/docs/llms.txt
Use this file to discover all available pages before exploring further.
open.larksuite.com, Feishu at open.feishu.cn. They share the same SDK, message types, and event protocol. A Custom App is registered with one of them; pick the region you need at setup time.
Craft Agent uses the official @larksuiteoapi/node-sdk’s long-connection (WebSocket) mode — no public webhook URL or reverse tunnel needed. Same lifecycle as the Telegram adapter, just talking to Lark instead.
Two ways to set up
Recommended: Built for agents quick-create
On the Open Platform’s app-creation page, look for the “Built for agents. Ready to connect” banner with a Create button. Clicking it produces an app with the right permissions and event settings pre-configured — you skip the scope toggles and event-subscription steps entirely.Then jump straight to Connect in the App below to paste your App ID and Secret into Craft Agent.
Manual setup
Create a Custom App and configure scopes + events yourself. Useful if the agent banner isn’t visible in your tenant’s UI yet, or if you want explicit control over which permissions you grant.Full walkthrough below.
You still copy App ID + Secret either way. Lark/Feishu issue per-tenant credentials regardless of which create flow you use — the agent quick-create path saves you the permissions and events configuration, not the credential paste.
Create an App
Open the Open Platform
- Lark: open.larksuite.com
- Feishu: open.feishu.cn
Copy App ID and App Secret
On the app’s home page, copy the App ID (starts with
cli_) and the App Secret (32-character string). Treat the secret like a password.Enable required scopes
Under Permissions & Scopes, enable:
im:message— read message eventsim:message.group_at_msg— receive @mentions in groupsim:message:send_as_bot— send messages as the bot
Subscribe to message events in long-connection mode
Under Events & Callbacks, set the delivery method to Long connection mode (NOT webhooks). Then add a subscription for:
im.message.receive_v1
Connect in the App
Open Settings → Messaging in Craft Agent
You’ll see a third tile alongside Telegram and WhatsApp: Lark / Feishu.
Pick your region
Lark (international) uses
open.larksuite.com; Feishu (China) uses open.feishu.cn. A bot belongs to one or the other — they’re separate ecosystems.Paste App ID + App Secret, then Test
Craft Agent exchanges them for a
tenant_access_token. On success the button shows a green check; on failure you’ll see Lark’s error message verbatim.First Conversation
Generate a code in Craft Agent
Open any session’s menu → Pair with Messaging → Lark. Copy the 6-digit code.
Group chats
In groups, the bot only receives messages where it’s @mentioned — that’s Lark’s default scope behaviour forim:message.group_at_msg. Without an @mention, the event isn’t delivered server-side, so there’s nothing for the adapter to drop. Messages addressed to the bot work the same way as DMs.
Rich Text
The agent’s responses preserve common formatting when sent to Lark:- bold, italic,
strikethroughrender natively via Lark’spostmessage type [Links](https://example.com)are clickable- Fenced code blocks (
```python ... ```) render with their language tag - Paragraph breaks are preserved
- Headers (
#,##, …) — Larkposthas no header element - Bullet / numbered lists — bullets appear as plain
•or1.prefixes - Tables — rendered as space-padded plain text
- Inline
`code`— rendered as bold text (Larkposthas no inline-code element)
Rich Cards
When the agent needs your input mid-flow (e.g. plan approval), buttons render as a Lark interactive card with native action buttons. Tap a button — the agent receives the press and proceeds. The card auto-clears once the choice is processed. Phase-2 limits:- Up to 10 buttons per card
- Button labels truncated at 30 characters
Attachments
Both directions are supported in DMs and group @mentions:- Inbound: send images and files to the bot. They’re downloaded server-side and made available to the agent under the session’s working directory.
- Outbound: the agent can send images and documents back. Captions accompanying a file are sent as a follow-up text message (Lark API can’t combine caption + file in a single message).
- Max attachment size: 20 MB (matches the renderer’s read limit)
- Audio, video, and stickers are dropped with a polite “unsupported attachment” log line
Limitations
- Lark and Feishu are separate domains — a bot belongs to one or the other, not both
- Bot only sees @mentions in groups (Lark’s default
im:message.group_at_msgscope; cannot be widened without enterprise approvals) - Edits to messages older than 24 hours are silently dropped (Lark API limit)
- Markdown headers, lists, and tables are rendered as plain text within
post(Larkposthas no native equivalents)
Troubleshooting
- “Bot doesn’t receive messages” — verify
im:messageis enabled andim.message.receive_v1is subscribed under Events & Callbacks. Double-check the delivery mode is Long connection, not webhooks. - “Connection failed during Test” — if the App Secret was regenerated in the Open Platform, copy the new value. If you switched the app’s tenant, the old credentials are revoked.
- “Bot received my DM but ignores my group message” — bot needs the
im:message.group_at_msgscope, AND the message must @mention the bot. - “Cards arrive but button presses don’t reach the agent” — confirm the app is published (or the tenant is in dev-mode). Cards from a draft app can render but card-action callbacks won’t fire.
- “
lark_send_card_failedwithcode: 230099andunknown property, property: elements” — happens when something downstream emits a schema-1.0 card payload under aschema: '2.0'envelope. The fix is to wrap the card body underbody: { elements: [...] }(already in place; this note exists for anyone forking the adapter). - “Can’t send files larger than ~20 MB” — that’s the adapter’s hard cap. Compress or split before sending.
- Logs:
~/.craft-agent/logs/messaging-gateway.log— search forcomponent:"lark-adapter"orevent:"lark_*".