13 KiB
PRD: Feishu (飞书) channel extension
Why
Clawdbot already supports several chat surfaces (e.g. Slack, Google Chat, Telegram). Feishu (飞书) is a common “primary chat” surface for many teams. Adding a Feishu channel plugin lets a user run Clawdbot as a personal assistant inside Feishu with the same security posture (pairing/allowlists) and the same agent routing + reply pipeline.
Goals
- Ship a Feishu channel plugin under
extensions/(installable from npm) that can:- Receive inbound messages (DM + group) via Feishu event subscription callback.
- Respond with text replies (agent replies +
clawdbot message send). - Respect Clawdbot’s DM security model (pairing/allowlist/open/disabled).
- Support group allowlists + mention gating behavior consistent with other channels.
- Show up in onboarding as an installable channel (like Matrix/MSTeams plugins).
- Keep V1 minimal and consistent with existing integration patterns:
extensions/googlechatfor “HTTP webhook → monitor → reply dispatcher”extensions/msteamsfor “extension owns provider + status + onboarding”
Non-goals (V1)
- Full message-card interactivity (buttons / card callbacks).
- Full media pipeline parity (file upload/download for every Feishu message type).
- Full directory/lookup parity (live user/group directory browsing).
- Multi-tenant ISV (app store) flow in the first pass (internal/self-built app only).
Primary user
Single human operator running Clawdbot for personal use, inside one Feishu tenant.
User journeys (high-level)
- User installs and enables the Feishu plugin.
- User creates a Feishu app (self-built/internal) with Bot capability enabled.
- User configures event subscription callback URL (served by Clawdbot Gateway).
- User DMs the bot; unknown DMs get pairing code; after approval bot answers.
- User adds bot to a group; bot responds only when allowed and mention-gated.
Functional requirements (high-level)
- Inbound:
- HTTP handler for Feishu event subscription callback.
- Support
url_verificationchallenge handshake. - Validate inbound requests (signature and/or verification token).
- Handle
im.message.receive_v1events.
- Outbound:
- Send text messages to
open_id(DM) andchat_id(group). - Reply-to behavior: best-effort thread/reply mapping if Feishu supports it.
- Send text messages to
- Security:
- DM policy:
pairingdefault; allowlists;open;disabled. - Group policy:
allowlistdefault; optionalopenwith mention gating;disabled. - Control command gating: ignore unauthorized control commands in group chats.
- DM policy:
- Ops:
channels statusshows configured/running/probe/last inbound/outbound.channels status --probevalidates token acquisition.
Success criteria
- A user can complete onboarding and successfully:
- Receive a DM and get a pairing code.
- Approve pairing and receive a reply.
- Receive a group message and respond only when allowlisted + mention-gated.
- Send a message via
clawdbot message send --to <target>.
Decisions (confirmed)
- Region: Feishu only.
- Inbound transport: HTTP callback (event subscription webhook).
- V1 scope: text-only.
Risks and mitigations
- Misconfigured public exposure: document “only expose
/feishupath” guidance and recommend a reverse proxy/Tailscale. - Secret leakage: never log app secrets; store secrets only in config.
- Rate limits: cache tokens; chunk outbound messages via existing chunker helpers.
*** Add File: extensions/feishu/spec/design.md
Tech design: Feishu (飞书) channel plugin
Summary
Implement @clawdbot/feishu as a channel extension that:
- Registers a channel plugin (
api.registerChannel) and an HTTP webhook handler (api.registerHttpHandler). - Starts a per-account “monitor” on gateway start (via
plugin.gateway.startAccount) that registers webhook targets and manages runtime status. - Uses the existing Clawdbot reply pipeline (
runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher) to route inbound messages to an agent and send outbound replies back to Feishu.
This follows the proven “webhook channel” structure in extensions/googlechat.
Architecture
Components
- Feishu plugin entrypoint:
extensions/feishu/index.ts- Stores
PluginRuntime(likeextensions/googlechat/src/runtime.ts). - Registers channel + HTTP handler.
- Stores
- Channel plugin:
extensions/feishu/src/channel.ts- Config adapter (accounts, enabled/configured, allowFrom formatting).
- Outbound adapter (sendText).
- Security adapter (DM policy warnings, group policy warnings).
- Status adapter (probe + runtime snapshot).
- Gateway adapter (startAccount → register webhook target).
- Monitor / webhook handler:
extensions/feishu/src/monitor.ts- Parses raw body, validates signature/token, decrypts if needed.
- Handles
url_verification. - Handles
im.message.receive_v1text messages. - Applies DM + group policies and mention gating.
- Builds inbound context and calls reply dispatcher.
- Sends replies via Feishu REST API.
- API client:
extensions/feishu/src/api.ts- Token manager:
tenant_access_token/internal(self-built apps). - Send message / reply message endpoints.
- Bot info (
/open-apis/bot/v3/info) to detect mentions.
- Token manager:
Webhook verification and decryption
URL verification
- Feishu sends a payload (plain or encrypted) where
type === "url_verification"and includeschallenge. - The handler responds
200with JSON:{"challenge":"<challenge>"}.
Decrypt algorithm
- If payload has
encrypt:- Compute AES key =
sha256(encryptKey)bytes (32 bytes). - Decode
encryptfrom base64. - IV = first 16 bytes; ciphertext = remaining bytes.
- Decrypt via
aes-256-cbcto UTF-8 JSON.
- Compute AES key =
Signature validation (encrypted mode)
- Headers:
x-lark-request-timestamp,x-lark-request-nonce,x-lark-signature. - Compute:
sha256(timestamp + nonce + encryptKey + rawBodyString)(hex). - Compare with
x-lark-signature. - Use the raw request body string exactly as received (do not re-stringify parsed JSON).
Token validation (non-encrypted mode)
- When
encryptKeyis not configured, validateverificationTokenagainst payloadtoken(orheader.token).
Mention gating
- Fetch and cache bot identity via
GET /open-apis/bot/v3/info. - In group chats:
wasMentioned = mentions.some(m => m.id.open_id === botOpenId || m.id.user_id === botUserId)- Apply
resolveMentionGatingWithBypasswithrequireMentionfrom group config or channel default.
Test strategy
Colocate tests in extensions/feishu/src/ (Vitest).
- Signature verification (valid/invalid).
- Decrypt (known encryptKey + payload → expected JSON).
- Target normalization.
- URL verification and event parsing.
*** Add File: extensions/feishu/spec/spec.md
Spec: Feishu channel extension
Requirements
Requirement: Channel plugin availability
The system SHALL provide a Feishu chat channel as a Clawdbot extension plugin that can be installed and enabled without modifying core channel code.
Scenario: Plugin appears in onboarding catalog
- GIVEN a user runs
clawdbot onboardin a workspace that contains the Feishu plugin (local path) or can access it on npm - WHEN the user reaches the channel selection step
- THEN Feishu is listed as an installable channel plugin with a docs link
Requirement: Webhook endpoint and URL verification
The system SHALL accept Feishu event subscription callbacks over HTTP and complete the platform “request URL verification” handshake.
Scenario: URL verification succeeds
- GIVEN Feishu sends a
type="url_verification"callback payload with achallenge - WHEN Clawdbot receives the POST at the configured webhook path
- THEN the response status is
200and the response body is{"challenge":"<value>"}(JSON)
Requirement: Request validation
The system SHALL validate inbound callback requests before processing events.
Scenario: Invalid signature/token is rejected
- GIVEN a callback request with an invalid signature (encrypted mode) OR mismatched verification token (non-encrypted mode)
- WHEN the request is received
- THEN the request is rejected with
401and no message processing occurs
Requirement: Encrypted payload support
When configured with an encrypt key, the system SHALL decrypt payloads that use the encrypt envelope.
Scenario: Encrypted event is processed
- GIVEN a callback request containing an
encryptfield - WHEN the plugin is configured with the correct
encryptKey - THEN the decrypted JSON is used for URL verification and event handling
Requirement: Inbound message handling (DM)
The system SHALL process im.message.receive_v1 DMs and route them into the Clawdbot agent pipeline with DM security policies.
Scenario: Unknown DM triggers pairing flow
- GIVEN
channels.feishu.dm.policy="pairing" - AND a DM sender is not allowlisted and not previously paired
- WHEN the sender DMs the bot
- THEN the system records a pairing request and replies with a pairing code message
Requirement: Inbound message handling (groups)
The system SHALL process im.message.receive_v1 group messages with group allowlists and mention gating.
Scenario: Group message is mention-gated
- GIVEN
channels.feishu.groupPolicy="open"(or allowlisted group) - AND
requireMention=true - WHEN a group message arrives without mentioning the bot
- THEN the system ignores the message and does not invoke the agent
Requirement: Outbound text delivery
The system SHALL be able to send text messages to Feishu users and group chats.
Scenario: CLI message send delivers text
- GIVEN the user runs
clawdbot message send --to <feishu-target> --message "hi" - WHEN the target is a valid Feishu user (
open_id) or chat (chat_id) - THEN the plugin sends a Feishu API request that results in a visible message in the correct conversation
Requirement: Status and probe visibility
The system SHALL expose Feishu channel health via clawdbot channels status, including an active probe that validates credentials.
Scenario: Probe fails with actionable error
- GIVEN the plugin is enabled but credentials are invalid
- WHEN the user runs
clawdbot channels status --probe - THEN the Feishu channel shows
probe=errorwith an actionable message (e.g. token fetch failed)
*** Add File: extensions/feishu/spec/tasks.md
Tasks: Add Feishu (飞书) channel extension
1. Extension scaffold
- Create
extensions/feishu/workspace package (package.json,clawdbot.plugin.json,index.ts,src/). - Add plugin catalog metadata in
extensions/feishu/package.json(clawdbot.channel+clawdbot.install) so onboarding can install it.
2. Config + normalization
- Define Feishu config Zod schema (extension-local) and expose it as
configSchemaviabuildChannelConfigSchema. - Implement target normalization (
user:<open_id>,chat:<chat_id>) and allowlist formatting. - Implement account model (start with default account; keep
accountsextensible).
3. Token manager + API client
- Implement tenant access token fetch + cache (
/auth/v3/tenant_access_token/internal). - Implement Feishu “bot info” fetch (
/bot/v3/info) for mention gating. - Implement send message (
/im/v1/messages) and reply message (/im/v1/messages/:message_id/reply).
4. Webhook handler
- Implement
handleFeishuWebhookRequest(req,res)and register viaapi.registerHttpHandler. - Support
url_verificationchallenge response (plain + encrypted). - Implement secure validation:
- Raw-body capture with size limit.
- Signature verification when
encryptKeyis configured. - Verification token checks when
encryptKeyis not configured.
- Implement decrypt for payloads with
encrypt.
5. Event processing + routing
- Handle
im.message.receive_v1(text-only V1):- DM policy + pairing store integration (mirror GoogleChat monitor behavior).
- Group policy allowlists + mention gating integration.
- Control command gating for group chats.
- Build inbound context via
runtime.channel.reply.finalizeInboundContextand dispatch replies via buffered dispatcher.
6. Outbound adapters
- Implement
outbound.sendTextforclawdbot message sendand heartbeats.
7. Status + probe
- Implement
statusadapter snapshot + summary. - Implement
probeAccountto validate credentials (token + bot info).
8. Onboarding
- Add onboarding adapter with prompts for app id/secret and webhook settings.
9. Tests
- Add unit tests for: signature, decrypt, target normalization.
- Add unit tests for: url_verification, event parsing.