Microsoft Teams 渠道

📎 引用文件

本文引用的文件 - agent/src/channels/msteams.py - agent/src/channels/base.py - agent/src/channels/manager.py - agent/tests/test_msteams_inbound_body_limit.py

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能与可靠性
  8. 故障排查指南
  9. 结论
  10. 附录:部署与配置要点

简介

本章节面向在 Vibe-Trading 中启用 Microsoft Teams 渠道的读者,说明当前代码库中的 Teams 集成实现、消息处理流程、安全校验、会话引用持久化以及与企业环境相关的注意事项。需要特别说明的是:当前实现为“DM 优先”的最小可用版本(MVP),主要支持文本消息收发、Bot Framework Webhook 接收、入站令牌校验、会话引用持久化与清理;尚未内置 Adaptive Cards、富文本、附件等高级能力。

项目结构

Vibe-Trading 将多通道统一抽象为 Channel 接口,Teams 作为其中一个具体实现,通过内置 HTTP 服务器暴露 Bot Framework Webhook 端点,接收活动并转发到内部消息总线,再由出站分发器路由回 Teams。

graph TB A["Teams 用户"] --> B["Bot Framework 服务"] B --> C["Webhook: /api/messages<br/>(HTTP Server)"] C --> D["MSTeamsChannel._handle_activity()"] D --> E["BaseChannel._handle_message()<br/>权限检查/配对码"] E --> F["MessageBus.publish_inbound()"] F --> G["Agent/业务处理"] G --> H["OutboundMessage 队列"] H --> I["ChannelManager._dispatch_outbound()"] I --> J["MSTeamsChannel.send()"] J --> K["Bot Framework API<br/>发送回复"]

图表来源 - agent/src/channels/msteams.py:172-277 - agent/src/channels/base.py:179-227 - agent/src/channels/manager.py:283-369

章节来源 - agent/src/channels/msteams.py:1-120 - agent/src/channels/base.py:1-82 - agent/src/channels/manager.py:36-137

核心组件

章节来源 - agent/src/channels/msteams.py:134-171 - agent/src/channels/base.py:22-82 - agent/src/channels/manager.py:36-137

架构总览

下图展示从 Teams 用户发消息到 Agent 处理再返回回复的完整链路,包括安全校验与会话引用管理。

sequenceDiagram participant U as "Teams 用户" participant BF as "Bot Framework" participant WH as "Webhook 处理器" participant CH as "MSTeamsChannel" participant BASE as "BaseChannel" participant BUS as "MessageBus" participant AG as "Agent/业务" participant DM as "ChannelManager" U->>BF : 发送消息 BF->>WH : POST /api/messages (Activity) WH->>CH : _handle_activity(activity) CH->>CH : 校验 serviceUrl/入站令牌 CH->>BASE : _handle_message(sender, chat_id, text, meta) BASE->>BUS : publish_inbound(InboundMessage) BUS-->>AG : 进入 Agent 处理 AG-->>DM : OutboundMessage(channel="msteams") DM->>CH : send(msg) CH->>BF : POST /v3/conversations/{id}/activities BF-->>U : 显示回复

图表来源 - agent/src/channels/msteams.py:195-256 - agent/src/channels/msteams.py:330-403 - agent/src/channels/base.py:179-227 - agent/src/channels/manager.py:283-369 - agent/src/channels/msteams.py:293-328

详细组件分析

MSTeamsChannel:Webhook 接收与活动处理

flowchart TD Start(["收到 Webhook"]) --> CheckPath["校验路径"] CheckPath --> LimitBody["校验 Content-Length"] LimitBody --> ReadBody["读取并解析 JSON"] ReadBody --> AuthCheck{"是否启用入站鉴权?"} AuthCheck -- 是 --> ValidateToken["校验 JWT + JWKS"] AuthCheck -- 否 --> HandleActivity["处理活动"] ValidateToken --> HandleActivity HandleActivity --> TypeCheck{"type == 'message' ?"} TypeCheck -- 否 --> End(["忽略"]) TypeCheck -- 是 --> TrustURL["校验 serviceUrl 可信域"] TrustURL --> DMOnly{"是否 DM?"} DMOnly -- 否 --> End DMOnly -- 是 --> Sanitize["清洗文本/处理回复包装"] Sanitize --> AllowList{"是否在允许列表?"} AllowList -- 否 --> End AllowList -- 是 --> SaveRef["保存/更新会话引用"] SaveRef --> Publish["发布到 MessageBus"] Publish --> End

图表来源 - agent/src/channels/msteams.py:195-256 - agent/src/channels/msteams.py:330-403 - agent/src/channels/msteams.py:505-546 - agent/src/channels/msteams.py:698-719

