feat(msteams): support multiple bot accounts#112811
Conversation
|
Validated replacement head ed5788d after a forward-only merge of upstream/main (4a2a600). The prior published head 299d96a and that upstream head are both direct parents/ancestors; no history was rewritten. GitHub reports this PR MERGEABLE, and the fork branch ref and PR internal head both equal ed5788d. Local validation passed: check:test-types; 82 Microsoft Teams test files / 1,215 tests; lint; generated channel config check; max-lines ratchet; 124 extension package-boundary compiles; deadcode exports; docs map; and git diff --check. The exact PR diff against upstream/main is 91 files with no CHANGELOG.md. |
…-account-replacement-20260722 # Conflicts: # src/config/zod-schema.providers-core.ts
|
Validated repaired head The upstream merge had one real conflict because Teams config schemas moved from core into extension-owned config APIs. The resolution keeps upstream's new ownership boundary and relocates only the Teams multi-account refinement into the Teams extension. A separate review of that resolution found no correctness or ownership issues. Validation on this exact head:
The cleanup also removes unrelated rescue tests and an abandoned helper; each locale file now adds only the two required Teams webhook prompts. Codex review regressions cover named inbound account scoping and named-default directory credential isolation. |
|
Validated current head |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Codex review: needs real behavior proof before merge. Reviewed July 24, 2026, 7:39 PM ET / 23:39 UTC. ClawSweeper reviewWhat this changesThe PR lets one OpenClaw gateway host multiple Microsoft Teams bot identities, routing each account to an agent while retaining the legacy single-bot configuration shape. Merge readiness⛔ Blocked until stronger real behavior proof is added - 6 items remain This is a substantial, still-needed Microsoft Teams capability rather than an obsolete replacement branch. The proposed account model affects credentials, routing, persistent channel state, setup, and legacy configuration, so it needs explicit maintainer sponsorship of the public configuration contract plus upgrade-focused review before merge; the linked live smoke is promising but could not be independently inspected in this read-only environment. Priority: P2 Review scores
Verification
How this fits togetherMicrosoft Teams is a plugin-backed channel whose webhook ingress selects an account and routes the conversation to an agent. That account context then determines credentials, Graph access, persisted conversation and token state, setup behavior, and outbound replies. flowchart LR
A[Teams bot webhooks] --> B[Account selection]
B --> C[Agent routing]
C --> D[Teams channel runtime]
D --> E[Account-scoped credentials and state]
E --> F[Replies and Graph actions]
Decision needed
Why: This is a new channel capability and configuration contract with compatibility-sensitive state and credential semantics; implementation correctness cannot decide whether this is the desired permanent product surface. Before merge
Agent review detailsSecurityNone. Review metrics
Stored data modelPersistent data-model change detected: Root-cause clusterRelationship: Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Sponsor one canonical Teams account model, retain the documented legacy single-bot behavior for existing installations, and land only after focused upgrade proof demonstrates that old root-level configuration and state remain usable while named accounts stay isolated. Do we have a high-confidence way to reproduce the issue? Not applicable as a feature request. The contributor reports a real two-bot Teams smoke, but the supplied screenshot could not be independently inspected in this environment. Is this the best way to solve the issue? Unclear. The implementation follows the repository’s existing multi-account channel vocabulary, but maintainers must first confirm that this permanent Teams configuration model is preferable to a narrower or staged API. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 872ba27ff363. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
|
|
@clawsweeper re-review The PR now includes focused upgrade evidence on head |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: feat(msteams): support multiple bot accounts This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
|
@clawsweeper re-review Please review the current validated head |
|
🦞🧹 I asked ClawSweeper to review this item again. |
Related: #71058
What Problem This Solves
Resolves a problem where Microsoft Teams could only be configured as one bot identity per OpenClaw gateway. That made it difficult to run multiple Teams-visible agents, each with its own Teams app/bot registration, from the same OpenClaw instance.
Why This Change Was Made
This adds first-class account support to the Microsoft Teams channel while preserving the legacy single-bot configuration path.
channels.msteams.accounts.<id>defines Teams bot accounts,channels.msteams.defaultAccountselects the implicit account, and existing root-level credentials and webhook configuration continue to work as the default account.Named accounts keep identity fields explicit while shared tenant, policy, Graph/SSO, streaming, and delivery settings can be inherited from the root and overridden per account. Inbound handling, proactive sends, replies, Graph actions, delegated and SSO token state, polls, sent-message state, conversation state, probes, setup flows, and routing carry account context.
This PR intentionally keeps the existing per-account listener model. Route-based multiplexing on one listener remains a possible focused follow-up.
User Impact
Operators can configure multiple Microsoft Teams bot identities on one gateway and bind each account to the agent that should answer. Existing root-level single-bot configurations remain valid and do not require bindings.
Evidence
pnpm test -- extensions/msteams/src/conversation-store-state.test.ts extensions/msteams/src/channel.test.ts src/routing/resolve-route.test.tspassed (86 tests). It covers legacy root-level credentials routing todefault, and confirms pre-account unscoped persisted conversation state remains readable and writable through the new default-account wrapper.pnpm test:extension msteams: 82 files, 1,216 tests passed.pnpm check:test-types: passed across core, extensions, and root tests.pnpm lint --threads=8: passed.pnpm config:channels:check: passed.pnpm check:max-lines-ratchet --base upstream/main: passed.pnpm run test:extensions:package-boundary:compile: 124 plugins passed.pnpm deadcode:dependencies,pnpm deadcode:unused-files, andpnpm deadcode:exports: passed; unused-file/export scans reported zero entries.pnpm docs:map:check: passed.pnpm test -- src/cli/hooks-cli.process.test.ts: 3 tests passed; this is the exact upstream-only flaky test that failed on the obsolete PR head.upstream/main: 90 scoped files, noCHANGELOG.md, andgit diff --checkpassed.MSTEAMS_*credentials for a named default. Both have regression coverage.AI-assisted: yes. I used Codex to implement, reconcile current upstream changes, test, audit, and review the change, and I reviewed the resulting behavior and code paths.
Replacement chain: this PR supersedes #104692, which superseded #97340. The first replacement moved the contribution from the Spinen organization fork to my personal fork so maintainers could edit it. During later recovery, #104692 remained internally attached to obsolete head
b686b0171453while its named fork branch moved to a clean, unrelated lineage, so that PR could no longer follow branch updates. This replacement uses a new branch, preserves both old PRs as review history, contains the audited feature commit, and merges currentupstream/mainwithout rebasing or rewriting any published branch.