Feishu Message Types: Receiving, Sending, Stickers, and Thread Replies

Explains which Feishu message types OpenClaw receives and sends, how stickers are handled, and how replies stay attached to threads. Useful for integrators configuring Feishu access and messaging behavior.

Read this when

  • Checking whether Feishu supports a message type
  • Enabling sticker replies or sticker keyword search

What OpenClaw is able to receive from and send to Feishu, how stickers work, and how replies stay attached to threads.

Reading messages and chat information

Feishu plugins installed from npm or ClawHub get the same Feishu access checks that the bundled plugin uses: reading messages, listing reactions and pins, fetching chat and member details, listing directories, and running configured sticker searches. The account, action, and access controls you already have continue to apply. Member lookups in direct chats are still restricted to the current sender, and directory results are still filtered according to the configured policy.

When you need to look up peers live, the channel-list action compares query against user IDs and names, paging through provider results. limit governs matching peers and defaults to 50. A lookup failure is reported if pagination cannot complete within 100 pages, or if the provider hands back an invalid continuation token.

Delegated reads made through an installed plugin need the current Feishu account and conversation context. Once the originating action ends or the plugin is retired, later provider requests are blocked and late results are rejected. Anything already sent to Feishu cannot be recalled.

Supported message types

Receive

  • ✅ Text
  • ✅ Rich text (post)
  • ✅ Images
  • ✅ Files
  • ✅ Audio
  • ✅ Video/media
  • ✅ Stickers

When a sticker arrives, its reusable file_key is exposed to the agent as <sticker key="..."/>. Downloading sticker resources is not supported by Feishu/Lark, so OpenClaw keeps the key and fetches no attachment.

A file that comes with a caption, or several files bundled in one message, arrives as a rich-text post carrying a top-level files[] array. OpenClaw pulls those files down along the same inbound attachment path used for a standalone file message.

Merged-forward messages carry each child's original sender and UTC timestamp where they are available. Sender names follow the account's resolveSenderNames setting; when a name cannot be resolved or lookups are turned off, the sender ID is kept. Mentions inside children stay bound to the original message. Only the first 50 children, in chronological order, get name lookups, which matches the rendered history.

Audio messages received from Feishu/Lark are normalized into media placeholders rather than raw file_key JSON. With tools.media.audio configured, OpenClaw downloads the voice-note resource and runs shared audio transcription ahead of the agent turn, so the agent gets the spoken transcript. Should Feishu supply transcript text in the audio payload itself, that text is used and no further ASR call is made. When no audio transcription provider exists, the agent still gets a <media:audio> placeholder together with the saved attachment, not the raw Feishu resource payload.

Send

  • ✅ Text
  • ✅ Images
  • ✅ Files
  • ✅ Audio
  • ✅ Video/media
  • ✅ Interactive cards (including streaming updates)
  • ✅ Stickers previously received by the same bot (requires actions.sticker)
  • ⚠️ Rich text (post-style formatting; doesn't support full Feishu/Lark authoring capabilities)

Native Feishu/Lark audio bubbles rely on the Feishu audio message type and need Ogg/Opus upload media (file_type: "opus"). Media that is already .opus or .ogg goes out directly as native audio. Other likely audio formats, such as MP3/WAV/M4A, are transcoded with ffmpeg to 48kHz Ogg/Opus only when the reply asks for voice delivery (audioAsVoice / message tool asVoice, including TTS voice-note replies). A plain MP3 attachment is still sent as a regular file. Should ffmpeg be absent or the conversion fail, OpenClaw falls back to a file attachment and records the reason in the log.

Sticker replies

Turn on the sticker action so the agent can resend stickers:

{
  channels: {
    feishu: {
      actions: { sticker: true },
    },
  },
}

To do this for a single account, set channels.feishu.accounts.<id>.actions.sticker: true instead. An account-level actions object replaces the channel-level object rather than merging with it, so repeat every action gate you want to keep. Here reactions stay off while stickers are enabled for work:

{
  channels: {
    feishu: {
      actions: { reactions: false },
      accounts: {
        work: {
          actions: { reactions: false, sticker: true },
        },
      },
    },
  },
}

Send a sticker to that bot first, then ask it to send the sticker again. The shared message tool passes action: "sticker" along with the received file_key in fileId, or the first entry of stickerId. With multiple accounts, use the same accountId that received the sticker.

The only stickers that can be sent are ones that bot has already received. Uploading new stickers, downloading sticker resources, and searching the sticker store are all unsupported.

A curated sticker set lets the agent locate a received sticker by keyword. Start by sending each sticker to the bot and asking it for the received file_key. Then add keys and your own labels to the existing Feishu configuration:

{
  channels: {
    feishu: {
      actions: { sticker: true },
      stickerSets: {
        cli_work: {
          file_received_key: ["thumbs up", "赞", "👍"],
        },
      },
    },
  },
}

Put the bot's real app ID in place of cli_work and the key that bot received in place of file_received_key. stickerSets sits directly under channels.feishu, not inside an account. An account can search only the set that matches its app ID; pointing an account at a different bot does not carry over the previous bot's set. Accounts that use the same bot share its set. Preserve any account-level action gates as described above.

Tell the agent to “send a thumbs up sticker.” It can call the shared message tool with action: "sticker-search", query: "thumbs up", and the accountId it wants, then send a returned fileId with action: "sticker" on that same account. Search works only when stickers are enabled and the bot has a nonempty configured set.

Matching is a case-insensitive substring test against an explicit keyword, Chinese labels and emoji included, in sticker-key order. It does not infer what a sticker means, query Feishu's store, or gather received stickers on its own. Results carry the matching keyword and reusable fileId. No matches yields an empty list; truncated: true signals that matching entries were dropped by the result limit or output budget, so narrow the query to surface the rest.

Limits: 32 bot sets, 256 stickers per set, and 1, 8 keywords per sticker. Store keywords with no leading or trailing whitespace; each must be nonempty and no longer than 64 Unicode characters. File keys must be exactly the keys received from Feishu, at most 512 Unicode characters. A key appears only once in its bot's map. Queries must be nonempty and at most 128 Unicode characters. limit defaults to 5 and takes integers from 1 through 10; search output is also capped at 3 KiB of JSON. Deleting a set removes it from search; no separate sticker database or cache is created.

Threads and replies

  • ✅ Inline replies
  • ✅ Thread replies
  • ✅ Media replies stay thread-aware when replying to a thread message

Topic-group session routing is described in Group session scope and topic threads.

1,167 words · updated Oct 26, 2026