Feishu Integration: Setup, Features, and Configuration for OpenClaw

This page covers the OpenClaw Feishu/Lark plugin, including bot DMs, group chats, streaming cards, and tools for docs and wikis. It guides developers through setup via wizard, QR code, or manual configuration.

Read this when

  • You want to connect a Feishu/Lark bot
  • You are configuring the Feishu channel

OpenClaw integrates with Feishu/Lark, the all-in-one collaboration platform, via the official @openclaw/feishu plugin. This enables bot DMs, group chats, streaming card replies, and tools for Feishu docs, wikis, drives, and Bitable.

Status: bot DMs and group chats are production-ready. WebSocket serves as the default event transport, requiring no public URL; webhook mode remains optional.

Quick start

Note

OpenClaw 2026.5.29 or later is required. Verify with openclaw --version. To upgrade, use openclaw update.

Run the channel setup wizard

openclaw channels login --channel feishu

If the @openclaw/feishu plugin is absent, this installs it, then guides you through configuration:

  • Manual setup: provide an App ID and App Secret from Feishu Open Platform (https://open.feishu.cn) or Lark Developer (https://open.larksuite.com).
  • QR setup: scan a QR code within the Feishu app to generate a bot automatically. This approach restricts DMs to your own account (dmPolicy: "allowlist" with your open_id).

The wizard also prompts for the API domain (Feishu or Lark) and the group policy. Should the domestic Feishu mobile app ignore the QR code, rerun setup and opt for manual setup.

After setup completes, restart the gateway to apply the changes

openclaw gateway restart

Inbound durability

Before agent dispatch, OpenClaw durably queues authenticated im.message.receive_v1 and drive.notice.comment_add_v1 envelopes. In webhook mode, the durable 200 carries x-openclaw-delivery-accepted: durable; verification challenges, non-durable event types, and error responses leave out the marker, letting reverse proxies enforce it to tell durable acceptance apart from a generic 200. Pending or retryable events persist across a Gateway restart, stay serialized per chat or document, and rely on Feishu's event ID to block duplicate queue entries while the active or retained completion record is present.

When a WebSocket event cannot be stored after bounded retries, OpenClaw shuts that socket and initiates a fresh authenticated connection, rather than moving past an uncommitted turn. Other Feishu event types, such as reactions and VC meeting invitations, follow their standard event paths and do not get this durable-queue guarantee.

Access control

Direct messages

Set channels.feishu.dmPolicy (default: pairing) to determine who may DM the bot:

ValueBehavior
"pairing"Unknown users get a pairing code; approve it via CLI
"allowlist"Only users listed in allowFrom can chat
"open"Public DMs; config validation demands allowFrom to contain "*". Non-wildcard entries still restrict access

Approve a pairing request:

openclaw pairing list feishu
openclaw pairing approve feishu <CODE>

Group chats

Group policy (channels.feishu.groupPolicy, default: allowlist):

ValueBehavior
"open"Reply to every message in groups
"allowlist"Reply only to groups in groupAllowFrom or explicitly set under groups.<chat_id>
"disabled"Turn off all group messages; explicit groups.<chat_id> entries cannot override this

Mention requirement (channels.feishu.requireMention):

  • By default, an @mention is needed, except when the effective group policy is "open"; there it defaults to false so messages lacking mentions (like images) still reach the agent.
  • Override by setting true or false explicitly; per-group override: channels.feishu.groups.<chat_id>.requireMention.
  • Broadcast-only @all and @_all do not count as bot mentions. A message mentioning both @all and the bot directly still qualifies as a bot mention.

Group configuration examples

Allow all groups, no @mention required

{
  channels: {
    feishu: {
      groupPolicy: "open", // requireMention defaults to false under "open"
    },
  },
}

Allow all groups, still require @mention

{
  channels: {
    feishu: {
      groupPolicy: "open",
      requireMention: true,
    },
  },
}

Allow specific groups only

{
  channels: {
    feishu: {
      groupPolicy: "allowlist",
      // Group IDs look like: oc_xxx
      groupAllowFrom: ["oc_xxx", "oc_yyy"],
    },
  },
}

In allowlist mode, adding an explicit groups.<chat_id> entry also admits a group. Explicit entries never override groupPolicy: "disabled". Wildcard defaults under groups.* configure matching groups, but they do not admit groups on their own.

{
  channels: {
    feishu: {
      groupPolicy: "allowlist",
      groups: {
        oc_xxx: {
          requireMention: false,
        },
      },
    },
  },
}

Restrict senders within a group

{
  channels: {
    feishu: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["oc_xxx"],
      groups: {
        oc_xxx: {
          // User open_ids look like: ou_xxx
          allowFrom: ["ou_user1", "ou_user2"],
        },
      },
    },
  },
}

