Lark guide

Bring your own Lark (open.larksuite.com) or Feishu (open.feishu.cn) custom app: registration proves the credentials, you paste one URL into the console, and the bot answers as your agent in p2p chats and groups.

Prerequisites

  • A custom app in the Lark Developer Console (or the Feishu console) with the Bot capability enabled and these permissions granted:
ScopeWhat stops working without it
im:message, im:message.p2p_msg:readonlythe bot receives nothing in a direct chat
im:message.group_at_msg:readonlythe bot receives nothing when mentioned in a group
im:message.group_msgordinary group follow-ups without a bot mention are not delivered; requires administrator approval
im:message:send_as_botthe bot cannot reply
im:message:updatea streamed reply cannot be revised — it arrives as one block at the end
im:message:recalla reply that gets shorter leaves its stale tail behind
im:message.reactions:write_onlyno working markers (⏳ → ✅)
im:message.reactions:reada marker Lark refuses to take down cannot be checked, so a turn whose ⏳ is already gone never gets its ✅

Permissions take effect when you publish an app version. Request the all-group-messages scope only when you want group conversations to continue without a mention; it permits receiving messages in every group containing the bot. With mention-only permission, mention the bot on every turn. See the official SDK permission guidance.

  • Its App ID and App Secret (Credentials & Basic Info) and the Verification Token from Event Subscriptions. If you set an Encrypt Key there, pass it too — deliveries then arrive encrypted and signed.
  • An AgentSky API token with write scope.

Register the channel app

The developer console walks the same checklist, or over the API:

bash
curl -s -X POST https://api.agentsky.dev/v1/channels/apps \
  -H "Authorization: Bearer $AST_TOKEN" -H 'content-type: application/json' \
  -d '{"platform": "lark", "label": "My Lark app", "credentials": {"app_id": "cli_...", "app_secret": "...", "verification_token": "...", "domain": "lark"}}'
# -> setup: { "events_url": "https://.../webhooks/lark/app_..." }

Registration mints a tenant token and reads the bot's identity — a wrong secret answers 400 lark_error. The stored credential keys grow bot_open_id and bot_name. domain is lark (default) or feishu; encrypt_key is optional.

Finish in the console. Lark has no API for event subscriptions: paste setup.events_url as the Request URL under Event Subscriptions (Lark verifies it with a challenge immediately), add the im.message.receive_v1 event, then publish an app version so the bot is available to your organization.

Connect

bash
curl -s -X POST https://api.agentsky.dev/v1/channels/connections \
  -H "Authorization: Bearer $AST_TOKEN" -H 'content-type: application/json' \
  -d '{"platform": "lark", "app": "app_...", "destination": {"session": "sess-..."}}'
# -> connect: { "url": "https://applink.larksuite.com/client/bot/open?appId=cli_...", "code": "LINK:…", "app_id": "cli_...", "expires_at": "…" }

connect.url opens the bot's chat inside Lark; the end user sends connect.code there and the chat claims the connection. To connect a group, add the bot to the group and send the code in the group with an @mention of the bot. The connection's thread is then lark:{app}:GROUP:{chat_id} and the service subscribes that conversation after the claim. With administrator-approved im:message.group_msg permission, subsequent messages need no mention; with mention-only permission, every follow-up must mention the bot. Unconnected, unmentioned groups are not routed to an agent. Codes expire after 15 minutes, and a code minted for your app is refused if sent to any other bot. The hosted connect page renders this ceremony for you.

Capabilities

threadsreactionsmarkersproactivemarkdownmodalsephemeralstreaming
✗✓✓✓✓✗✗✓

Markdown renders as an interactive card (Lark's markdown element: bold, italic, links, inline code, code blocks, lists, headings), which is also what lets replies be edited in place. A raw part is sent as a plain text message. Working markers use Lark's reaction set — OnIt while working, DONE on completion, CrossMark on failure. Thread ids are lark:P2P:{chat_id} / lark:GROUP:{chat_id} (with the app id as the second segment on your own app).

Troubleshooting

  • The console refuses the Request URL — the app was registered with a different verification token than the console shows; rotate the app's credentials (PATCH /v1/channels/apps/{id}) with the current token and try again.
  • Nothing arrives from a group — the bot only receives group messages that @mention it unless the app holds the receive-all-group-messages scope; mention the bot, and check the event subscription includes im.message.receive_v1.
  • Replies fail with a permission error — grant im:message:send_as_bot (and the reactions scope for markers) and re-publish the app version; permissions take effect on publish.
  • Encrypted deliveries answer 401 — the encrypt_key credential does not match the console's Encrypt Key.