| name | channel-manager |
| description | Configure IM platform channels (Feishu, Weixin/WeChat, WeCom, DingTalk, Discord, Telegram) for octo.
Guides the user through platform consoles, collects credentials, writes ~/.octo/channels.yml,
and diagnoses connection problems.
Trigger on: "channel setup", "setup feishu", "setup weixin", "setup wechat", "setup wecom",
"setup dingtalk", "setup discord", "setup telegram",
"channel config", "channel status", "channel enable", "channel disable", "channel doctor",
"connect feishu", "connect wechat", "connect wecom", "connect dingtalk", "connect discord", "connect telegram".
Subcommands: setup, status, enable <platform>, disable <platform>, doctor.
|
Channel Manager Skill
Configure IM platform channels for octo. Supported platforms: feishu, weixin, wecom, dingtalk, discord, telegram.
How channels work in octo
- Config lives in
~/.octo/channels.yml (YAML, mode 600). Edit it directly with
read_file / write_file.
- Adapters run inside
octo serve, started alongside the HTTP server (skip with
--no-channel). Config changes are applied on save via POST /api/channels/<platform>
โ no full restart needed.
- Weixin login state lives separately in
~/.octo/weixin-credentials.json, written by
the QR-login flow this skill drives (POST /api/channels/weixin/login on the running serve).
channels.yml schema:
channels:
feishu:
enabled: true | false
app_id: string
app_secret: string
domain: string
allowed_users: string
weixin:
enabled: true | false
token: string
cred_path: string
base_url: string
allowed_users: string
dingtalk:
enabled: true | false
client_id: string
client_secret: string
allowed_users: string
wecom:
enabled: true | false
bot_id: string
secret: string
allowed_users: string
discord:
enabled: true | false
bot_token: string
allowed_users: string
telegram:
enabled: true | false
bot_token: string
base_url: string
parse_mode: string
allowed_users: string
Hot-reload after config change
After writing channels.yml, apply the change without a full restart:
curl -s -X POST "http://127.0.0.1:8088/api/channels/<platform>/reload"
- HTTP 200 โ the adapter started immediately. Done.
- Connection refused โ the server isn't running. Ask to start it with
octo serve.
Use this in place of restart_server throughout this skill. The tool is no longer
available in the desktop build (the server runs in-process with no supervisor), so
hot-reload via the API is the only zero-downtime path.
Command Parsing
| User says | Subcommand |
|---|
channel setup, setup feishu, setup weixin, setup wechat, setup wecom, setup dingtalk, setup discord, setup telegram | setup |
channel status | status |
channel enable <platform> | enable |
channel disable <platform> | disable |
channel doctor | doctor |
status
- Read
~/.octo/channels.yml. If missing or empty: "No channels configured yet. Run /channel-manager setup to get started." and stop.
- Check whether the server (which hosts the adapters) is responding:
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8088/api/health
200 โ RUNNING. Non-200 / connection refused โ STOPPED.
Do NOT use pgrep -f "octo.*serve": the server process is named octo-desktop in the desktop build and won't match. The health check works uniformly across octo serve, desktop, and TUI-hosted serves.
- Display:
Channel Status (adapter process: RUNNING/STOPPED)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Platform Enabled Details
feishu โ
yes app_id: cli_xxxโฆ
weixin โ
yes credentials: present
dingtalk โ no (not configured)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- Feishu: show
app_id truncated to 12 chars.
- Weixin: show whether
token is set or a credential file exists (cred_path, else ~/.octo/weixin-credentials.json). Never print the token value.
- DingTalk: show
client_id truncated to 12 chars. Never print client_secret.
- WeCom: show
bot_id truncated to 12 chars. Never print secret.
- Discord: show whether
bot_token is set (token: present). Never print the token value.
- Telegram: show whether
bot_token is set (token: present). Never print the token value.
If the process is STOPPED but at least one platform is enabled, ask: "octo serve ๆช่ฟ่ก๏ผๆฏๅฆ็ฐๅจๅฏๅจ๏ผ" If the user agrees and you can start it safely, run octo serve in the background. If it is RUNNING but started before a recent config change, trigger a hot reload (see "Hot-reload after config change") so the new config takes effect without a restart.
setup
Ask with ask_user_question:
Which platform would you like to connect?
- Feishu (้ฃไนฆ)
- Weixin (Personal WeChat via iLink QR login)
- WeCom (ไผไธๅพฎไฟก intelligent robot)
- DingTalk (้้)
- Discord
- Telegram (Bot API)
Feishu setup
Phase 1 โ Create the app
- Tell the user to open https://open.feishu.cn/app (log in if needed), then:
"Click 'Create Enterprise Self-Built App' (ๅๅปบไผไธ่ชๅปบๅบ็จ), fill in a name (e.g. octo) and description, and submit. Reply done." Wait for "done". Always create a new app โ do NOT reuse existing apps.
Phase 2 โ Enable Bot capability
- "On the Add App Capabilities page, find the Bot (ๆบๅจไบบ) card and click Add. Reply done." Wait for "done".
Phase 3 โ Get credentials
- "Open 'Credentials & Basic Info' (ๅญ่ฏไธๅบ็กไฟกๆฏ) in the left menu, copy App ID and App Secret, and paste them here as: App ID: xxx, App Secret: xxx". Parse
app_id and app_secret from the reply.
Phase 4 โ Add message permissions
- "Open 'Permission Management' (ๆ้็ฎก็) โ bulk import (ๆน้ๅฏผๅ
ฅ), clear the example content, paste the JSON below, and confirm. Reply done." Wait for "done".
{
"scopes": {
"tenant": [
"im:message",
"im:message.p2p_msg:readonly",
"im:message:send_as_bot"
],
"user": []
}
}
Phase 5 โ Validate and save
- Validate the credentials:
curl -s -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
-H "Content-Type: application/json" \
-d '{"app_id":"<APP_ID>","app_secret":"<APP_SECRET>"}'
Check for "code":0. On failure show the error and re-ask for credentials (up to 3 tries).
- Merge into
~/.octo/channels.yml (preserve other platforms), then chmod 600 ~/.octo/channels.yml:
channels:
feishu:
enabled: true
app_id: <APP_ID>
app_secret: <APP_SECRET>
Phase 6 โ Configure event subscription (Long Connection)
CRITICAL: octo's Feishu adapter uses a WebSocket long connection, and Feishu refuses to save the long-connection event config until a client is connected. So the adapter must be running first.
- Tell the user to (re)start
octo serve and wait until the log prints [feishu] connected to WebSocket.
- "In 'Events & Callbacks' (ไบไปถไธๅ่ฐ), select 'Long Connection' (้ฟ่ฟๆฅ) mode and save. Then click Add Event, search
im.message.receive_v1, and add it. Reply done." Wait for "done".
Phase 7 โ Publish
- "Open 'Version Management & Release' (็ๆฌ็ฎก็ไธๅๅธ), create a version (e.g. 1.0.0) and publish it. Reply done." Wait for "done".
- "โ
Feishu channel configured." Trigger a hot reload (see "Hot-reload after config change") so the new adapter starts immediately. If the server isn't running, ask the user to start
octo serve first. Then say: "Find the bot in Feishu and send it a message."
Weixin setup (Personal WeChat via iLink QR login)
Weixin uses a QR-code login โ no app credentials needed.
Do NOT pgrep for octo serve before this flow โ on desktop the server runs as octo-desktop and won't match. Just call the API; if it fails with connection refused, then offer to start the server.
- Start the QR login flow via the serve API (the response carries the QR link):
curl -s -X POST http://127.0.0.1:8088/api/channels/weixin/login
Pass -d '{"force":true}' to re-login over existing credentials.
- If the response is
already_logged_in:
- Do not tell the user the credentials are definitely valid. The cached token may have expired.
- Say: "ๆฃๆตๅฐๆฌๅฐๅทฒไฟๅญๅพฎไฟก็ปๅฝๆ๏ผไฝๆ ๆณ็กฎ่ฎคๆฏๅฆไปๆๆใๆฏๅฆ้ๆฐๆซ็ ็ปๅฝ๏ผ๏ผๅๅค
้ๆฐ็ปๅฝ ๅผบๅถ้ๆฐๆซ็ ๏ผๅๅค ็ปง็ปญ ็ดๆฅๅค็จๅฝๅ็ปๅฝๆ๏ผ"
- If the user replies
้ๆฐ็ปๅฝ, call POST /api/channels/weixin/login with -d '{"force":true}' and continue from step 3.
- If the user replies
็ปง็ปญ (or any other confirmation), proceed to step 4.
- Relay the QR link to the user:
Open this link and scan the QR code with WeChat, then confirm login in the app:
<qr_url from the response>
- Poll until the flow finishes (every ~3s, up to 5 minutes):
curl -s http://127.0.0.1:8088/api/channels/weixin/login
"status":"done" โ credentials are saved to ~/.octo/weixin-credentials.json. Continue.
"status":"pending" with a new qr_url โ the QR expired and was refreshed; relay the new link.
"status":"failed" โ show the error and offer to retry from step 1.
This agent-driven flow is the only way to log in; the web Channels panel
intentionally has no inline QR button.
- Enable the platform in
~/.octo/channels.yml (preserve other platforms), then chmod 600:
channels:
weixin:
enabled: true
The adapter reads ~/.octo/weixin-credentials.json automatically; only set cred_path if the user keeps credentials elsewhere.
- After writing
channels.yml, trigger a hot reload (see "Hot-reload after config change") so the new adapter starts immediately. If the server isn't running, tell the user to start octo serve.
- "โ
Weixin channel configured. Once
octo serve is running, message the bot on WeChat."
DingTalk setup
- Tell the user to open https://open-dev.dingtalk.com/ (log in if needed), then:
"Create an internal app (ไผไธๅ
้จๅบ็จ): Application Development โ Create Application. Reply done." Wait for "done".
- "In the app, open 'Add Application Capabilities' (ๆทปๅ ๅบ็จ่ฝๅ) and add the Bot (ๆบๅจไบบ) capability. In the bot's message receiving mode, select Stream mode (Stream ๆจกๅผ) โ octo connects over a WebSocket stream, no callback URL needed. Save/publish the capability. Reply done." Wait for "done".
- "Open 'Credentials & Basic Info' (ๅญ่ฏไธๅบ็กไฟกๆฏ), copy Client ID (AppKey) and Client Secret (AppSecret), and paste them here as: Client ID: xxx, Client Secret: xxx". Parse the reply.
- Validate:
curl -s -X POST "https://api.dingtalk.com/v1.0/oauth2/accessToken" \
-H "Content-Type: application/json" \
-d '{"appKey":"<CLIENT_ID>","appSecret":"<CLIENT_SECRET>"}'
Success returns an accessToken field. On failure show the error and re-ask (up to 3 tries).
- Merge into
~/.octo/channels.yml (preserve other platforms), then chmod 600:
channels:
dingtalk:
enabled: true
client_id: <CLIENT_ID>
client_secret: <CLIENT_SECRET>
- Trigger a hot reload (see "Hot-reload after config change"). If the server isn't running, remind the user to start
octo serve. Then say: "โ
DingTalk channel configured. Publish the app version if you haven't, then message the robot in DingTalk."
WeCom setup (ไผไธๅพฎไฟก intelligent robot)
WeCom "API mode" intelligent robots connect over a WebSocket long connection โ no public callback URL needed.
- Tell the user to open https://work.weixin.qq.com/wework_admin/frame#/aiHelper/create (scan to log in if needed), then:
"Scroll to the bottom of the right panel and click 'API mode creation' (API ๆจกๅผๅๅปบ). Reply done." Wait for "done".
- "Click 'Add' next to 'Visible Range' (ๅฏ่ง่ๅด), select the top-level company node, and confirm. Reply done." Wait for "done".
- "If the Secret is not visible, click 'Get Secret' (่ทๅ Secret). Copy the Bot ID and Secret before clicking Save, and paste them here as: Bot ID: xxx, Secret: xxx". Parse the reply. Trim whitespace; the
bot_id starts with aib โ if the two values look swapped, swap them back.
- "Click Save, enter a name (e.g. octo) and description, confirm, and click Save again. Reply done." Wait for "done".
- Merge into
~/.octo/channels.yml (preserve other platforms), then chmod 600:
channels:
wecom:
enabled: true
bot_id: <BOT_ID>
secret: <SECRET>
There is no public REST endpoint to pre-validate these credentials โ they are checked when the WebSocket subscribes. After octo serve starts, an invalid pair logs [wecom] authentication failed.
- Trigger a hot reload (see "Hot-reload after config change"). If the server isn't running, remind the user to start
octo serve. Then say: "โ
WeCom channel configured. Find the bot in the WeCom client under Contacts โ Smart Bot (ๆบ่ฝๆบๅจไบบ) and message it."
Discord setup
Discord requires manual portal interaction (hCaptcha gates application creation). Guide the user through the portal in one round-trip.
-
Tell the user to open https://discord.com/developers/applications, then give all of the following in a single message and collect the values with ask_user_question (or a plain reply):
- Click New Application (top-right), name it (e.g. "octo"), accept the ToS, click Create.
- In the left nav click Bot.
- Scroll to Privileged Gateway Intents and turn on MESSAGE CONTENT INTENT, then Save Changes.
- Scroll up, click Reset Token โ Yes, do it! โ Copy. (The token is shown only once โ copy before navigating away.)
- In the left nav click General Information and copy the Application ID.
Paste both back as one line: token=YOUR_BOT_TOKEN app_id=YOUR_APPLICATION_ID
If the user chats in a non-English language, append the localized label in parens after each bolded English button name (the English label is what they physically click). Parse with tolerant matching (token=\S+, app_id=\d+); if either field is missing, re-ask with the same format reminder (up to 3 tries).
-
Validate the token:
curl -s -H "Authorization: Bot <BOT_TOKEN>" \
-H "User-Agent: DiscordBot (https://github.com/open-octo/octo-agent, 1.0)" \
https://discord.com/api/v10/users/@me
Success returns the bot user JSON with an id. A 401 means a bad token โ re-ask.
-
Merge into ~/.octo/channels.yml (preserve other platforms), then chmod 600:
channels:
discord:
enabled: true
bot_token: <BOT_TOKEN>
-
Build the invite URL with the Application ID and tell the user to open it:
https://discord.com/oauth2/authorize?client_id=<APP_ID>&scope=bot&permissions=274878220912
Pick your server from the dropdown โ Continue โ Authorize. If the dropdown is empty you don't have a server yet โ open https://discord.com/channels/@me, click the + button โ Create My Own, then re-open the invite link.
-
Trigger a hot reload (see "Hot-reload after config change"). If the server isn't running, remind the user to start octo serve. Then say: "โ
Discord channel configured. @-mention the bot in a channel or DM it."
Telegram setup (Bot API)
Telegram is the simplest โ no browser automation, no QR. The user creates a bot via @BotFather and pastes the token.
-
Tell the user:
Open Telegram and chat with @BotFather (https://t.me/BotFather). Send /newbot, pick a display name and a username ending in bot. BotFather replies with an HTTP API token like 123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ. Paste the token here.
Optional: if your network blocks api.telegram.org, also give me the base URL of your self-hosted Bot API server.
Parse the token (matches ^\d+:[\w-]{30,}$).
-
Validate with getMe:
curl -s "<BASE_URL_OR_https://api.telegram.org>/bot<TOKEN>/getMe"
Success returns "ok":true. 401 Unauthorized means a wrong token โ re-ask.
-
Merge into ~/.octo/channels.yml (preserve other platforms; omit base_url unless the user gave one), then chmod 600:
channels:
telegram:
enabled: true
bot_token: <TOKEN>
-
Trigger a hot reload (see "Hot-reload after config change"). If the server isn't running, remind the user to start octo serve. Then say: "โ
Telegram channel configured. Open your bot in Telegram and send it a message."
For group chats: disable Privacy Mode first (@BotFather โ /mybots โ Bot Settings โ Group Privacy โ Turn off), then remove and re-add the bot to the group โ otherwise it cannot receive any group messages, including @-mentions.
enable / disable
- Read
~/.octo/channels.yml. If the platform has no entry (or required fields are missing), redirect to setup.
- Toggle
enabled: true|false for that platform only; preserve every other field and platform.
- Write back,
chmod 600 ~/.octo/channels.yml.
- Say "โ
<platform> channel enabled." / "โ <platform> channel disabled.", then trigger a hot reload (see "Hot-reload after config change"). If the server isn't running, remind the user to start octo serve.
doctor
Check each item, report โ
/ โ with remediation:
- Config file โ
~/.octo/channels.yml exists, is valid YAML, and has mode 600 (stat -f %Lp on macOS, stat -c %a on Linux).
- Required fields โ for each enabled platform:
- Feishu:
app_id, app_secret non-empty.
- Weixin:
token non-empty, or a readable credential file (cred_path, else ~/.octo/weixin-credentials.json).
- DingTalk:
client_id, client_secret non-empty.
- WeCom:
bot_id (starts with aib), secret non-empty.
- Discord:
bot_token non-empty.
- Telegram:
bot_token non-empty.
- Feishu credentials (if enabled) โ run the tenant_access_token curl from setup Phase 5;
"code":0 โ โ
, else โ "Feishu credentials rejected โ re-run setup".
- DingTalk credentials (if enabled) โ run the accessToken curl from setup step 4;
accessToken present โ โ
, else โ "DingTalk credentials invalid โ re-run setup".
- Weixin credentials (if enabled) โ credential file exists and contains a non-empty
token โ โ
, else โ "Re-run the weixin QR login (web Channels panel, or POST /api/channels/weixin/login)".
- Discord credentials (if enabled) โ run the
/users/@me curl from Discord setup step 2; an id in the response โ โ
, else โ "Discord token invalid or revoked โ re-run setup".
- Telegram credentials (if enabled) โ run the
getMe curl from Telegram setup step 2; "ok":true โ โ
, else โ "Telegram token rejected by getMe โ re-run setup".
- WeCom credentials (if enabled) โ no public REST validation endpoint; check the
octo serve output for [wecom] authentication failed โ โ "WeCom credentials incorrect โ re-run setup", or [wecom] connected, authenticating with no auth error โ โ
.
- Serve process โ use the health check from
status (curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8088/api/health); if no enabled platform, skip; if enabled but not running, โ "Run octo serve" (and ask to start it if the user agrees).
- Recorded issue (if serve is running) โ query the live status instead of only grepping logs:
curl -s http://127.0.0.1:8088/api/channels
Each entry's issue field (omitted when healthy) carries the exact reason the adapter isn't running: an unregistered/misconfigured/invalid-config skip at startup, or a crash-and-restart status such as restarting (2/10) after crash: ... or gave up after 11 crashes: .... A non-empty issue โ โ, quote it verbatim, and point at the matching setup step; a "gave up" issue means retries are exhausted and the platform needs enable/disable + hot reload (or a config fix + full server restart) to try again โ it will not recover on its own.
Security
- Always mask secrets in output โ show at most the first 4 and last 4 characters.
~/.octo/channels.yml must be mode 600; fix with chmod 600 after every write.
- Never echo
app_secret, client_secret, secret, bot_token, or token values back to the user.