channels.feishu.groupSenderAllowFrom applies the same sender allowlist across every group; a group-specific allowFrom overrides it.

Bot-authored messages

By default, Feishu ignores messages from other bots. To enable bot-to-bot group chats, request the im:message.group_at_msg.include_bot:readonly and im:message:readonly scopes for the app, then configure allowBots:

{
  channels: {
    feishu: {
      allowBots: true,
    },
  },
}

Feishu only sends bot-authored group events when another bot mentions this bot. Existing group policy, sender allowlists, and mention requirements remain in effect. OpenClaw discards self-authored messages, mentions the peer bot in every text or card reply, and enforces the shared channels.defaults.botLoopProtection guard.

Get group/user IDs

Group IDs (chat_id, format: oc_xxx)

In Feishu/Lark, open the group, tap the menu icon at the top-right, then choose Settings. The group ID (chat_id) appears on that settings page.

Get Group ID

User IDs (open_id, format: ou_xxx)

Launch the gateway, send a DM to the bot, and inspect the logs:

openclaw logs --follow

Search the log output for open_id. Pending pairing requests can also be reviewed:

openclaw pairing list feishu

Common commands

CommandDescription
/statusDisplay bot status
/resetClear the active session
/modelShow or change the AI model

Note

Feishu/Lark lacks native slash-command menus, so type these as plain text.

Troubleshooting

Bot does not respond in group chats

  1. Confirm the bot has been added to the group
  2. Confirm you @mention the bot (required unless changed)
  3. Verify groupPolicy is not set to "disabled"
  4. Review logs: openclaw logs --follow

Bot does not receive messages

  1. Confirm the bot is published and approved in Feishu Open Platform / Lark Developer
  2. Confirm event subscription covers im.message.receive_v1
  3. For auto-join of meeting invites, also subscribe to vc.bot.meeting_invited_v1
  4. Confirm persistent connection (WebSocket) is selected
  5. Confirm all required permission scopes have been granted
  6. Confirm the gateway is running: openclaw gateway status
  7. Review logs: openclaw logs --follow

Subscribing to vc.bot.meeting_invited_v1 only triggers the event delivery. Automatic joins are disabled by default. To turn them on globally:

{
  channels: {
    feishu: {
      vcAutoJoin: true,
    },
  },
}

To enable for a single account, skip the top-level switch and set the account override:

{
  channels: {
    feishu: {
      accounts: {
        meetings: { vcAutoJoin: true },
      },
    },
  },
}

Inviters still pass through the standard Feishu DM policy, allowlist/pairing, session, and reply routing before the agent gets a join turn. Joining also requires a Feishu VC join tool configured for app identity with the vc:meeting.bot.join:write scope. As an example, the official lark-cli VC agent skill offers vc +meeting-join.

Warning

The official lark-cli VC agent skill currently flags meeting-bot actions as a limited beta. If the tool returns ErrNotInGray or error code 20017, the app or tenant has not been enabled for that beta; follow the early-access instructions in the linked skill before checking ordinary scope grants.

QR setup does not react in the Feishu mobile app

  1. Run setup again: openclaw channels login --channel feishu
  2. Pick manual setup
  3. In Feishu Open Platform, create a self-built app and copy its App ID and App Secret
  4. Paste those credentials into the setup wizard

App Secret leaked

  1. Reset the App Secret in Feishu Open Platform / Lark Developer
  2. Update the value in your config
  3. Restart the gateway: openclaw gateway restart

Advanced configuration

Multiple accounts

{
  channels: {
    feishu: {
      defaultAccount: "main",
      accounts: {
        main: {
          appId: "cli_xxx",
          appSecret: "xxx",
          name: "Primary bot",
          tts: {
            providers: {
              openai: { voice: "shimmer" },
            },
          },
        },
        backup: {
          appId: "cli_yyy",
          appSecret: "yyy",
          name: "Backup bot",
          enabled: false,
        },
      },
    },
  },
}

defaultAccount determines which account is used when outbound APIs lack an accountId. Account entries inherit top-level settings; most top-level keys can be overridden per account. accounts.<id>.tts follows the same structure as tts and deep-merges over global TTS config, so multi-bot Feishu setups can keep shared provider credentials globally while overriding only voice, model, persona, or auto mode per account.

Message limits

  • textChunkLimit: outbound text chunk size, defaulting to 4000 characters
  • streaming.chunkMode: "length" is the default and cuts at the limit; "newline" prefers breaking at newlines
  • mediaMaxMb: media upload/download cap, defaulting to 30 MB

Standard Markdown cards and rich-text posts also get divided to comply with Feishu's 30 KB serialized message cap. Headers, notes, mentions, JSON escaping, and UTF-8 text all consume part of that cap, so chunks can end up smaller than textChunkLimit. Long media captions go out as text/card chunks before the attachment is sent.

Streaming

Feishu/Lark can stream replies through interactive cards using the Card Kit streaming API. With this enabled, the bot refreshes the card live as it produces text.

{
  channels: {
    feishu: {
      streaming: {
        mode: "partial", // streaming card output (default: "partial")
        block: { enabled: true }, // opt into completed-block streaming
      },
    },
  },
}

Set streaming.mode: "off" to deliver the final reply without streaming updates; long replies still break at the message limits mentioned above. renderMode: "raw" (which uses plain text rather than cards) also turns off streaming cards. streaming.block.enabled defaults to off; switch it on only when you need completed assistant blocks flushed ahead of the final reply. The legacy boolean streaming and the flat blockStreaming / blockStreamingCoalesce / chunkMode keys migrate into this nested structure via openclaw doctor --fix.

Quota optimization

Cut down on Feishu/Lark API calls with two optional flags:

  • typingIndicator (default true): set false to skip typing reaction calls
  • resolveSenderNames (default true): set false to skip sender profile lookups
{
  channels: {
    feishu: {
      typingIndicator: false,
      resolveSenderNames: false,
    },
  },
}

Group session scope and topic threads

channels.feishu.groupSessionScope (top-level, per account, or per group) determines how group messages map to agent sessions:

ValueSession
"group" (default)One session per group chat
"group_sender"One session per (group + sender)
"group_topic"One session per topic thread; falls back to the group session
"group_topic_sender"One session per (topic + sender); falls back to (group + sender)

For topic scopes, native Feishu/Lark topic groups rely on the event thread_id (omt_*) as the canonical topic session key. When a native topic starter event omits thread_id, OpenClaw fills it in from Feishu before routing the turn. Regular group replies that OpenClaw converts into threads keep using the reply root message ID (om_*) so the initial turn and subsequent turns stay in the same session.

Set replyInThread: "enabled" (top-level or per group) so bot replies create or continue a Feishu topic thread instead of replying inline. topicSessionMode is the deprecated predecessor of groupSessionScope; go with groupSessionScope.

Feishu workspace tools

The plugin includes agent tools for Feishu documents, chats, knowledge base, cloud storage, permissions, and Bitable, along with matching skills (feishu-doc, feishu-drive, feishu-perm, feishu-wiki). Tool families are controlled by channels.feishu.tools:

KeyToolsDefault
tools.docfeishu_doc document operationstrue
tools.chatfeishu_chat chat info + member queriestrue
tools.wikifeishu_wiki knowledge base (requires doc)true
tools.drivefeishu_drive cloud storagetrue
tools.permfeishu_perm permission managementfalse (sensitive)
tools.scopesfeishu_app_scopes app scope diagnosticstrue
tools.bitablefeishu_bitable_* Bitable/Base operationstrue

Per-account gates are located under accounts.<id>.tools.

Only title-bearing documents are produced by feishu_doc. To include Markdown content, take the returned document_id and feed it as doc_token into a subsequent write call. Any create request carrying content will fail, and no empty document gets created.

For direct feishu_drive info lookups outside the root directory, grant drive:drive.metadata:readonly, unless the app already holds the complete drive:drive scope. When neither scope is present, info preserves the legacy root-directory lookup path via drive:drive:readonly.

ACP sessions

ACP is supported for DMs and group thread messages on Feishu/Lark. Since there are no native slash-command menus, Feishu/Lark ACP relies on text commands, so send /acp ... messages straight into the conversation.

Persistent ACP binding

{
  agents: {
    entries: {
      codex: {
        default: true,
        runtime: {
          type: "acp",
          acp: {
            agent: "codex",
            backend: "acpx",
            mode: "persistent",
            cwd: "/workspace/openclaw",
          },
        },
      },
    },
  },
  bindings: [
    {
      type: "acp",
      agentId: "codex",
      match: {
        channel: "feishu",
        accountId: "default",
        peer: { kind: "direct", id: "ou_1234567890" },
      },
    },
    {
      type: "acp",
      agentId: "codex",
      match: {
        channel: "feishu",
        accountId: "default",
        peer: { kind: "group", id: "oc_group_chat:topic:om_topic_root" },
      },
      acp: { label: "codex-feishu-topic" },
    },
  ],
}

Spawn ACP from chat

Inside a Feishu/Lark DM or thread:

/acp spawn codex --thread here

DMs and Feishu/Lark thread messages both work with --thread here. Any follow-up messages within the bound conversation are sent directly to that ACP session.

Multi-agent routing

To direct Feishu/Lark DMs or groups toward different agents, use bindings.

{
  agents: {
    entries: {
      main: { default: true },
      "agent-a": { workspace: "/home/user/agent-a" },
      "agent-b": { workspace: "/home/user/agent-b" },
    },
  },
  bindings: [
    {
      agentId: "agent-a",
      match: {
        channel: "feishu",
        peer: { kind: "direct", id: "ou_xxx" },
      },
    },
    {
      agentId: "agent-b",
      match: {
        channel: "feishu",
        peer: { kind: "group", id: "oc_zzz" },
      },
    },
  ],
}

Fields for routing:

  • match.channel: "feishu"
  • match.peer.kind: "direct" (DM) or "group" (group chat)
  • match.peer.id: user Open ID (ou_xxx) or group ID (oc_xxx)

For lookup guidance, check Get group/user IDs.

Per-user agent isolation (Dynamic Agent Creation)

Turning on dynamicAgentCreation creates isolated agent instances automatically for every DM user. Each user is given their own:

  • Workspace directory that is independent
  • Separate USER.md / SOUL.md / MEMORY.md
  • Conversation history kept private
  • Skills and state that are isolated

For public bots where each user should get a private AI assistant experience, this becomes essential.

Note

The normalized Feishu accountId is part of dynamic bindings, which means both default and named accounts direct each sender to the appropriate dynamic agent.

On older releases, a named account may have created an unscoped dynamic agent. Such legacy agents still consume maxAgents. Before removing one, verify it is not in use by the default account, or raise maxAgents temporarily. OpenClaw cannot reliably determine which account owns ambiguous legacy state.

Quick setup

{
  channels: {
    feishu: {
      dmPolicy: "open",
      allowFrom: ["*"],
      dynamicAgentCreation: {
        enabled: true,
        workspaceTemplate: "~/.openclaw/workspace-{agentId}",
        agentDirTemplate: "~/.openclaw/agents/{agentId}/agent",
      },
    },
  },
  session: {
    // Critical: makes each user's DM their "main session"
    // Automatically loads USER.md / SOUL.md / MEMORY.md
    // For stronger isolation, use "per-channel-peer" instead
    dmScope: "main",
  },
}

How it works

When a user sends their first DM:

  1. A unique agentId is generated by the channel: feishu-{user_open_id} for the default account, or a bounded account-prefixed identity digest for a named account
  2. A new workspace is created at the workspaceTemplate path
  3. The agent is registered and a binding for that user is established
  4. On first access, the workspace helper ensures bootstrap files (AGENTS.md, SOUL.md, USER.md, etc.) are present
  5. All subsequent messages from this user are routed to their dedicated agent

Configuration options

SettingDescriptionDefault
channels.feishu.dynamicAgentCreation.enabledTurn on automatic per-user agent creationfalse
channels.feishu.dynamicAgentCreation.workspaceTemplateTemplate for dynamic agent workspace paths~/.openclaw/workspace-{agentId}
channels.feishu.dynamicAgentCreation.agentDirTemplateTemplate for agent directory names~/.openclaw/agents/{agentId}/agent
channels.feishu.dynamicAgentCreation.maxAgentsCap on the number of dynamic agentsunlimited

Template variables:

  • {agentId} - the generated agent ID (for instance, feishu-ou_xxxxxx or feishu-support-<identity_digest>)
  • {userId} - the sender's Feishu open_id (for instance, ou_xxxxxx)

Session scope

Mapping of direct messages to agent sessions is governed by session.dmScope. This setting applies globally, affecting every channel.

ValueBehaviorBest for
"main"A user's DM maps to their agent's main sessionSingle-user bots where USER.md / SOUL.md should auto-load
"per-peer"Each peer receives its own session (channel-independent)Isolation based solely on sender identity
"per-channel-peer"Each (channel + user) pair gets its own sessionPublic multi-user bots requiring stronger isolation
"per-account-channel-peer"Each (account + channel + user) trio gets its own sessionMulti-account bots needing account-level session isolation

Tradeoff: With "main", bootstrap files (USER.md, SOUL.md, MEMORY.md) load automatically, but every DM across all channels shares the same session key pattern. For public multi-user bots where isolation outweighs bootstrap auto-loading, "per-channel-peer" is a better fit, with manual bootstrap file management.

Note

When named Feishu accounts must maintain separate sessions for the same sender, use "per-account-channel-peer". Account scope is preserved by dynamic bindings.

Typical multi-user deployment

{
  channels: {
    feishu: {
      appId: "cli_xxx",
      appSecret: "xxx",
      dmPolicy: "open",
      allowFrom: ["*"],
      groupPolicy: "open",
      requireMention: true,
      dynamicAgentCreation: {
        enabled: true,
        workspaceTemplate: "~/.openclaw/workspace-{agentId}",
        agentDirTemplate: "~/.openclaw/agents/{agentId}/agent",
      },
    },
  },
  session: {
    // Choose dmScope based on your isolation needs:
    // "main" for bootstrap auto-loading, "per-channel-peer" for stronger isolation
    dmScope: "main",
  },
  bindings: [], // Empty - dynamic agents auto-bind
}

Verification

To verify dynamic creation is functioning, inspect the gateway logs:

feishu: creating dynamic agent "feishu-ou_xxxxxx" for user ou_xxxxxx
  workspace: /home/user/.openclaw/workspace-feishu-ou_xxxxxx
  agentDir: /home/user/.openclaw/agents/feishu-ou_xxxxxx/agent

To list every workspace that has been created:

ls -la ~/.openclaw/workspace-*

Notes

  • Workspace isolation: A dedicated workspace directory and agent instance exist for each user. Within the normal messaging flow, users cannot access each other's conversation history or files.
  • Security boundary: This isolates messaging context, not hostile co-tenants. The agent process and host environment are shared.
  • Config writes must stay enabled: Agents and bindings are written into the config during dynamic creation; this step is skipped when channels.feishu.configWrites is false (default: enabled).
  • bindings should be empty: Bindings are auto-registered by dynamic agents
  • Upgrade path: Manual bindings and dynamic agents can coexist
  • session.dmScope is global: All channels are affected, not just Feishu

Configuration reference

Full configuration: Gateway configuration

SettingDescriptionDefault
channels.feishu.enabledTurns the channel on or offtrue
channels.feishu.domainAPI endpoint (feishu, lark, or a custom https:// base URL)feishu
channels.feishu.connectionModeHow events are delivered (websocket or webhook)websocket
channels.feishu.defaultAccountDefault account used for outgoing messagesdefault
channels.feishu.verificationTokenMandatory when operating in webhook mode-
channels.feishu.encryptKeyMandatory when operating in webhook mode-
channels.feishu.webhookPathStandard HTTP request path (needs to begin with /)/feishu/events
channels.feishu.webhookHostHost the webhook listens on127.0.0.1
channels.feishu.webhookPortPort the webhook listens on3000
channels.feishu.accounts.<id>.appIdApplication identifier-
channels.feishu.accounts.<id>.appSecretApplication secret-
channels.feishu.accounts.<id>.domainOverrides the domain for a specific accountfeishu
channels.feishu.accounts.<id>.replyToModeOverrides reply-reference behavior for a specific accountinherited
channels.feishu.accounts.<id>.ttsOverrides text-to-speech for a specific accounttts
channels.feishu.accounts.<id>.actions.stickerOverrides sticker handling for a specific accountinherited
channels.feishu.dmPolicyDirect message handling (pairing, allowlist, open)pairing
channels.feishu.allowFromDirect message allowlist (open_id list)-
channels.feishu.groupPolicyGroup handling (open, allowlist, disabled)allowlist
channels.feishu.groupAllowFromGroup allowlist-
channels.feishu.groupSenderAllowFromSender allowlist that applies to every group-
channels.feishu.requireMentionGroups require an @mentiontrue (false when policy is open)
channels.feishu.allowBotsAccept mentions from other bots, with protection against bot loopsfalse
channels.feishu.groups.<chat_id>.requireMentionOverrides @mention needs per group; explicit IDs also add the group to the allowlist in allowlist modeinherited
channels.feishu.groups.<chat_id>.enabledEnables or disables a particular grouptrue
channels.feishu.groups.<chat_id>.allowFromPer-group sender allowlist (takes precedence over groupSenderAllowFrom)-
channels.feishu.groupSessionScopeMaps group sessions (group, group_sender, group_topic, group_topic_sender)group
channels.feishu.replyToModeReply-reference mode (off, first, all, batched)all
channels.feishu.replyInThreadBot replies create/continue topic threads (disabled, enabled)disabled
channels.feishu.reactionNotificationsInbound reaction events (off, own, all)own
channels.feishu.actions.stickerEnable received-sticker sending and configured sticker searchfalse
channels.feishu.stickerSetsSearchable received-sticker keys and keywords, grouped by bot app IDnone
channels.feishu.vcAutoJoinJoin invited VC meetings after normal DM authorizationfalse
channels.feishu.dynamicAgentCreation.enabledEnable automatic per-user agent creationfalse
channels.feishu.dynamicAgentCreation.workspaceTemplatePath template for dynamic agent workspaces~/.openclaw/workspace-{agentId}
channels.feishu.dynamicAgentCreation.agentDirTemplateAgent directory name template~/.openclaw/agents/{agentId}/agent
channels.feishu.dynamicAgentCreation.maxAgentsMaximum number of dynamic agents to createunlimited
channels.feishu.textChunkLimitMessage chunk size4000
channels.feishu.streaming.chunkModeChunk splitting (length or newline)length
channels.feishu.mediaMaxMbMedia size limit30
channels.feishu.renderModeReply rendering (auto, raw, card)auto
channels.feishu.streaming.modeStreaming card output (partial or off)partial
channels.feishu.streaming.block.enabledCompleted-block reply streamingfalse
channels.feishu.typingIndicatorSend typing reactionstrue
channels.feishu.resolveSenderNamesResolve sender display namestrue
channels.feishu.configWritesAllow channel-initiated config writes (needed by dynamic agents)true
channels.feishu.tools.docEnable document toolstrue
channels.feishu.tools.chatEnable chat info toolstrue
channels.feishu.tools.wikiEnable knowledge base tools (requires doc)true
channels.feishu.tools.driveTurn on cloud storage toolstrue
channels.feishu.tools.permTurn on permission management toolsfalse
channels.feishu.tools.scopesTurn on app scopes diagnostic tooltrue
channels.feishu.tools.bitableTurn on Bitable/Base toolstrue
channels.feishu.accounts.<id>.tools.bitablePer-account Bitable/Base tool gateinherited

In webhook mode, channels.feishu.webhookPath and channels.feishu.accounts.<id>.webhookPath have to be canonical HTTP request paths that start with /, for instance /feishu/events. An optional query string is allowed and needs to match exactly. Full URLs, relative paths, URL fragments, dot segments, and unencoded spaces or Unicode get rejected. If a current configuration holds a noncanonical path, execute openclaw doctor --fix to fix it before the gateway starts.

Supported message types

Receive

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

Received stickers make their reusable file_key available to the agent as <sticker key="..."/>. Downloading sticker resources is not supported by Feishu/Lark, so OpenClaw keeps the key without fetching an attachment.

Inbound Feishu/Lark audio messages get normalized as media placeholders rather than raw file_key JSON. When tools.media.audio is set, OpenClaw pulls the voice-note resource and runs shared audio transcription before the agent turn, giving the agent the spoken transcript. If Feishu includes transcript text directly in the audio payload, that text is used without another ASR call. Without an audio transcription provider, the agent still gets a <media:audio> placeholder plus 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 use the Feishu audio message type and need Ogg/Opus upload media (file_type: "opus"). Existing .opus and .ogg media is sent directly as native audio. MP3/WAV/M4A and other likely audio formats are transcoded to 48kHz Ogg/Opus with ffmpeg only when the reply requests voice delivery (audioAsVoice / message tool asVoice, including TTS voice-note replies). Ordinary MP3 attachments stay regular files. If ffmpeg is missing or conversion fails, OpenClaw falls back to a file attachment and logs the reason.

Sticker replies

Enable the sticker action to let the agent resend stickers:

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

For one account only, set channels.feishu.accounts.<id>.actions.sticker: true instead. An account-level actions object replaces, rather than merges with, the channel-level object. Repeat any action gates you want to preserve. For example, keep reactions disabled while enabling stickers 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 resend the sticker. The shared message tool uses action: "sticker" with the received file_key in fileId or the first entry of stickerId. In multi-account setups, use the same accountId that received the sticker.

Only stickers previously received by that bot can be sent. Uploading new stickers, downloading sticker resources, and searching the sticker store are not supported.

Add a curated sticker set to let the agent find a received sticker by keyword. First send each sticker to the bot and ask 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", "赞", "👍"],
        },
      },
    },
  },
}

Replace cli_work with the bot's actual app ID and file_received_key with the key received by that bot. stickerSets belongs directly under channels.feishu, not inside an account. The selected account can search only the set matching its app ID; changing an account to a different bot does not reuse the previous bot's set. Accounts using the same bot share its set. Keep any existing account-level action gates as described above.

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

Search matches a case-insensitive substring of an explicit keyword, including Chinese labels and emoji, in sticker-key order. It does not infer a sticker's meaning, search Feishu's store, or automatically collect received stickers. Results include the matching keyword and reusable fileId. No matches produce an empty list; truncated: true means matching entries were omitted by the result limit or output budget. Narrow the query to find other matches.

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

Threads and replies

  • ✅ Inline responses are supported
  • ✅ Replies within threads are supported
  • ✅ When replying to a thread message, media replies remain thread-aware

For details on topic-group session routing, see Group session scope and topic threads.

  • Channels Overview - every channel that is supported
  • Pairing - the DM authentication and pairing process
  • Groups - behavior in group chats and mention restrictions
  • Channel Routing - how messages are routed across sessions
  • Security - the access model and hardening measures
4,690 words · updated Sep 1, 2026