Skip to content

Spec: bind a Bot to an app in one step; DMs and mentions arrive without per-conversation authorization #1107

Closed
8 of 8 issues completed

Description

@DoodleBears

v1.3 release topology — 2026-10-11

Parent: #48 (native sub-issue relationship verified). Project #10; target milestone v1.3. Preserve the existing implementation/qualification scope, claims, accepted evidence and runtime authorization. Native parentage is coordination, not an additional execution blocker.


ADR-0142 (Accepted, PR #1114) · requested by Vain on 2026-10-07 in the BotHarness project thread.

Problem

People think of it this way: "I bound this Bot to my Lark app (or Discord app), so now the Bot can receive and send messages there." What it actually takes today is:

  1. Settings → IM Bots: connect the app in the Provider's settings.
  2. Settings → IM Bots → app → Delivery targets: save a delivery target for every group or DM, then test and save it.
  3. Bot DM sidebar → External identities → Bind identity: one identity per Bot per platform.
  4. Bot DM sidebar → External connectors → Authorize a conversation: pick the app and the saved target.
  5. Turn reception on for that authorization.
  6. (Optional) Add an External connector to route the conversation into a local Channel.

Until every step is done, a DM or @mention to the app is acknowledged and dropped without any trace. People who create several Lark, WeChat or Discord apps also run into these problems:

  • A Bot can bind only one app per platform (unique index messaging_binding_bot_platform).
  • The Provider's settings list doesn't show which Bot uses an app.
  • The bind dialog offers apps that already belong to another Bot and then fails with binding-conflict.

Decisions

One-step binding

  • External identities offers Bind app (绑定应用). You choose the platform, then pick an already-connected app that no Bot uses yet, or create one inline (Lark/Feishu credentials, WeChat QR). There's no detour to Settings.
  • Once bound, the Bot can receive and reply right away. You don't need delivery targets, conversation authorization or a reception switch for this.

Default traffic

  • DMs to the app and @mentions of the app in groups it belongs to go to that Bot's Inbox. Replies go back to the original conversation, through the existing checked reply route.
  • Platform settings decide who can reach the app: availability scope, group membership, app permissions. BotHarness adds no per-conversation consent before admission.
  • What counts as default traffic follows what each platform has qualified: Lark DMs and mentions, Slack public-channel mentions, Discord channel and public-thread mentions, the WeChat paired-owner DM.

Conversations are a list you manage afterwards

  • The first admitted message from a conversation records a conversation entry (an implicit Grant row).
  • For each conversation you can Mute (no wake, still readable), change reception rules (ordinary text, thread following, wake), or Block.
  • A block sticks. It survives restarts, auto mode, and unbinding then rebinding the same app to the same Bot. Only Allow again reopens the conversation, and messages from while it was blocked are not backfilled.
  • New-conversation mode per app is either Admit automatically (the default for every binding) or Ask me first. In Ask me first, a new conversation is listed as waiting and nothing is stored or admitted until you allow it. Automatic admission is bounded per app (20 new per hour, 500 active). Past that, new conversations wait.

Multiple apps

  • One app belongs to exactly one Bot (the existing account and fingerprint uniqueness stays). A Bot may bind several apps per platform.
  • The bind dialog lists only apps no Bot uses yet.
  • A new IM apps list in Bot settings shows every app and the Bot using it, with a link to the Provider settings for credentials.

What stays explicit and unchanged

  • Pairing (/pair) and approvals.
  • Saved-target Service Grants, kept only as the fallback for Providers that cannot list or address conversations.
  • Ordinary-text collection and thread following.
  • Placing a conversation into a local Channel, now done from that conversation's row. The External connectors entry is reserved for later one-way input streams such as webhooks.
  • Another Bot replying: it uses its own app's entry, and the reply refuses when that Bot has two apps in the same conversation.

Proactive posts reach wherever the platform lets the app speak (Vain, 2026-10-07)

  • Posting in other groups is an intended use. The platform decides where the app can speak (Discord channel permissions, Lark/Slack group membership, availability scope), and the person manages reach there.
  • A Provider capability lists the conversations the app can post in right now. The Bot can read that list and post to any of them, with no saved delivery target. The Host re-checks reachability before sending.
  • The first post to a new conversation creates a conversation entry, so it shows up in the list and can be muted or blocked.
  • Blocked conversations refuse posts. A per-app loop guard (60 per hour by default, adjustable or off) stops runaway loops.
  • This ships with the Provider release that adds inline creation.

Migration

  • Existing Grants become explicit conversation entries without any change in behavior.
  • Every app, existing or new, gets Admit automatically (Vain, 2026-10-07: the plugin has no users yet). Revoked conversations become blocks.

Copy

  • UI says app (应用), conversation (会话), Bot, External connector (外部连接器). Never Human, PersonaBot or Source Event.

User-facing flow

  1. Bot DM sidebar → External identities → Bind app.
  2. Choose Lark / Feishu, Discord, Slack or WeChat.
  3. Pick an unused connected app, or choose Create app:
    • Lark: credentials form, Provider-owned.
    • WeChat: scan the QR code.
    • Discord/Slack: token form.
  4. The dialog shows Ready: DMs and @mentions to <app> now reach <Bot>, using the real receiver state, and what this platform receives.
  5. DM the app or @mention it in a group. The message appears in the Bot Inbox and the Bot replies in place.
  6. Open the app row to see Conversations: active, muted, waiting and blocked, each with Mute, Rules, Block and Allow again.
  7. The Bot can also post proactively into any conversation the app can reach on the platform. Each conversation row has Sync to a Channel.

Slices (one issue = one PR, serial, in this order)

Sub-issues are linked below.

  1. Tracer: bind a connected Lark app; DMs and mentions reach the Inbox; the reply goes back in place
  2. Conversation list: mute, rules, block that sticks, allow again
  3. Several apps per platform and the IM apps list
  4. Create the app inside Bind app: Lark credentials and WeChat QR (Provider setup capability)
  5. Proactive posts to any conversation the platform lets the app speak in (Proactive posts to any conversation the platform lets the app speak in #1115)
  6. Slack and Discord default traffic through the same binding registration
  7. External connectors relabel and the connection guides

Each PR includes before/after screenshots (zh/en, light/dark where it matters), updates the affected zh/en guides, and follows the tracer-bullet rule from AGENTS.md: focused automated coverage plus a runnable Human verification path. Pause for Human QA after slice 1.

Out of scope

  • DMs on Slack and Discord until they are separately qualified. WeChat groups and non-owner contacts.
  • Showing a "used by" label inside the Provider's own settings UI. That can follow upstream later.
  • Merging duplicate Source Events when two of one Bot's apps see the same message.

Resolved questions (Vain, 2026-10-07)

  • Existing apps migrate straight to Admit automatically.
  • The Bot can post proactively wherever the platform lets the app speak, with no saved delivery target. Platform permissions manage the reach.

Activity

  1. added
    needs-triageMaintainer needs to evaluate this issue
    area:fullstackEnd-to-end Host and Client implementation
    scope:specNormative specification for follow-on slices
    on Oct 7, 2026
  2. added this to the v1.2 milestone on Oct 8, 2026
  3. DoodleBears commented on Oct 8, 2026

    @DoodleBears
    ContributorAuthor

    Issue 归属整理 — 2026-10-08 (Asia/Tokyo)

    已按 Human 授权补 Project 10 / v1.2,并为未完成子票 #1111、#1115 补同一归属。现有已完成基线不重开;Provider release、真实平台验收和现有任务认领保持原范围。相关旧规格 #629/#693 和 Project 10 的当前执行索引已同步到本票的既定方案。

  4. 1 remaining item

  5. added this to the v1.3 milestone on Oct 11, 2026
  6. DoodleBears commented on Oct 13, 2026

    @DoodleBears
    ContributorAuthor

    Agent work claim — parent closure validation

    Native child status checked: #1108, #1109, #1110, #1111, #1115, #1112 and #1113 are closed; #1123 is the sole open child. The remaining native qualification and matched UI captures have now passed, and the integrated runtime head's official verify run passed 4,713 tests (10 skipped). The task receiver is stopped. The final PR evidence/closing references are being published; this claim does not grant a new IM receiver window.

  7. added
    agent:activeOne or more coding-agent tasks currently claim this issue; see claim comments for task IDs
    on Oct 13, 2026
  8. moved this from Todo to In Progress in Roadmapon Oct 13, 2026
  9. DoodleBears commented on Oct 13, 2026

    @DoodleBears
    ContributorAuthor

    Agent delivery handoff

  10. removed
    agent:activeOne or more coding-agent tasks currently claim this issue; see claim comments for task IDs
    on Oct 13, 2026
  11. moved this from In Progress to Done in Roadmapon Oct 14, 2026
  12. DoodleBears commented on Oct 14, 2026

    @DoodleBears
    ContributorAuthor

    Agent outcome: completed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:fullstackEnd-to-end Host and Client implementationneeds-triageMaintainer needs to evaluate this issuescope:specNormative specification for follow-on slices

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions