Skip to main content

Gateway

PilotDeck ships with 16+ chat platform channels, all toggled by the adapters.<name> block in ~/.pilotdeck/pilotdeck.yaml. This page covers what to put in the YAML and how to start, nothing more.

Same launch command for everything:

cd /path/to/PilotDeck
npm install
npm run server

PilotDeck defaults to Stream Mode: it opens an outbound WSS to the Lark cloud — no public URL, no ngrok, no reverse proxy required.

1. Lark Developer Console

In Lark Open Platform (or Lark international) create a self-built application:

StepWhat matters
CredentialsNote the App ID (cli_xxx) and App Secret
Events & Callbacks → Subscription ModePick "Persistent connection" (NOT Webhook)
Event subscriptionsAdd im.message.receive_v1
Permissionsim:message, im:message:send_as_bot, im:chat:readonly
Versions & ReleasesCreate a version and publish, otherwise the bot won't receive any events
warning

Marketplace apps don't support persistent connections — they have to use Webhook mode (see bottom).

2. YAML

adapters:
feishu:
enabled: true
appId: cli_xxxxxxxxxxxx
appSecret: xxxxxxxxxxxxxxxxxxxxxxxx
defaultSessionLabel: default
# domainName: lark # Use 'lark' for the international edition (default 'feishu')

When you see feishu: stream mode connected (appId=...) in the startup log, you're ready — go @-mention the bot in Lark.


Requires being on the ClawBot beta allowlist. The WeChat channel is disabled by default to prevent stray QR-login flows on machines without access.

YAML

adapters:
weixin:
enabled: true # Required — without this WeixinChannel is never instantiated

No other credentials needed: at startup the terminal prints a QR-login URL, scan with an allowlisted WeChat account, and credentials get cached at ~/.pilotdeck/weixin-credentials.json for subsequent runs. Send /new to start a fresh session; delete the credentials file to force re-login.


QQ Official Bot

Connects to the QQ Official Bot Gateway over WSS. Both group chats and DMs are supported. Currently configured via environment variables (not YAML).

1. QQ Developer Console

In q.qq.com create a bot, grab AppId / AppSecret, and subscribe to:

  • GROUP_AT_MESSAGE_CREATE — bot is @-mentioned in a group
  • C2C_MESSAGE_CREATE — direct message to bot

2. Launch

export QQ_BOT_APPID=102xxxxxxx
export QQ_BOT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx
# Optional: restrict to specific groups
# export QQ_ALLOW_GROUPS=GROUP_OPENID_A,GROUP_OPENID_B

npm run server

When you see qq: authenticated, listening for group messages, the bot is online.

During the sandbox phase the bot only responds in your designated test groups; after store approval it can serve any group.


Other Platforms (One-Block YAML)

Telegram, Discord, Slack, Matrix, Mattermost, Signal, WhatsApp, BlueBubbles, DingTalk, WeCom, Email, SMS, HomeAssistant, ApiServer, and Webhook — 16 channels in total — all share the same schema:

adapters:
<name>:
enabled: true
token: xxx # Most platforms use a token
apiKey: xxx # Some platforms
webhookUrl: https://... # Some platforms
extra:
# Platform-specific fields (e.g. Slack's appToken, Matrix's homeserver)

The exact fields are wired in src/adapters/channel/loadEnabledChannels.ts. Common examples:

Telegram
adapters:
telegram:
enabled: true
token: 123456:ABC... # From @BotFather
Discord
adapters:
discord:
enabled: true
token: NTk3... # Discord Developer Portal → Bot → Token
Slack
adapters:
slack:
enabled: true
token: xoxb-... # Bot User OAuth Token
extra:
appToken: xapp-... # Socket Mode app-level token
DingTalk Stream
adapters:
dingtalk:
enabled: true
extra:
clientId: dingxxxxxxxx
clientSecret: xxxxxxxxxxxxxxxxxxxxxxxx
Matrix
adapters:
matrix:
enabled: true
token: syt_... # access token
extra:
homeserver: https://matrix.org
userId: "@bot:matrix.org"

Each channel implementation lives in src/adapters/channel/<name>/ as a trio: <Name>Channel.ts + <Name>SessionMapper.ts + <name>-render.ts.


Conventions That Apply Everywhere

BehaviorNotes
/newA user typing /new in any channel starts a fresh session; /new hello opens the new session and uses hello as the first message
Session keysFormat <channel>:chat=<id>:general or <channel>:chat=<id>:s_<uuid>
Concurrency guardWhile a turn is running for a chat, new messages from the same chat are dropped (avoids out-of-order replies)
LoggingEach channel prints <channel>: ready / <channel>: connected at startup; if you don't see it the channel isn't enabled or the credentials are wrong

Webhook Mode (Feishu Fallback)

If your Feishu app is a marketplace app and must use webhooks:

adapters:
feishu:
enabled: true
connectionMode: webhook
appId: cli_xxx
appSecret: xxx
encryptKey: xxx # Only if encryption is enabled in the Lark console
verifyToken: xxx # Only if verification token is enabled

Point your Feishu console "Event Subscription URL" at https://<your-tunnel>/feishu/webhook. PilotDeck handles url_verification, AES-256-CBC encrypted events, and event_id deduplication automatically.