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.