Files
nanoclaw/.claude/skills/manage-channels/SKILL.md
Koshkoshinsk 2017589683 feat(telegram): self-contained pairing for chat ownership verification
BotFather issues bot tokens with no user binding, so anyone who guesses the
bot's username can DM it and get registered as a channel. Pairing closes that
gap: setup issues a one-time 4-digit code, the operator echoes it back from
the chat they want to register, and the inbound interceptor binds
admin_user_id before the message reaches the router.

- src/channels/telegram-pairing.ts: JSON-backed store with createPairing,
  tryConsume, getStatus, waitForPairing (fs.watch + poll fallback)
- src/channels/telegram.ts: wraps bridge.setup with an onInbound interceptor
  that consumes pairing codes and upserts messaging_groups
- setup/pair-telegram.ts: CLI step issues a code and waits up to 5 min for
  the operator to echo it back, emitting PLATFORM_ID/IS_GROUP/ADMIN_USER_ID
- Skill docs: /setup reorders mounts -> service -> wire (pairing needs a
  live polling adapter); /manage-channels and /add-telegram-v2 use pairing
  instead of asking the user to discover chat IDs

All other channels still bind admin via install-time identity (OAuth/QR/token);
pairing is Telegram-only. The bridge, router, and other adapters are untouched.
2026-04-13 12:27:02 +00:00

4.6 KiB

name, description
name description
manage-channels Wire channels to agent groups, manage isolation levels, add new channel groups. Use after adding a channel, during setup, or standalone to reconfigure.

Manage Channels

Wire messaging channels to agent groups. See docs/v2-isolation-model.md for the full isolation model.

Assess Current State

Read the v2 central DB (data/v2.db) — query agent_groups, messaging_groups, and messaging_group_agents tables. Also check .env for channel tokens and src/channels/index.ts for uncommented imports.

Categorize channels as: wired (has DB entities), configured but unwired (has credentials + barrel import, no DB entities), or not configured.

First Channel (No Agent Groups Exist)

  1. Ask the assistant name (default: project name or "Andy")
  2. Ask which channel is the primary/admin channel
  3. Telegram special case: if the chosen channel is telegram, do not ask for an ID. Run npx tsx setup/index.ts --step pair-telegram -- --intent main, show the user the 4-digit CODE from the PAIR_TELEGRAM_ISSUED block, and tell them to DM the bot with @<botname> CODE from the chat they want as their main. Wait for the PAIR_TELEGRAM block — PLATFORM_ID, IS_GROUP, ADMIN_USER_ID come back from there. Skip step 4 of this list (the messaging group is already created with admin binding); instead run only the agent-group + wiring portion via setup --step register with the returned PLATFORM_ID.
  4. Otherwise (non-Telegram), ask for the platform ID — read the channel's SKILL.md ## Channel Info > how-to-find-id to guide them, then register:
npx tsx setup/index.ts --step register -- \
  --platform-id "<id>" --name "<name>" --folder "main" \
  --channel "<type>" --is-main --no-trigger-required \
  --assistant-name "<name>" --session-mode "shared"
  1. Continue to "Wire New Channel" for any remaining configured channels.

Wire New Channel

For each unwired channel:

  1. Read its SKILL.md ## Channel Info for terminology, how-to-find-id, typical-use, and default-isolation
  2. Ask for the platform ID using the platform's terminology
  3. Ask the isolation question (see below)
  4. Register with the appropriate flags

Isolation Question

Present a multiple-choice with a contextual recommendation. The three options:

  • Same conversation (--session-mode "agent-shared" + existing folder) — all messages land in one session. Recommend for webhook + chat combos (GitHub + Slack).
  • Same agent, separate conversations (--session-mode "shared" + existing folder) — shared workspace/memory, independent threads. Recommend for same user across platforms.
  • Separate agent (new --folder) — full isolation. Recommend when different people are involved.

Use the channel's typical-use and default-isolation fields to pick the recommendation. Offer to explain more if the user is unsure — reference docs/v2-isolation-model.md for the detailed explanation.

Register Command

npx tsx setup/index.ts --step register -- \
  --platform-id "<id>" --name "<name>" \
  --folder "<folder>" --channel "<type>" \
  --session-mode "<shared|agent-shared>" \
  --assistant-name "<name>"

For separate agents, also ask for a folder name and optionally a different assistant name.

Add Channel Group

When adding another group/chat on an already-configured platform (e.g. a second Telegram group):

  1. Telegram: ask the isolation question first to determine intent (wire-to:<folder> for an existing agent, new-agent:<folder> for a fresh one). Run npx tsx setup/index.ts --step pair-telegram -- --intent <intent>, show the CODE, and tell the user to post @<botname> CODE in the target group (or DM the bot for a private chat). Wait for the PAIR_TELEGRAM block, then run setup --step register with the returned PLATFORM_ID and the chosen folder/session-mode. The messaging group row is already created with admin_user_id set — register only needs to add the wiring.
  2. Other channels: read the channel's SKILL.md ## Channel Info for terminology and how-to-find-id. Ask for the new group/chat ID, ask the isolation question, then register. No package or credential changes needed.

Change Wiring

  1. Show current wiring
  2. Ask which channel to move and to which agent group
  3. Delete the old messaging_group_agents entry, create a new one
  4. Note: existing sessions stay with the old agent group; new messages route to the new one

Show Configuration

Display a readable summary showing agent groups with their wired channels, configured-but-unwired channels, and unconfigured channels.