8.1 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 (HTTP callback or long connection).
- 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 delivery (HTTP callback or long connection).
- 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 (
mode="http"). - Long connection listener for Feishu event subscription (
mode="ws"). - Support
url_verificationchallenge handshake. - Validate inbound requests (signature and/or verification token).
- Handle
im.message.receive_v1events.
- HTTP handler for Feishu event subscription callback (
- 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 and long connection.
- 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.
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.
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)