章节来源 - agent/src/channels/msteams.py:172-277 - agent/src/channels/msteams.py:330-403 - agent/src/channels/msteams.py:505-546 - agent/src/channels/msteams.py:688-719

出站消息发送与线程回复

sequenceDiagram participant DM as "ChannelManager" participant CH as "MSTeamsChannel" participant BF as "Bot Framework API" DM->>CH : send(OutboundMessage) CH->>CH : 查找会话引用(service_url, conversation_id, activity_id) CH->>CH : 获取访问令牌(tenant/app_id/app_password) CH->>BF : POST /v3/conversations/{id}/activities {text, replyToId?} BF-->>CH : 200 OK CH->>CH : 刷新引用 updated_at

图表来源 - agent/src/channels/msteams.py:293-328 - agent/src/channels/msteams.py:846-869

章节来源 - agent/src/channels/msteams.py:293-328 - agent/src/channels/msteams.py:846-869

入站令牌校验与安全

flowchart TD In["收到请求"] --> HasAuth{"有 Authorization?"} HasAuth -- 否 --> Reject["401 Unauthorized"] HasAuth -- 是 --> ParseJWT["解析 JWT 头部获取 kid"] ParseJWT --> FetchJWKS["获取 JWKS"] FetchJWKS --> Verify["RS256 验签 + 校验 aud/iss/exp/nbf"] Verify --> ServiceUrlCheck{"serviceUrl 匹配?"} ServiceUrlCheck -- 否 --> Reject ServiceUrlCheck -- 是 --> Continue["继续处理活动"]

图表来源 - agent/src/channels/msteams.py:505-546 - agent/src/channels/msteams.py:547-582 - agent/src/channels/msteams.py:71-90

章节来源 - agent/src/channels/msteams.py:505-546 - agent/src/channels/msteams.py:547-582 - agent/tests/test_msteams_inbound_body_limit.py:1-56

会话引用持久化与清理

classDiagram class ConversationRef { +string service_url +string conversation_id +string bot_id +string activity_id +string conversation_type +string tenant_id +float updated_at } class MSTeamsChannel { -dict _conversation_refs -Path _refs_path -Path _refs_meta_path -Path _refs_lock_path +_save_refs_locked() +_prune_conversation_refs() +_touch_conversation_ref() } MSTeamsChannel --> ConversationRef : "维护/持久化"

图表来源 - agent/src/channels/msteams.py:121-132 - agent/src/channels/msteams.py:612-670 - agent/src/channels/msteams.py:721-762 - agent/src/channels/msteams.py:777-844

章节来源 - agent/src/channels/msteams.py:612-670 - agent/src/channels/msteams.py:721-762 - agent/src/channels/msteams.py:777-844

权限控制与配对码

章节来源 - agent/src/channels/base.py:165-227

出站分发与重试

章节来源 - agent/src/channels/manager.py:283-453

依赖关系分析

graph LR M["MSTeamsChannel"] --> B["BaseChannel"] M --> H["httpx.AsyncClient"] M --> J["PyJWT/cryptography"] DM["ChannelManager"] --> M DM --> Bus["MessageBus"]

图表来源 - agent/src/channels/msteams.py:34-53 - agent/src/channels/base.py:1-18 - agent/src/channels/manager.py:13-21

章节来源 - agent/src/channels/msteams.py:34-53 - agent/src/channels/base.py:1-18 - agent/src/channels/manager.py:13-21

性能与可靠性

章节来源 - agent/tests/test_msteams_inbound_body_limit.py:1-56 - agent/src/channels/msteams.py:71-90 - agent/src/channels/msteams.py:721-762 - agent/src/channels/manager.py:421-453

故障排查指南

章节来源 - agent/src/channels/msteams.py:172-187 - agent/src/channels/msteams.py:293-328 - agent/src/channels/msteams.py:505-546 - agent/src/channels/msteams.py:721-762

结论

当前 Vibe-Trading 的 Microsoft Teams 渠道实现了最小可用的 DM 场景:安全的 Webhook 接收、入站令牌校验、会话引用持久化、出站消息发送与线程回复。对于企业级生产环境,建议启用入站鉴权、严格限制可信域名、合理配置 TTL 与清理策略,并结合监控告警关注启动失败、入站拒绝、发送失败等关键指标。如需卡片、富文本、附件等企业协作能力,可在现有基础上扩展 MSTeamsChannel 的消息格式与附件处理逻辑。

附录:部署与配置要点

章节来源 - agent/src/channels/msteams.py:98-118 - agent/src/channels/msteams.py:172-187 - agent/src/channels/msteams.py:698-719 - agent/src/channels/msteams.py:721-762