Microsoft Teams 对话 Agent
Microsoft 当前将 Microsoft 365 Agents SDK 定位为构建跨渠道对话 Agent 的框架:它接收并标准化 Activity、路由处理器,再把响应发回 Teams。本文以该 SDK 为新建项目主路径;核验日期为 2026-09-08,未创建 Entra 应用或 Azure 资源。
- Workflows Webhook 用于把外部通知送进频道,不是接收用户自由文本的对话 Bot。
- Teams 对话需要 Agent/Bot 身份、消息 Endpoint、Teams App Manifest 和组织安装/同意流程。
- Agents SDK 负责渠道、Activity 与会话状态,不是 LLM、编排引擎或无代码 AI 产品。
- 旧 Bot Framework SDK 教程仍可能可见;新建项目应先采用 Agents SDK,并按 Microsoft 生命周期说明评估迁移。
- 有 Microsoft 365 开发租户或允许侧载测试 App 的 Teams 环境。
- 能创建 Microsoft Entra 应用/Agent 身份,并按官方流程配置 Azure 资源。
- 准备公网 HTTPS 消息 Endpoint;本地使用 Microsoft 365 Agents Playground 或隧道调试。
- JavaScript 使用 Node.js 18+;Python 使用官方当前支持的 3.9-3.11 版本范围。本文示例以 Node.js 20 为基线。
- 按 Agents SDK Quickstart 创建基础 Agent,先在 Playground 完成 echo。
- 使用 Microsoft 365 Agents Toolkit 或官方脚本预配 Entra/Azure 身份与消息 Endpoint。
- 在 Teams App Manifest 的
bots中声明 Bot ID、scope(personal、team、groupChat)及需要的能力。 - 将 Messaging Endpoint 指向部署服务的
/api/messages,配置应用 ID、租户类型和凭据。 - 打包并侧载/发布 Teams App;组织策略可能要求管理员审批。
- 在个人聊天和测试团队分别发送
/ping,确认 Activity 入站与回复。
不要手工复制过期 Bot Framework 模板中的包名和认证设置。Agents SDK 仍在快速演进,初始化代码以当前 Quickstart 生成的项目为准。
文本消息被标准化为 message Activity。常用上下文包括 activity.id、conversation.id、from.id、recipient.id、channelId、serviceUrl 和 text。Teams 群聊中的 Bot mention 可能编码在 entities 和文本中,应使用 SDK 工具移除 mention。
以 Activity ID 做事件去重。会话键建议 teams:{tenantId}:{conversation.id};若产品要求不同用户在同一群聊隔离 AI 上下文,再加入 from.id。serviceUrl 和对话引用属于回复路由信息,不进入提示词。
本地消息 Endpoint 验证
Section titled “本地消息 Endpoint 验证”真实 Teams 请求包含渠道签发的 Bearer Token,必须由 SDK 验证。下面只用于本地 Playground/测试桩,不能绕过生产鉴权;JavaScript/Python 处理器需放入当前 Quickstart 生成的宿主。
curl -X POST 'http://localhost:3978/api/messages' \ -H 'Authorization: Bearer PLAYGROUND_TOKEN' \ -H 'Content-Type: application/json' \ -d '{"type":"message","id":"activity-test-1","channelId":"emulator","conversation":{"id":"conversation-test"},"from":{"id":"user-test"},"recipient":{"id":"agent-test"},"text":"/ping","serviceUrl":"http://localhost:3978"}'// 注册到 Agents SDK Quickstart 创建的 AgentApplication。agent.onActivity('message', async (context) => { const text = context.activity.text?.trim(); await context.sendActivity(text === '/ping' ? 'pong' : '输入 /help 查看命令');});# 注册到 Agents SDK Quickstart 创建的 AgentApplication。@agent_app.activity("message")async def on_message(context): text = (context.activity.text or "").strip() await context.send_activity("pong" if text == "/ping" else "输入 /help 查看命令")SDK 的具体注册方法可能随版本变化;以上处理器展示稳定的 Activity 输入/回复关系,项目脚手架和认证中间件必须使用当前官方 Quickstart。
普通 API 双向回复
Section titled “普通 API 双向回复”收到 message Activity 后,先去除 Bot mention,再路由 /ping、/status、工单查询等命令。处理器可调用任意内部 API,并通过当前 turn context 的 sendActivity 回复同一会话。
耗时任务先发送进度或把 ConversationReference 安全保存后异步主动回复。主动消息需要遵循 Teams 的身份、安装范围与 service URL 规则,不能仅保存会话 ID 后自行拼 HTTP 请求。
AI 对话扩展
Section titled “AI 对话扩展”const conversationKey = `teams:${tenantId}:${context.activity.conversation.id}`;const answer = await generateReply({ messages: await history.withUserMessage(conversationKey, normalizedText), signal: AbortSignal.timeout(20_000),});await context.sendActivity(answer);Agents SDK 官方明确保持 AI 厂商无关,因此 generateReply 可以对接任意模型或规则处理器。使用 Adaptive Card 展示引用、反馈或确认动作,但不要让卡片交互直接绕过服务端授权。
安全与可靠性
Section titled “安全与可靠性”- 所有
/api/messages请求交给官方认证中间件验证,不信任客户端自报的租户、用户或 service URL。 - App Secret、证书和 Entra 凭据只在服务端/托管密钥服务中保存,生产优先采用可轮换凭据或托管身份。
- 用 Activity ID 做事件去重,同一会话串行处理;主动消息保存 SDK 定义的 Conversation Reference。
- 在 Manifest 中只声明需要的 scope 和权限,遵循组织 App 审批、数据驻留与审计要求。
- 对模型输入脱敏,防范提示词注入;执行 Microsoft Graph 或内部工具时按当前用户重新鉴权。
Playground 可用,Teams 中收不到消息:检查 Messaging Endpoint 公网可达、身份配置、Manifest Bot ID、App 安装范围和组织策略。
个人聊天可用,团队频道不触发:检查 Manifest 是否声明 team scope、Bot 是否安装到团队,以及消息是否包含正确 mention。
生产接口用 curl 返回 401:这是预期保护。真实 Activity 必须带渠道签发并由 SDK 验证的 Token,不能用占位 Token 绕过。
应该继续用 Bot Framework SDK 吗:维护现有系统时按官方迁移指南评估;新建系统优先 Microsoft 365 Agents SDK。