安全扩展 Microsoft 365 Copilot 的正确姿势:深入浅出声明式代理(Declarative Agent)

2026年3月21日社区分享

一、为什么要”安全地扩展” Microsoft 365 Copilot?

Microsoft 365 Copilot 定位为”AI built for work”,提供了多模型协作、安全管理与治理、以及代理平台生态三大能力层。然而,原生 Copilot 主要基于通用知识回答问题,难以直接满足企业的垂直场景需求。典型痛点包括:知识缺口:企业有大量私有知识(内部技术文档、产品手册、HR 政策等),Copilot 默认无法获取。例如员工 IT 自助代理客户支持代理需要基于公司专属知识库进行推理和回答。

  • 行动力不足:仅能回答问题远远不够,企业还希望 Copilot 能通过 API 与外部系统交互——查询工单状态、提交报销单、下订单——真正”代替用户做事”。
  • 安全与合规:不当的扩展可能将敏感凭据暴露给客户端或引入越权访问。因此,任何扩展方案都必须复用 M365 平台内建的安全控制,保证数据安全和企业治理要求。

这三个痛点共同指向一个核心需求:一种既能注入企业专属知识和操作能力,又不突破 M365 现有安全体系的扩展方案。声明式代理(Declarative Agent)正是微软为此设计的解决路径。

二、什么是声明式代理?它在 Copilot 体系中的位置

2.1 定义

