Skip to content

feat(channels): org-chat integrations — Microsoft Teams, Discord & WhatsApp#3749

Open
vibegui wants to merge 5 commits into
mainfrom
vibegui/org-chat-integration
Open

feat(channels): org-chat integrations — Microsoft Teams, Discord & WhatsApp#3749
vibegui wants to merge 5 commits into
mainfrom
vibegui/org-chat-integration

Conversation

@vibegui

@vibegui vibegui commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

A first-class org Channels feature (sibling to AI Providers) connecting chat platforms. Three integrations ship here:

  • Microsoft Teams & Discord — per-org bots. Each org pastes credentials in a guided wizard; a synthetic bot org-member answers via a Decopilot agent (inbound webhook → agent turn → reply).
  • WhatsApp (concierge) — one shared decoCMS number. A user verifies their phone once in their profile; inbound messages are routed by phone → user → org and the org's agent answers as that real user.

Teams / Discord

  • channels table + ChannelStorage (vault-encrypted creds), adapters (Discord Ed25519 interactions, Teams Bot Framework JWT — node:crypto + jose, no new deps), bot identity, CHANNEL_* tools, per-org webhooks at /api/:org/channels/:channelId/{teams,discord}, and a draft-first setup wizard.

WhatsApp (concierge)

  • Inbound-only verification: Studio issues a code, the user sends it to the concierge number, the inbound proves ownership (migration 108-user-phones, PHONE_LINK_START/GET/DELETE, profile "Link WhatsApp" UI that polls until verified).
  • Global ingest POST /api/whatsapp/ingest (shared-secret auth, async): verify code → resolve phone→user → resolve target org (default-org + in-chat numbered pick-list / switch) → run the agent as the real user (runChannelTurn, botUserIduserId) → deliver via the worker's /send.
  • Enable-only channel: WhatsApp has no per-org credentials/bot — CHANNELS_LIST advertises it (setupKind: "shared"), CHANNEL_CREATE activates immediately with a chosen agent; the page shows an "Add WhatsApp" enable dialog. Only available when WHATSAPP_WORKER_URL/TOKEN, WHATSAPP_INGEST_SECRET, WHATSAPP_CONCIERGE_NUMBER are set.
  • The deployed Cloudflare worker (mangabeira) stays the WABA owner and becomes a thin relay; the integration prompt for it is in .context/whatsapp-worker-integration-prompt.md.

Testing

  • bun run check 0 errors · bun run lint clean · bun run fmt applied.
  • Unit tests: adapter parse/verify/mask, phone canonicalization, WhatsApp org-selection resolver.
  • Manual/E2E: Teams/Discord via a tunnel (HTTPS); WhatsApp via the worker (or curl the ingest endpoint with a mock /send). Run bun run --cwd=apps/mesh migrate first.

Risks / follow-ups

  • Teams Bot Framework JWT verification is the highest-uncertainty area — validate Discord first.
  • Discord over HTTP = slash-command conversations (free-text DMs need the Gateway).
  • WhatsApp Studio↔worker requires the worker URL + secrets configured; the worker change is the attached prompt.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

🧪 Benchmark

Should we run the Virtual MCP strategy benchmark for this PR?

React with 👍 to run the benchmark.

Reaction Action
👍 Run quick benchmark (10 & 128 tools)

Benchmark will run on the next push after you react.

@vibegui vibegui force-pushed the vibegui/org-chat-integration branch from ba68143 to 21666e3 Compare June 11, 2026 15:24
@vibegui vibegui changed the title feat(channels): native org-chat integration (Microsoft Teams + Discord) feat(channels): org-chat integrations — Microsoft Teams, Discord & WhatsApp Jun 11, 2026
vibegui and others added 4 commits June 11, 2026 18:35
…cord

Add a first-class org "Channels" feature (sibling to AI Providers) that lets an
org connect chat-platform bots. Each channel registers a synthetic bot
org-member; an inbound platform message runs a Decopilot agent turn and the
reply is posted back into the conversation.

Backend:
- migration 106-channels.ts + ChannelStorage (vault-encrypted credentials)
- channel adapters (Discord Ed25519 interactions, Teams Bot Framework JWT) via
  node:crypto + jose, no new deps
- bot identity (synthetic user + member, bypassing the signup auto-org hook)
- runChannelTurn reuses the per-thread gate (awaitThreadRun) for a
  memory-carrying, serialized agent turn; reply read back from the thread
- CHANNEL_* MCP tools + channels:manage capability
- inbound webhooks at /api/:org/channels/:channelId/{teams,discord}
  (verify signature, ACK within deadline, run agent async, send reply)

Frontend:
- Channels settings page + guided draft-first setup wizard (StepIndicator,
  copyable endpoint URL, masked credential inputs, agent picker, status,
  resume/edit/delete), effect-free per React 19 rules
- route + nav item + use-channels hooks + query keys

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Empty state and connected-channels header now show direct "Add Microsoft
  Teams" / "Add Discord" buttons (one per supported platform) instead of a
  generic "Add channel" leading to an in-dialog grid.
- Platform selection creates the draft channel at the page level on click, then
  opens the wizard straight at the instructions step — removing the redundant
  in-dialog grid that rendered an empty body when opened without a selection
  (the lazy reducer init defaulted to the unrendered "closed" state).
- Trim the now-unreachable grid/closed/creating-draft states from the wizard
  reducer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Single-word step labels (no 'Create app' wrap that misaligned the first
circle), wider dialog (max-w-xl), and a centered overflow-safe stepper
container so the 4-step header never breaks the dialog layout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The webhook URL <code> had flex-1 + truncate but no min-w-0, so it refused to
shrink below its content width and pushed itself + the copy button past the
dialog's right edge. Add min-w-0 so truncate works.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vibegui vibegui force-pushed the vibegui/org-chat-integration branch from b0aab7e to 856fdd1 Compare June 11, 2026 21:37
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant