Feishu Channel Configuration Reference: All Keys and Defaults
Reference for every channels.feishu configuration key, its default value, and the rules that govern webhook paths. Use it when setting up or adjusting a Feishu or Lark channel.
Read this when
- Looking up a `channels.feishu` configuration key
- Checking the default value of a Feishu setting
The complete set of channels.feishu keys, their defaults, and the rules that govern webhook paths.
Configuration reference
All available options: Gateway configuration
| Setting | Description | Default |
|---|---|---|
channels.feishu.enabled | Turns the channel on or off | true |
channels.feishu.domain | API domain (feishu, lark, or a base URL from https://) | feishu |
channels.feishu.connectionMode | How events are transported (websocket or webhook) | websocket |
channels.feishu.defaultAccount | Account used by default for outbound routing | default |
channels.feishu.verificationToken | Mandatory when running in webhook mode | - |
channels.feishu.encryptKey | Mandatory when running in webhook mode | - |
channels.feishu.webhookPath | Normalized HTTP request path (its first character must be /) | /feishu/events |
channels.feishu.legacyWebhook | Explicit forwarding listener: { port, host? }; if omitted or set to false, no listener opens, though account inheritance still applies | none |
channels.feishu.accounts.<id>.appId | App ID | - |
channels.feishu.accounts.<id>.appSecret | App Secret | - |
channels.feishu.accounts.<id>.domain | Domain override for one account | feishu |
channels.feishu.accounts.<id>.replyToMode | Reply-reference mode for one account | inherited |
channels.feishu.accounts.<id>.requireMentionInBotThreads | Whether one account requires a mention in threads this bot started | inherited |
channels.feishu.accounts.<id>.tts | TTS override for one account | tts |
channels.feishu.accounts.<id>.actions.sticker | Sticker action override for one account | inherited |
channels.feishu.dmPolicy | DM policy (pairing, allowlist, open) | pairing |
channels.feishu.allowFrom | DM allowlist (open_id list) | - |
channels.feishu.groupPolicy | Group policy (open, allowlist, disabled) | allowlist |
channels.feishu.groupAllowFrom | Group allowlist | - |
channels.feishu.groupSenderAllowFrom | Sender allowlist that applies across every group | - |
channels.feishu.requireMention | Whether an @mention is required in groups | true (false when policy is open) |
channels.feishu.requireMentionInBotThreads | Changes mention handling in threads this bot started; refer to access control | existing mention behavior |
channels.feishu.allowBots | Lets other bots that mention this bot through, while guarding against bot loops | false |
channels.feishu.groups.<chat_id>.requireMention | @mention override for a single group; listing explicit IDs also admits that group under allowlist mode | inherited |
channels.feishu.groups.<chat_id>.requireMentionInBotThreads | Whether a mention is required in threads this bot started, per group | inherited |
channels.feishu.groups.<chat_id>.enabled | Turns a specific group on or off | true |
channels.feishu.groups.<chat_id>.allowFrom | Sender allowlist for one group (takes precedence over groupSenderAllowFrom) | - |
channels.feishu.groupSessionScope | Mapping of group sessions (group, group_sender, group_topic, group_topic_sender) | group |
channels.feishu.replyToMode | Mode for reply references (off, first, all, batched) | all |
channels.feishu.replyInThread | Bot replies start or extend topic threads (disabled, enabled) | disabled |
channels.feishu.reactionNotifications | Reaction events arriving inbound (off, own, all) | own |
channels.feishu.actions.sticker | Turns on sending of received stickers plus sticker search as configured | false |
channels.feishu.stickerSets | Searchable keys and keywords for received stickers, grouped by bot app ID | none |
channels.feishu.vcAutoJoin | Joins VC meetings you are invited to, once normal DM authorization is done | false |
channels.feishu.dynamicAgentCreation.enabled | Turns on automatic creation of one agent per user | false |
channels.feishu.dynamicAgentCreation.workspaceTemplate | Template for dynamic agent workspace paths | ~/.openclaw/workspace-{agentId} |
channels.feishu.dynamicAgentCreation.agentDirTemplate | Template for the agent directory name | ~/.openclaw/agents/{agentId}/agent |
channels.feishu.dynamicAgentCreation.maxAgents | Cap on how many dynamic agents get created | unlimited |
channels.feishu.textChunkLimit | Size of each message chunk | 4000 |
channels.feishu.streaming.chunkMode | How chunks are split (length or newline) | length |
channels.feishu.mediaMaxMb | Limit on media size | 30 |
channels.feishu.renderMode | How replies are rendered (auto, raw, card) | auto |
channels.feishu.streaming.mode | Output as streaming cards (partial or off) | partial |
channels.feishu.streaming.block.enabled | Streaming of replies once a block completes | false |
channels.feishu.typingIndicator | Sending of typing reactions | true |
channels.feishu.resolveSenderNames | Lookup of sender display names | true |
channels.feishu.configWrites | Permit config writes started by the channel (dynamic agents depend on this) | true |
channels.feishu.tools.doc | Turns on document tools | true |
channels.feishu.tools.chat | Turn on chat info tools | true |
channels.feishu.tools.wiki | Turn on knowledge base tools (needs doc) | true |
channels.feishu.tools.drive | Turn on cloud storage tools | true |
channels.feishu.tools.perm | Turn on permission management tools | false |
channels.feishu.tools.scopes | Turn on the app scopes diagnostic tool | true |
channels.feishu.tools.bitable | Turn on Bitable/Base tools | true |
channels.feishu.accounts.<id>.tools.bitable | Bitable/Base tool gate applied per account | inherited |
For webhook mode, channels.feishu.webhookPath and channels.feishu.accounts.<id>.webhookPath both have to be normalized HTTP request paths that start with /, for example /feishu/events. A query string is allowed but optional, and when present it must match exactly. The following are rejected: full URLs, relative paths, URL fragments, dot segments, and spaces or Unicode that are not encoded. Should an existing configuration hold a path that is not normalized, run openclaw doctor --fix to repair it prior to starting the gateway.
Gateway webhook route
Webhook mode relies on the Gateway HTTP listener (gateway.port, usually 18789) on webhookPath, usually /feishu/events. Point the public Feishu callback URL or your reverse proxy at that Gateway port and path. Feishu signatures are verified by the route, and Gateway bearer authentication is not needed. When their encrypt keys differ, accounts may share one path; if signatures are ambiguous on the Gateway port, the request is rejected rather than an arbitrary account being chosen. Accounts carried over from before that share both a path and an encrypt key stay distinguishable through their own separate explicit legacy listeners. Before you move those callbacks onto the shared Gateway port, give the accounts distinct encrypt keys or webhook paths.
Because signature verification needs the whole body, accounts that share a Gateway path also share that path's unauthenticated request-rate and in-flight body-read budgets. Separate budgets require distinct webhookPath pathnames. Trusted legacy endpoints keep independent in-flight capacity even where their paths are identical.
A new installation opens no separate webhook port. On a installation that already exists, Doctor pins legacyWebhook: { port: 3000, host: "127.0.0.1" } once for enabled webhook accounts that depended on the implicit endpoint. That explicit listener belongs to the Gateway, which forwards requests to the same plugin route and signature verifier. To pick a different endpoint, set legacyWebhook: { port: 3100, host: "127.0.0.1" }. When the object host is omitted, it binds to 127.0.0.1; explicit hosts, wildcard addresses included, are kept as written. Account entries take the root setting, and accounts.<id>.legacyWebhook: false turns forwarding off for that account. OpenClaw 2026.9.8 or newer is required by Feishu. Every webhook listener is owned by the Gateway, and a shared legacy socket remains open as long as another account still uses that endpoint. When an account shuts down, authenticated responses get up to five seconds to finish, which matches the close grace period of the previous listener. At that deadline unfinished responses are closed; routes and listeners of other accounts are unaffected. During the grace period, correctly signed callbacks for the stopping account get a retryable 503, unless a live successor already accepts their signature.
The plugin's Doctor migration relocates webhookPort and webhookHost into legacyWebhook: { port, host }, and when only one key was set it keeps the effective old defaults. The original settings are protected by the normal config backup. Existing legacyWebhook settings, false included, take precedence. The one-shot pin preserves an existing install that omitted both old settings; it needs evidence of prior operation and is not applied to a fresh install.
If you are updating from a 2026.9.6 host that has these old keys, bring OpenClaw core to 2026.9.8 or newer first, since that release contains the plugin-update migration repair. After that, explicitly update any pinned Feishu package to the release you want. Explicit plugin version pins are preserved by the core updater. Feishu's migration runs in the updated installer before the replacement package is activated; the published 2026.9.6 installer rejects the new schema before that repair can run. If a plugin-only update is refused, the previous installation and settings stay intact.
The deprecated TypeScript webhookPort and webhookHost input fields stay source-compatible through the next Plugin SDK major. Runtime config uses legacyWebhook; to migrate the old keys, run openclaw doctor --fix.
To rely on the Gateway port alone, change the Feishu callback URL or the reverse-proxy upstream to the Gateway port and webhookPath, confirm delivery works, and then drop the legacyWebhook pin. Keep meta.migrations.webhookListeners, which Doctor saves alongside the pin, so later runs do not recreate it. Included and read-only config sources are covered in webhook migrations. Use accounts.<id>.legacyWebhook: false to override an inherited root listener. Startup and Doctor print the destination and the removal instruction. Healthy endpoint guidance is shown by Doctor as information, and path conflicts as warnings; disabled accounts and WebSocket accounts get no webhook notes. Callback URLs stored in the Feishu console cannot be updated by OpenClaw.
The exact Gateway check paths (/health, /healthz, /ready, /readyz, /startup, and /startupz, query strings included) cannot receive Feishu callbacks on the Gateway port. With no explicit legacy listener, webhook startup refuses these paths and names the replacement. When the legacy listener is enabled, it keeps serving the old path. Change webhookPath to /feishu/events (or to another unreserved path), update the Feishu callback URL or reverse-proxy path, and confirm delivery on the Gateway before you remove the legacyWebhook pin. This rule does not reserve paths nested below a check path.
Paths under /api/channels need Gateway authentication, so ordinary Feishu callbacks cannot reach them on the Gateway port. Encoded forms of that prefix are covered too. Startup and Doctor issue the same path-change instructions; legacy listeners keep those callbacks working until the path and the external callback or proxy have been migrated.