使用响应语义显示引文

引文可建立对智能 智能 Microsoft 365 Copilot 副驾驶® 副驾驶®响应准确且扎实的信任。 响应正文自动包含 Copilot 合成响应的引文。 但是,最终用户可能无法打开信息源。 当 Copilot 基于公共 Web 内容的响应时,会自动引用该 URL。

对于来自 模型上下文协议 (MCP) 服务器API 的内容,该内容必须返回最终用户可以打开和查看的 URL。 在插件定义中定义 response_semantics ,以便 Copilot 知道该 URL 在插件响应中的位置,并且可以使用正确的链接使引文可单击。

如果跳过此步骤,响应仍包含引文,但仅包含具有代表性的药丸或图标。 最终用户无法单击并确认站点中的数据。 这就是为什么可点击引文也是发布到应用商店的应用智能 智能 Microsoft 365 Copilot 副驾驶® 副驾驶®代理存储策略要求的原因。

Copilot 还可以从常见字段名称自动推断引文元数据,因此不再需要显式定义 response_semantics。 显式 response_semantics 在提供它们时仍优先。 在使用 动态工具发现时,依赖此动态回退特别有用,因为动态工具发现工具图面可在运行时更改。 有关详细信息,请参阅 动态响应语义

在 Copilot 响应中可单击引文的悬停体验上。

重要

无需自适应卡片即可获取引文。 仅响应语义( data_path 加上几个 properties 映射)就足以让 Copilot 呈现指向源的可单击引文。

请考虑使用交互式 MCP 应用 来获取除引文之外的丰富 UX。

使用响应语义

插件清单中定义的响应语义充当 MCP 服务器或 API 与 Copilot 之间的协定。

  1. 工具返回 JSON。

  2. 插件清单中:

    • 告知 Copilot citable 项在该 JSON 中的位置 (data_path) 。
    • 你告诉 Copilot 每个项上的哪些字段映射到引文的标题、副标题和 URL (properties) 。
  3. Copilot 为每个项目呈现引文。 用户单击指向源。

如果提供显式 properties 映射,则 Copilot 会按原样使用它们。 仅当不存在这些映射时,动态推理才适用。 有关详细信息,请参阅 动态响应语义

最低配置

配置 response_semantics 由工具响应的形状驱动,而不是由工具响应的协议驱动。 具有所有工具协议 (MCP、OpenAPI、消息扩展的 Copilot 代理) 使用相同的清单架构。

大多数工具响应分为以下两种形式之一:

  • 结果数组 (类似于搜索工具) :该工具返回多个项,其中每个项应成为自己的引文。
  • 单个对象 (类似于提取工具) :该工具只返回一个文档或记录,这将成为单个引文。