代理(Agent 是可在聊天界面中与用户交互的对话式 AI,能够回答问题、提供信息并代表用户执行任务,常用于客户支持、IT 技术支持和 HR 支持等场景。

声明式代理 则是一种专门用于扩展 Microsoft 365 Copilot 的代理类型。开发者通过配置(而非从零编码)的方式,定义自定义知识自定义操作,以创建针对特定应用场景定制的助手。其关键特征是:使用与 Microsoft 365 Copilot 相同的基础结构、业务流程协调程序、基础模型和安全控制,从而确保一致且熟悉的用户体验。

2.2 与 Prompt Engineering 和 Custom Engine Agent 的对比

维度 Prompt Engineering 声明式代理 (Declarative Agent) 自定义引擎代理 (Custom Engine Agent)
核心思路 在 Copilot Web Chat 中编写清晰、结构化、上下文丰富的输入,引导 Copilot 生成准确和相关的响应 [ 通过配置 Instructions、Grounding 数据源和 API 插件来扩展 M365 Copilot “带上你自己的模型”,构建高度可定制的专业代码解决方案
编排器 / 基础模型 使用 M365 Copilot 原有编排器与模型 复用 M365 Copilot 编排器与模型 可自定义编排器和模型,允许更改规划和执行流程
数据访问 仅限 Copilot 原有数据范围 M365 数据源 + Graph 连接器 + API 插件 可访问 Microsoft 生态内外各种来源的数据
适用人群 所有用户 从信息工作者到专业开发者均可构建 主要面向需要完全控制的专业开发者
发布渠道 可选添加到 Prompt Gallery(仅桌面端) 侧加载 / 组织目录 / Microsoft 商业市场 侧加载 / 组织目录 / Microsoft 商业市场

选型建议

  • 如果只需临时优化某次对话的格式或风格,Prompt Engineering 即可满足。
  • 如果有明确的业务场景需要注入企业知识、对接外部 API,且希望留在 M365 安全体系内,声明式代理是最佳选择。
  • 如果需要完全自定义 LLM 模型或编排流程,例如使用非微软的 LLM,则应考虑自定义引擎代理。

三、核心能力:自定义知识与自定义操作

声明式代理的能力来自两个可定制维度:自定义知识(为 LLM 提供额外数据与上下文)和自定义操作(使代理能与外部系统实时交互)。

3.1 自定义知识

自定义知识由两部分组成:

1)自定义说明(Instructions——定义代理的行为方式以及应如何形成其响应。说明可包含四类内容: [

  • 任务定义:概述模型应执行的操作(如回答问题、汇总文本)
  • 行为准则:设置响应的语气、风格和细节级别
  • 内容限制:指定应避免的内容(如敏感主题、版权材料)
  • 格式设置规则:规定输出结构(如项目符号、特定格式)

以 IT 支持场景为例,PPT 中给出的指令示例为:你是 IT 客户支持,一个智能助手,旨在回答 Contoso Electronics 员工提出的常见 IT 支持查询,并管理支持票证……响应应简洁且适合非技术受众。 [

2)自定义基础设置(Grounding——定义代理可在其响应中使用的数据源。默认情况下声明式代理未连接到任何数据源,可配置的 M365 数据源包括: OneDrive 中的文档

  • SharePoint Online 中的文档
  • 通过 Graph 连接器引入 Microsoft 365 的内容
  • Web 搜索(来自com 的结果)

Grounding 的本质是将 LLM 连接到实际信息,使响应更准确、更相关,减少对训练数据的依赖,提高响应质量。当 Copilot 在答案中使用了 Grounding 数据时,会在响应中引用数据源。

3.2 自定义操作

自定义操作使声明式代理能够实时与外部系统交互。通过创建操作并与代理集成,使用 API 读取和更新外部系统中的数据。例如在 IT 支持场景中,自定义操作可以通过 API 在支持票证系统中读取和写入数据。操作的实现方式是通过 API 插件,允许声明式代理调用 API。

3.3 协同工作流程

当用户提交提示后,M365 Copilot 按照以下步骤处理:输入:用户提交提示

  1. 初步检查:执行负责任的 AI 和安全风险检查
  2. 推理:创建响应计划
    • 基础设置数据中检索相关信息
    • 操作(API 插件)中检索数据
    • 检索声明式代理指令
  3. 响应:编排器编译所有数据,传递给 LLM 生成最终响应
  4. 输出:将响应传递到用户界面并更新对话

四、工程化构建路径:TypeSpec + Microsoft 365 Agents Toolkit

4.1 构建工具选择

PPT 中给出了完整的工具矩阵,声明式代理支持从 No-code 到 Pro-code 的多层次构建方式:

工具 编码方法 声明式代理 自定义引擎代理 适用场景 前置要求
SharePoint No-code 商务用户为特定目的定制 Copilot 或指定特定网站、文档库供搜索 M365 订阅 + 网站管理员权限
Copilot Studio Agent Builder No-code 无编程经验的商务用户提升个人和团队生产力 M365 订阅
Copilot Studio Low-code 需要低代码且包含 Power Platform 集成的信息工作者和业务用户 M365 订阅 + Copilot Studio 许可
M365 Agents Toolkit Pro-code 开发者需要对编码环境、源码管理和 API 拥有完全控制权 M365 订阅(启用侧加载)+ VS Code/VS + Azure 订阅(可选)
M365 Agent SDK Pro-code 需要控制权并希望构建在 Teams 应用商店公开的代理 Agent SDK 利用 Azure 机器人服务
Azure AI Foundry SDK Pro-code 在统一 Azure AI SDK 下提供代理开发能力 Azure OpenAI Services 和 Azure Cognitive Services
Semantic Kernel SDK Pro-code 构建代理并集成多种 AI 服务,定义编排链 Azure AI Agent Service 或 OpenAI API 密钥

企业管理员可以管理哪些用户通过 Actions 和特定连接器构建更高级的代理。

4.2 TypeSpec:微软开源的 API 定义语言

TypeSpec 是由 Microsoft 开发的开源语言,用于简化 API 设计与开发。它在声明式代理工程化中扮演的角色包括:

  • 启用声明式代理:支持为 M365 Copilot 生成声明性代理,简化代理自定义和部署
  • 模块化且可扩展:允许针对各种开发方案和 API 标准合规性的可重用组件和扩展性
  • 集成与兼容性:确保与 OpenAPI 等工具兼容,促进与现有工作流和系统的无缝集成

TypeSpec 的核心语法元素包括:

  • 命名空间(namespace:组织 API 定义
  • 模型(model:使用 model 关键字为代理输入和输出指定结构化数据
  • 操作(op:使用 op 关键字定义 API 终结点和代理操作
  • 修饰器(@:使用 @ 语法应用元数据和约束,实现 M365 集成

TypeSpec 的开发者优势可以概括为五点:简化 API 开发(降低复杂性)、确保合规性(可重用组件遵循行业准则)、增强兼容性(OpenAPI 发射器无缝集成)、支持扩展性(允许自定义 API 定义)、加速部署(快速生成服务和客户端代码)。

4.3 构建流程概览

以 Pro-code 方式为例,端到端流程如下:

Step 1 — 创建项目:打开 VS Code,安装 M365 Agents Toolkit 扩展,选择”创建新代理/应用” → “声明性代理” → “TypeSpec for Microsoft 365 Copilot”。

Step 2 — 定义指令与对话开场白:在 main.tsp 中使用 @instructions 修饰器添加代理行为指令,使用 @conversationStarter 添加预设对话引导。例如:

TypeScript

@instructions(“””

你是声明性代理,由 Teams Toolkit 创建。你是创作诗歌的专家。

每次用户提问时,你必须将答案转化为一首诗。

“””)

@conversationStarter(#{ 标题: “入门指南”, 文本: “如何开始使用智能体工具

显示更多行

【5000†L1622-L1632】

Step 3 — 添加知识源:在 main.tsp 的命名空间中逐一添加能力声明。例如添加 Web 搜索能力:

TypeScript

namespace MyAgent {

op webSearch is AgentCapabilities.WebSearch<TSites = [

{ url: “https://learn.microsoft.com” }

]>;

}

显示更多行

【5000†L1750-L1758】

类似地,可以添加 OneDrive/SharePoint 集成(AgentCapabilities.OneDriveAndSharePoint)、Teams 消息(AgentCapabilities.TeamsMessages)、电子邮件(AgentCapabilities.Email)、图像生成(AgentCapabilities.GraphicArt)和代码解释器(AgentCapabilities.CodeInterpreter)【5000†L1802-L1808】【5000†L1868-L1874】【5000†L1937-L1944】【5000†L2000-L2001】【5000†L2044-L2045】。

注意事项:如果未指定 TSites / TItemsByUrl / TUrls 等数组参数,M365 组织中的所有相关内容都将对代理可用【5000†L1773-L1777】【5000†L1833-L1845】【5000†L1895-L1904】。在生产环境中,应精确限定可访问范围。

Step 4 — 预配与测试:在 Toolkit 生命周期窗格中选择”预配置”以配置代理;然后在 M365 Copilot 应用程序中选择代理并进行交互式测试,验证响应是否符合预期【5000†L1531-L1553】。

五、API 插件如何让代理”真正做事”

5.1 工作机制

API 插件是声明式代理执行自定义操作的核心载体。每次用户提交提示时,代理按以下流程处理【5000†L2142-L2201】:

  1. 用户提示提交 (1):用户向代理发送请求
  2. 函数评估 (2):代理使用基础语言模型,根据可用的插件和函数说明评估提示,判断是否有合适的函数可调用
  3. API 请求处理 (3):匹配函数后,代理在必要时进行身份验证 (3a, 3b),构造 API 请求并调用 API (3c),处理其响应 (3d)
  4. 响应生成 (4-6):代理处理 API 响应,生成用户友好的回答

5.2 插件定义的三大组成部分

一个 API 插件定义文件(如 ai-plugin.json)包含三个核心部分【5000†L2405-L2436】:

  • 基本信息:namespace、name_for_human、description_for_human、description_for_model——其中 description_for_model 尤为重要,它直接影响 LLM 理解插件用途的能力
  • 函数(Functions:定义插件可执行的一个或多个 API 操作
  • 运行时(Runtimes:描述插件使用哪些 API,以及哪些函数属于哪个 API

5.3 函数描述的准确性——被低估的关键设计点

函数的 description 字段是代理将函数与用户提示匹配的依据【5000†L2542-L2549】。PPT 中明确指出:如果说明不准确或不完整,代理就无法将其与特定提示匹配,并且无法调用函数【5000†L2547-L2550】。因此在描述函数时,必须说明它完成的任务及其变化(如筛选、排序信息)【5000†L2547-L2549】。

这是一个容易被忽视但至关重要的工程细节:函数描述的质量直接决定了代理的智能程度

5.4 响应语义与自适应卡片

API 通常返回结构化数据,如何让代理以最优方式呈现这些数据?答案是响应语义(response_semantics。在函数定义的 capabilities 部分,开发者可以配置【5000†L2518-L2535】:

  • data_path:指定 JSON 响应中的数据路径(如 $.dishes)
  • properties:映射字段含义(如 title → $.name,subtitle → $.description)
  • static_template:定义自适应卡片模板,控制代理向用户呈现来自 API 的数据的方式【5000†L2932-L2957】

使用自适应卡片的好处是:代理可以将 API 返回的结构化数据渲染为图文并茂的卡片,而非仅依赖语言模型动态生成文本格式(后者可能并不总是选择最佳格式)【5000†L2901-L2918】。

5.5 运行时定义与 OpenAPI 规范

运行时中需要配置的关键属性包括【5000†L2553-L2605】:

  • type:API 描述类型,目前仅支持 OpenAPI【5000†L2578-L2579】
  • auth:身份验证类型(None 表示匿名调用;需要安全通信时应更新为对应的认证机制)【5000†L2582-L2590】
  • spec:引用本地 API 规范文档的相对路径(如 apiSpecificationFile/ristorante.yml)【5000†L2591-L2596】
  • run_for_functions:指定属于此 API 的函数列表。M365 Agents Toolkit 会验证此属性中的函数与函数部分定义的函数是否匹配,不匹配则报错【5000†L2600-L2607】【5000†L2690-L2698】

API 规范为代理提供了四类关键信息:API 位置(托管详情)、身份验证要求、支持的操作列表、以及每个操作的预期数据和响应格式【5000†L2703-L2724】。工程上的重要提示:如果使用现有的大型 API 规范,应仅包含计划使用的部分——包含整个规范会使代理更难解析出相关信息。可以使用 Microsoft 提供的 Hidi 工具来提取 API 规范的相关部分【5000†L2764-L2789】。代理支持 YAML 和 JSON 中的 OpenAPI API 规范【5000†L2792-L2795】。

5.6 整体架构关系

各组件之间的关系如下【5000†L2822-L2884】:

  • Microsoft Teams 应用:用于打包和分发代理,每个 Teams 应用可包含一个或多个声明式代理
  • 声明式代理:针对特定方案优化,可包含零个或多个 API 插件
  • API 插件:允许与外部系统通信,定义一个或多个函数
  • 函数:每个函数执行一个特定任务,只引用一个 API 操作
  • API 规范:描述插件所使用的 API 及其操作

六、安全如何”内建”:API Key、OAuth 2.0 与保管库

在企业环境中,声明式代理对外部 API 的访问必须经过严格的身份验证和权限控制。PPT 中详细介绍了两种安全模式和保管库机制。

6.1 API Key 模式

适用场景:API 使用静态密钥进行授权。

工作原理【5000†L2970-L2993】:

  1. 在 OpenAPI 规范的 securitySchemes 部分定义 apiKey 属性,指定使用 API 密钥作为授权请求标头中持有者令牌的安全方案【5000†L2998-L3002】
  2. /repairs.get.security 属性引用 apiKey 安全方案【5000†L3003-L3007】
  3. API 端的处理程序函数(如 repairs)会拒绝所有未授权请求(状态码 401),isApiKeyValid 函数检查授权标头中的持有者令牌,并与 API_KEY 环境变量进行比较【5000†L3019-L3031】

密钥安全存储

  • Toolkit 的 apiKey/register 任务将 SECRET_API_KEY 项目变量注册到保管库(Vault)中【5000†L3039-L3043】
  • 保管库条目 ID 写入 env/.env.local 以创建 APIKEY_REGISTRATION_ID 环境变量【5000†L3044-L3049】
  • Toolkit 将 APIKEY_REGISTRATION_ID 写入 appPackages/ai-plugin.json 插件定义【5000†L3050-L3057】
  • 运行时:加载 API 插件的声明式代理使用此 ID 从保管库中检索 API 密钥,并安全地调用 API——密钥全程不在客户端暴露【5000†L3058-L3064】

6.2 OAuth 2.0 授权模式

适用场景:需要基于用户身份的细粒度授权的受保护 API。

核心配置要素【5000†L3077-L3102】:

要素 说明
CLIENT_ID / CLIENT_SECRET OAuth 集成所需的客户端凭据【5000†L3079-L3082】
标识提供者终结点 身份验证服务器地址【5000†L3082-L3083】
身份验证流程 M365 Copilot 使用这些信息代表用户进行身份验证以获取访问令牌【5000†L3084-L3089】
安全存储 存储在 M365 保管库中、未向客户端应用公开的机密信息【5000†L3090-L3096】
PKCE(代码交换的证明密钥) (可选)以最低开销为应用程序增加额外安全性,即使使用机密客户端也是如此【5000†L3097-L3102】

运行时流程【5000†L3103-L3114】:

  1. 声明式代理加载插件 (2)
  2. 从保管库中指定条目检索 OAuth 信息 (3a)
  3. 遵循授权代码授予类型(Authorization Code Flow)获取访问令牌 (3b)
  4. 使用访问令牌调用受保护的 API (3c)

OpenAPI 规范中的定义:components.securitySchemes 部分包含 oAuth2AuthCode 属性,该属性定义 OAuth2 安全方案,并包含有关用于调用的 URL 的信息以及 API 使用的范围(Scope)【5000†L3123-L3129】。

保管库注册:oauth/register 任务在保管库中注册 TEAMS_APP_ID、AAD_APP_CLIENT_ID 和 SECRET_AAD_APP_CLIENT_SECRET 项目变量,并启用 PKCE 以提高安全性【5000†L3168-L3181】。保管库条目 ID 写入 env/.env.local 创建环境变量,Toolkit 将 OAUTH2AUTHCODE_CONFIGURATION_ID 写入 appPackages/ai-plugin.json 插件定义【5000†L3182-L3195】。oauth/update 任务使保管库中的 OAuth 信息与项目保持同步,开发隧道需要这些信息使 Copilot 能够访问 API【5000†L3206-L3212】。

API 端的验证:API 运行 Azure Functions 并使用”简易身份验证“(Easy Auth)来验证访问令牌。在 Easy Auth 验证令牌后,API 插件会验证所需的范围【5000†L3150-L3157】。repairs 处理程序函数会拒绝没有访问令牌和必要范围的请求,并显示 403 错误;hasRequiredScopes 函数检查访问令牌是否具有必要的范围,而无需验证令牌本身【5000†L3145-L3149】。

身份验证与授权配置(infra/azure.bicep)【5000†L3218-L3235】:

  • globalValidation 部分仅允许经过身份验证的请求,未经身份验证的请求以 401 拒绝
  • identityProviders 指定 Microsoft Entra ID 用于授权请求
  • 定义用于保护 API 安全的 Microsoft Entra 应用注册,并指定允许的访问群体

Entra 应用注册(aad.manifest.json)中,oauth2Permissions 属性定义名为 repairs_read 的自定义范围,以授予客户端读取修复 API 的权限;identifierUris 属性定义用于完全限定范围的标识符【5000†L3246-L3258】。

6.3 保管库(Vault)的核心作用

无论 API Key 还是 OAuth 模式,敏感凭据始终存储在保管库中,插件配置文件中引用的只是保管库中条目的标识符(如 APIKEY_REGISTRATION_ID 或 OAUTH2AUTHCODE_CONFIGURATION_ID),而非明文密码【5000†L3040-L3057】【5000†L3188-L3195】。这种设计将认证步骤与业务逻辑隔离,确保开发者和最终用户都无需直接处理敏感凭据。

6.4 安全设计的取舍

模式 优势 局限 适用场景
API Key 实现简单,配置少 密钥权限管理粗粒度,无法区分用户身份 简单接口,无需用户级授权
OAuth 2.0 + Entra ID 用户级授权,细粒度 Scope 控制,支持 PKCE 配置步骤多,需要 Entra 应用注册 企业级受保护 API,需要合规审计

七、何时选择声明式代理?何时不该选?

✅ 适合使用的场景

根据 PPT 给出的决策因素【5000†L1147-L1197】:

  • 有明确的特定主题或任务需要优化——”我是否有想要优化的特定主题或任务?”是考虑声明式代理时要问的关键问题。当你知道要优化的应用场景时,声明式代理可以顺利运行【5000†L1161-L1164】。
  • 数据主要在 M365 生态内——当 M365 中提供了与应用场景相关的信息时,声明式代理效果最佳。如果需要从外部系统引入数据,可使用 Graph 连接器;需要实时交互则使用自定义操作【5000†L1185-L1194】。
  • 希望复用 M365 Copilot 现有架构与安全控制——声明式代理使用与 M365 Copilot 相同的业务流程协调程序和模型,为最终用户提供一致的体验【5000†L1171-L1175】。

典型场景包括:员工 IT 自助代理客户支持代理【5000†L759-L765】,以及需要将 Web 内容、OneDrive/SharePoint 数据、Teams 消息和电子邮件等知识源集成到对话体验中的场景【5000†L1717-L1726】。

❌ 不适合使用的场景

  • 需要自定义业务流程和/或使用其他大型语言模型——此时不能选择声明式代理,应考虑生成自定义引擎代理【5000†L1173-L1178】。
  • 关键数据完全不在 M365 且无法通过 Graph 连接器引入——此时 API 插件虽然可以提供实时跨系统访问能力,但过于复杂的外部依赖可能影响效率。
  • 仅需临时性的输出格式调整——直接使用 Prompt Engineering 即可,声明式代理更适合持续使用的可复用场景【5000†L516-L521】。
  • API 使用的复杂查询模式超出语言模型的能力——需要评估 API 是否对用户友好,或者是否需要可能挑战语言模型的复杂查询【5000†L2256-L2259】。

 

Microsoft 365 Copilot 的声明式代理提供了一条安全、工程化、低成本的扩展路线。它复用 M365 的基础模型、编排器和安全基础设施,通过自定义知识注入领域上下文,通过API 插件赋予行动能力,并通过保管库 + API Key / OAuth 2.0 + Entra ID 的多层安全机制确保企业合规。TypeSpec 和 M365 Agents Toolkit 的组合使这一切可以在 VS Code 中以声明式语法完成定义、测试和发布。对于有明确业务场景、数据在 M365 生态内、且希望在安全可控前提下快速扩展 Copilot 能力的团队,声明式代理是值得深入实践的方向。