搜索样式) (结果数组

返回多个项的工具通常在 (或等效) 键下 results 返回数组,如以下示例所示。

{
  "results": [
    {
      "id": "tr-001",
      "title": "Forecasting AI adoption in the enterprise (2026)",
      "url": "https://www.treyresearch.net/notes/ai-adoption-2026",
      "publishedDate": "2026-03-12",
      "thumbnailUrl": "https://www.treyresearch.net/assets/trey-research-logo.png"
    },
    {
      "id": "tr-005",
      "title": "Enterprise AI spend, deep dive",
      "url": "https://www.treyresearch.net/notes/ai-spend",
      "publishedDate": "2026-03-28",
      "thumbnailUrl": "https://www.treyresearch.net/assets/trey-research-logo.png"
    }
  ]
}

以下示例显示了插件清单中的最小响应语义配置。

"capabilities": {
  "response_semantics": {
    "data_path": "$.results",
    "properties": {
      "title": "$.title",
      "subtitle": "$.publishedDate",
      "url": "$.url"
    }
  }
}

属性 data_path 指向数组。 每个元素生成其自己的可单击引文。 properties JSONPath 是相对于每个数组元素而不是根元素解析的。

单个对象 (提取样式)

以下示例显示了一个响应,其中包含一条记录(一个文档、一个实体、一个文件)作为一个源引用。

{
  "id": "tr-001",
  "title": "Forecasting AI adoption in the enterprise (2026)",
  "text": "Trey Research surveyed 412 enterprise CIOs across North America and EMEA between January and February 2026. We forecast that 64% of Fortune 500 firms will be running at least one production generative AI workload by end of 2026, up from 38% at the close of 2025...",
  "url": "https://www.treyresearch.net/notes/ai-adoption-2026",
  "publishedDate": "2026-03-12",
  "thumbnailUrl": "https://www.treyresearch.net/assets/trey-research-logo.png",
  "metadata": { "source": "trey-research", "category": "AI" }
}

以下示例显示了插件清单中的最小响应语义配置。

"capabilities": {
  "response_semantics": {
    "data_path": "$",
    "properties": {
      "title": "$.title",
      "subtitle": "$.publishedDate",
      "url": "$.url"
    }
  }
}

data_path设置为 $ 的属性选择根对象作为单个引文项。 每当工具返回一条记录时,这是正确的选择 - 即使记录包含嵌套字段(如 metadata)。

MCP 内容包装器

MCP 工具将其响应包装在一 content 系列 TextContentBlock 项中。 Copilot 将text每个块的字段分析为 JSON,然后针对分析的值应用 。data_path 字符串内 text 的形状是驱动配置(而不是外部 content 包装器)的驱动。

MCP 响应示例

{
  "content": [
    {
      "type": "text",
      "text": "{\"id\":\"tr-001\",\"title\":\"Forecasting AI adoption in the enterprise (2026)\",\"url\":\"https://www.treyresearch.net/notes/ai-adoption-2026\"}"
    }
  ]
}

分析程序首先解包 text 有效负载,留下一个对象。 使用 单个对象 配置 ("data_path": "$") 。 返回字段中数组的 text MCP 搜索工具使用 结果配置数组 (data_path: "$.results") 。

动态响应语义 (零配置回退)

仅当工具稳定且不变时,显式 response_semantics 才有效。 通常情况并非如此:基于第三方 MCP 服务器构建的连接器会频繁更新其工具,因此,随着服务器的发展,你必须使清单保持同步。 当服务器更改但清单未更改时,结构化地面会无提示地回退到原始文本和引文停止呈现。

当清单省略显式 properties 映射时,Copilot 会根据已知别名的优先级列表扫描每个结果对象来推断引文字段。 这种零配置回退对于 动态工具发现特别有用,因为动态工具发现无法将清单固定到固定工具图面。

字段别名

对于每个引文字段,Copilot 按优先级顺序检查以下别名,并使用找到的第一个匹配项。

引文字段 优先级顺序) (别名
URL display_url, displayUrl, web_url, webUrl, url, citation_url, citationUrl, reference_url, referenceUrl, website_url, websiteUrl, web_link, webLink, link, href
标题 display_title, displayTitle, title, name, display_name, displayName, web_title, webTitle, subject, heading, caption
副标题 subtitle, description, summary, snippet, source, provider, site_name, siteName, highlight
缩略图 thumbnail_url, thumbnailUrl, thumbnail, image_url, imageUrl, logo_url, logoUrl, icon_url, iconUrl
结果数组 results, items, data, value, records, entries

解决规则

  • URL 是硬性要求。 如果未找到非空 URL,则 Copilot 将跳过 元素并发出任何引文。
  • 如果没有游戏别名,游戏将回退到主机名
  • 副标题和缩略图是机会性的。 Copilot 在识别匹配字段时包括它们,否则将忽略它们。

示例

如果 MCP 工具返回以下响应,则无需显式定义 response_semantics 。 Copilot 从已知别名推断引文字段。

{
  "isError": false,
  "content": [
    {
      "type": "text",
      "text": "<stringified results>"
    }
  ]
}

字段 text 包含字符串化的结果:

{
  "results": [
    {
      "url": "https://example.com/result1",
      "title": "Result 1",
      "subtitle": "Subtitle for Result 1"
    },
    {
      "url": "https://example.com/result2",
      "title": "Result 2",
      "subtitle": "Subtitle for Result 2"
    }
  ]
}

由于 resultsurltitlesubtitle 都匹配已知的别名,因此 Copilot 会为每个项目呈现可单击的引文。 任何等效别名在其位置工作 - 例如, itemsdata 而不是 results、 或 webUrlhref 而不是 url

引文属性

以下属性可用于引文。 所有值都是针对 所选的一项的 data_path相对 JSONPath 表达式。

属性 必需 功能
title 是 (实际上) 引文的可单击标题。
subtitle 第二行 - 日期、作者、类别。
url 是 (实际上) 单击时引文导航的位置。 必须是返回源的规范链接。
thumbnail_url 与引文一起显示的小图像。

注意

如果 url 缺少 ,则引文不可单击。 缺少此属性是开发人员看到非功能性引文的常见原因。

设置 data_path

属性 data_path 是 JSONPath (RFC 9535) 表达式。 使用不正确的 JSONPath 表达式是引文未显示的最常见原因之一。

如果你的响应如下所示... 使用此 data_path
{ "results": [ ... ] } $.results
{ "content": [ { "results": [ ... ] } ] } (MCP 样式的嵌套) $.content[0].results
根目录中的单个对象 (没有数组包装器) $
{ "content": [ { "type": "text", "text": "<stringified JSON>" } ] } (原始 MCP) $如果内部 JSON 具有数组,则为 根,或$.results

提示

平展数组。 例如,多级嵌套数组 (, $.content[0].results[0].items) 是最有可能以无提示方式失败的架构模式。 如果拥有工具响应形状,则返回一个平面 results: [...] 数组。

超越响应语义

作为第一个首选项, 请考虑向 代理添加丰富的 UI 小组件。 此方法面向未来且 AI 原生,可实现更智能、更自适应和无缝的交互。

仅当需要以下条件之一时,才在需要以下条件之一时,添加自适应卡作为最后手段

  • 引文的自定义视觉布局单独 (多列、图像横幅、格式化文本块) 或引文卡正文中呈现的多个字段, (标题、副标题和 URL) 。
  • 默认“单击引文”行为之外的操作按钮 (例如 ,Action.Execute多按钮工具栏) 。

对于绝大多数引文方案(“显示源,让我单击”)完全跳过自适应卡片。 它们增加了复杂性,更难调试,并且默认引文 UI 干净且与 Copilot 的其余部分保持一致。

使用自适应卡片的示例

"response_semantics": {
  "data_path": "$.content[1].results",
  "properties": {
    "title": "$.title",
    "subtitle": "$.publishedDate",
    "url": "$.url"
  },
  "staticTemplate": {
    "type": "AdaptiveCard",
    "version": "1.4",
    "body": [
      {
        "type": "TextBlock",
        "text": "${title}",
        "weight": "bolder",
        "size": "medium"
      },
      {
        "type": "TextBlock",
        "text": "${subtitle}",
        "isSubtle": true
      },
      {
        "type": "TextBlock",
        "text": "${text}",
        "wrap": true
      }
    ],
    "selectAction": {
      "type": "OpenUrl",
      "url": "${url}"
    }
  }
}

${title}请注意 、 ${subtitle}${url} 标记 - 这些标记由前面显示的相同properties映射填充。 自适应卡片是响应语义之上的 表示层 ;它不会替换它。

故障排除清单

如果未显示引文,请使用以下清单。

  • 是否 data_path 指向正确的节点? 将工具的原始 JSON 响应粘贴到 JSONPath 测试器中,并确认表达式返回预期的数组或对象。
  • 每个项是否都有一个非空 url? 缺少 URL 会导致不可单击的引文。
  • 对于 MCP 工具,字段 text 是否在有效的 JSON 内 TextContentBlock ? 手动分析它以确认。
  • 架构是否平整? 如果有深层嵌套的数组,请尝试返回单个平面数组。
  • 你是否声明 response_semantics 了每个函数 (插件清单中的) 而不是插件根目录中的函数 capabilities ? 必须将它限定为 函数。