亚马逊AWS官方博客

Amazon Quick Chat Agent 网页嵌入集成实践指南

摘要:如何让 Amazon Quick 的 Chat Agent 不止停留在控制台,而是嵌入自有业务页面、与页面操作联动?本文系统介绍一键式嵌入与 SDK 嵌入两种方式的原理、安全模型、实现步骤与选型,并附实践避坑指南。


一、前言

Amazon Quick 是亚马逊云科技推出的基于 Agentic AI 的工作助手,可用于自动化任务、分析数据、构建 Web 应用与深度研究。用户以自然语言与 Quick 的 Chat Agent 对话,Agent 则借助底层模型,基于连接的数据源、MCP 与应用程序处理请求并作答——同一个 Agent 既能查数分析,也能解读业务对象、检索知识、辅助决策乃至代为执行流程。

但 Chat Agent 默认运行在 Amazon Quick 的界面中,用户每次使用都要离开业务系统、切到独立入口、再把上下文重新交代一遍。官方提供的 Extensions 虽能把 Agent 嵌入浏览器、Slack、Teams、Microsoft 365 等应用,缓解了切换,但它解决的是「在通用应用中随手唤起 Quick」。对企业自有业务系统而言,仍是各自安装、与页面相对独立的入口,无法成为产品内的原生功能,也谈不上与页面控件联动。

更理想的做法是把 Agent 嵌入式集成进自有业务页面。Agent 直接出现在用户日常使用的业务系统页面里,无需跳转独立入口,从根本上消除了来回切换的割裂感。在此基础上还能更进一步——让 Agent 与页面控件联动:用户选好对象或条件一键推送,Agent 结合上下文直接给出解释、分析、建议或动作,真正成为业务系统的原生能力。本文将系统性地介绍如何把 Quick Chat Agent 嵌入自有 Web 应用,涵盖工作原理、安全模型、实现步骤与能力边界,并附实践中的典型问题,帮你结合自身场景落地。

二、方案总览

把 Chat Agent 嵌进网页,官方提供两种方式,二者的实现成本与能力差异显著:

一键式嵌入——零后端方案。把控制台复制的 share URL 放进一个 <iframe> 即可,无需后端与 API 调用,让 Chat Agent 的对话框直接出现在业务系统界面的指定位置,属于静态iframe嵌入方式。其能力边界也很清晰:Agent 以「原样」嵌入,用户可在框内正常对话,但外层页面与 Agent 之间是隔离的,适合面向已登录用户、以”放一个对话入口”为目标的需要。

SDK 嵌入——可编程方案。引入官方 JS SDK 加载 Agent 对话框,嵌入链接由后端接口动态签发。与一键式嵌入不同,SDK 会接管 iframe 并在两端建立 postMessage 通道、向前端返回一个可编程句柄,从而打通外层页面与 Agent 的双向通信:页面可把控件的当前状态序列化后主动推送给 Agent,也能定制其界面、监听加载等事件。这种方式是需要少量前后端开发,换来的是页面与 Agent 联动、以及面向未登录用户的受控访问等一键式嵌入无法实现的能力。

下面是两种方式的实际效果展示——

[图1 一键式嵌入:页面里包含Agent 对话框,用户手动输入问题Agent 回答]

[图2 SDK嵌入:页面里包含Agent 对话框,左侧选好筛选条件 → 点击按钮 → 右侧 Agent 自动收到 prompt 并给出分析]

我们再用两张图分别说明两种方式背后的整体架构。

一键式嵌入:你手写一个裸 <iframe> 加载 Agent 的 share URL,零后端,鉴权完全依赖访问者自己的登录态:

[图3:一键式嵌入整体架构。iframe 由你手写,加载 share URL;无后端参与,外层页面与 iframe 之间没有可编程通道]

SDK 嵌入:iframe 改由 SDK 创建并接管,加载后端签发的动态 embed URL,前端经 SDK 获得可编程句柄,从而实现页面控件与 Agent 的联动:

[图4:SDK 嵌入整体架构。iframe 由 SDK 创建并接管,加载动态生成的 embed URL;实线 a→d 为主链路,虚线为前端经 postMessage 与 iframe 的页面联动]

下表汇总两种方式的差异,先给出速览对比与选型结论:

一键式嵌入 SDK 嵌入
一句话概括 手写裸 <iframe> 加载 share URL SDK 创建并接管 iframe,加载后端签发的 embed URL
iframe 由谁创建 你手写 SDK 创建并接管
是否需要后端 不需要 需要一个签发接口
鉴权模型 访问者自己的 Quick Suite 登录态 服务端 IAM 为注册用户签发
页面与 Agent 联动 不支持 支持(sendPrompt(),经 postMessage)
上线速度 几分钟 需少量前后端代码

选型建议:

  • 只是「把 Agent 原样放进内部页面,给已登录 Quick的用户使用」→ 一键式嵌入,最快上线。
  • 需要「页面对象 / 条件联动 Agent」「定制 Agent UI」「为没有 Quick Suite 登录态的用户提供受控访问」→ 必须使用 SDK嵌入。

三、配置指南

接下来我们详细介绍两种方式的完整配置,并附对比与排错。

3.1 前提条件

本文聚焦「Agent 已就绪后,如何嵌入网页」。开始前请确认以下条件已具备:

  1. 一个已创建并发布的自定义 Chat Agent:状态为 PUBLISHED + ACTIVE。Agent 本身的创建及 Action Connector 的配置不在本文范围内;
  2. 已开通 Embedding 能力的 Amazon Quick 账号(Enterprise 级);
  3. 一个 HTTPS 发布域名:Amazon Quick 嵌入强制要求 HTTPS,且 SDK 方式签发时需要把域名加入白名单。域名白名单的加入需要在Quick的管理界面中添加Manage Domain,如下所示:

[图5 图示说明:在Quick控制台->管理域下添加相应域名]

3.2 方式一:一键式嵌入

3.2.1 工作原理

Chat Agent 在控制台执行「共享 / Share」后,会得到一个 share embed URL,形如:

https://<region>.quicksight.aws.amazon.com/sn/account/<account-name>/embed/share/accounts/<account-id>/chatagents/<agent-id>

这个 URL 本身就是一个可嵌入的完整页面。将它放进 <iframe src="…"> 后,浏览器加载时由 Quick使用访问者自己的登录态(Cookie / SSO 会话)完成鉴权并渲染 Agent:

[图6 图示说明:iframe 方式的鉴权流程——完全依赖访问者自身登录态]

关键特征:

  • 零后端:不需要签发接口、不需要 AWS SDK、不需要任何 IAM 调用;
  • 依赖访问者自身登录态:访问者必须是已登录且对该 Agent 有权限的 Quick Suite 用户;

3.2.2 实现步骤

1. 获取 share URL: 登录 Quick Suite 控制台(注意切换到 Agent 所在 region)→ 打开目标 Chat Agent → Share → 复制 embed/share 链接。

[图7]

2. 在页面中放置 iframe,关键是 src 与 allow 两个属性:

<div class="embed-slot">
  <iframe
    allow="clipboard-read https://<region>.quicksight.aws.amazon.com;
           clipboard-write https://<region>.quicksight.aws.amazon.com"
    src="<你复制的 share URL>">
  </iframe>
</div>
.embed-slot{width:100%;height:760px;border-radius:12px;overflow:hidden;}
.embed-slot iframe{width:100%;height:100%;border:0;display:block;}

两个实践细节:

  • allow 属性需声明剪贴板权限(Agent 回答中常带「复制」按钮),origin 指向 QuickSight 的嵌入域名;
  • 根据实际需要调整对话框的具体尺寸。

3. 通过 HTTPS 发布并访问。 已登录且有权限的用户打开页面,即可直接看到 Agent 的欢迎语、输入框与 starter prompts。

ℹ️ 注意:

使用**没有 Quick Suite 登录态**的浏览器(无痕窗口、外部访客)访问时,iframe 中渲染的不是 Agent,而是 Amazon Quick 的 **Sign in 登录页**。访客必须先在 iframe 内完成登录、且对该 Agent 有权限,才能看到对话界面。这是 iframe 方式「依赖访问者自身登录态」最直接的体现,也是它**不适合匿名或外部用户场景**的根本原因。

3.2.3 能力与局限

能力 是否支持
显示并使用 Chat Agent(用户手动提问)
复用访问者自身登录态鉴权
从外层页面用 JS 主动给 Agent 发送消息
页面控件(下拉/筛选/对象选择)联动 Agent ❌(拿不到 Agent 的 JS 句柄)
控制 Agent UI(隐藏 footer、初始 prompt 等)
面向未登录外部用户的受控嵌入 ⚠️ 受限

3.3 方式二:SDK 嵌入

3.3.1 工作原理

SDK 方式使用官方 JS 库 **amazon-quicksight-embedding-sdk**(本次实践版本 2.11.3),整体分为「服务端签发」与「前端嵌入」两个阶段,下面的时序图展示了完整流程:

[图8 图示说明:SDK 方式的完整时序——签发、嵌入、握手、运行时联动]

阶段一:服务端签发(图中 ①②)。 后端调用 GenerateEmbedUrlForRegisteredUser API,为指定的注册用户签发 embed URL。这一步把「谁能看」收敛到服务端 IAM 控制,不依赖访问者自己登录 Quick。

阶段二:前端嵌入(图中 ③~⑥)。 前端调用 createEmbeddingContext().embedQuickChat(…),SDK 在指定容器中创建并管理 iframe,**并返回一个可编程的 JS 对象 chatExperience**。这个对象暴露的 sendPrompt() 方法,正是手写裸 iframe 拿不到、而实现「页面联动 Agent」所必需的句柄。
此处与一键式嵌入的差异不在于「用没用 iframe」(两者都用),而在于这个 iframe 由 SDK 创建并在两端预置了 postMessage 收发逻辑,从而把跨域 iframe 变成了可编程对象。

3.3.2 安全模型:一次性令牌 + 域名白名单 + 服务端身份

理解 SDK 方式的安全设计,有助于正确地实现签发接口。它由三层机制构成:

第一层:短时效的一次性令牌。 签发出的 embed URL 中包含一个 bearer token,根据官方 API 文档,该 token 首次兑换的有效期为 5 分钟;兑换成功后建立的会话有效期为 15 分钟到 10 小时(默认 10 小时)。这意味着:

  • embed URL 是「即签即用」的,不能缓存、不能预生成后存起来复用——这也是签发接口要返回 Cache-Control: no-store 的原因;
  • 每次页面加载都应重新请求签发,URL 用过即失效,即使泄露也无法二次使用。

第二层:域名白名单。 签发时通过 AllowedDomains 参数声明允许承载嵌入的域名(必须 HTTPS)。QuickSight 服务端据此限制 iframe 只能在白名单域名下加载,第三方网站即使拿到 embed URL 也无法嵌入。

第三层:服务端身份绑定。 签发时的 UserArn 决定了嵌入会话以哪个注册用户的身份运行,Agent 的可见性、数据权限都跟随这个身份。由于签发动作由你的后端发起(受 IAM 权限 quicksight:GenerateEmbedUrlForRegisteredUser 控制),你可以在自己的业务鉴权之后再决定为谁签发——例如先校验业务系统的登录态,再映射到对应的 Quick 用户。

3.3.3 SDK 内部机制:iframe 管理与 postMessage 通信

embedQuickChat 返回的 chatExperience 为什么能「隔着 iframe」给 Agent 发消息?理解这一点对调试很有帮助:

  1. createEmbeddingContext() 建立通信基础设施。** 它在父页面注册全局的消息监听,作为后续所有嵌入体验(Dashboard、Quick Chat 等)的通信枢纽,并可通过 onChange 回调感知上下文级别的状态变化。
  2. embedQuickChat(frameOptions, contentOptions) 创建并接管 iframe。** SDK 根据 frameOptions.container 找到容器,把 contentOptions 中的配置(如 agentOptions.fixedAgentId、各类 promptOptions)编码进最终的 iframe URL 参数,再创建 iframe 挂载到容器中。这解释了一个实测确认的反直觉设计:GenerateEmbedUrlForRegisteredUserExperienceConfiguration.QuickChat 在服务端是空结构——后端只需传 {"QuickChat": {}},具体绑定哪个 Agent 是由前端 SDK 注入的。
  3. **父页面与 iframe 之间通过 window.postMessage 双向通信。** 浏览器的同源策略禁止父页面直接操作跨域 iframe 的 DOM,postMessage 是唯一合规的跨 frame 通道:
  4. 下行(父页面 → iframe):chatExp.sendPrompt(text) 本质是通过 postMessage 把消息投递进 iframe,由 Agent 界面代为「输入并发送」;
  5. 上行(iframe → 父页面):嵌入体验的生命周期事件通过 postMessage 回传,frameOptions.onChange 接收 frame 级事件(FRAME_MOUNTEDFRAME_LOADEDFRAME_REMOVEDERROR 级事件),contentOptions.onMessage 接收内容级事件(如 CONTENT_LOADED)。

[图9 图示说明:SDK 的 postMessage 双向通信模型]

基于这套事件模型,你可以做更精细的工程化处理——例如在 CONTENT_LOADED 事件触发后再启用页面上的「发送给智能体」按钮,避免用户在 Agent 就绪前点击。

3.3.4 实现步骤

1. 后端实现签发接口

以 FastAPI + boto3 为例(任何后端框架与语言 SDK 同理):

import boto3
from fastapi.responses import JSONResponse

QS_ACCOUNT  = "<aws-account-id>"
QS_USER_ARN = "arn:aws:quicksight:us-east-1:<aws-account-id>:user/default/<user-name>"
QS_REGION   = "us-west-2"            # ★ 必须 = Agent 所在 region
SITE_DOMAIN = "https://<your-domain>"

@app.get("/embed-url")
def embed_url():
    try:
        qs = boto3.client("quicksight", region_name=QS_REGION)   # ★ Agent 所在 region
        resp = qs.generate_embed_url_for_registered_user(
            AwsAccountId=QS_ACCOUNT,
            UserArn=QS_USER_ARN,
            ExperienceConfiguration={"QuickChat": {}},   # ★ 空结构,Agent 由前端指定
            AllowedDomains=[SITE_DOMAIN],                # ★ 域名白名单,必须 HTTPS
        )
        return JSONResponse({"embedUrl": resp["EmbedUrl"]},
                            headers={"Cache-Control": "no-store"})
    except Exception as e:
        return JSONResponse({"error": str(e)}, status_code=500,
                            headers={"Cache-Control": "no-store"})

IAM 要求:需要具备 quicksight:GenerateEmbedUrlForRegisteredUser 权限,视情况补充 quicksight:RegisterUser 等相关权限。

验证签发是否成功——返回的 URL 应形如 https://<region>.quicksight.aws.amazon.com/embedding/…/quick/chat?…
curl -s https://<your-domain>/embed-url

注意 embed URL 与 iframe 方式的 share URL 形态完全不同(`/embedding/…/quick/chat` 与 `/embed/share/…/chatagents/…`),这也是「两条路线不可混用」的直观证据。

2. 前端引入 SDK 并嵌入

<script src="https://cdn.jsdelivr.net/npm/amazon-quicksight-embedding-sdk@2.11.3/dist/quicksight-embedding-js-sdk.min.js"></script>

<div id="embed-slot"><div class="loading">正在签发嵌入会话并加载智能体…</div></div>

<script>
var AGENT_ID = "<agent-id>";   // ★ Agent 在前端指定
var chatExp = null;

async function initEmbed(){
  // ① 取后端签发的 embed URL
  var data = await (await fetch('/embed-url', {cache:'no-store'})).json();
  if(!data.embedUrl) throw new Error(data.error || '未拿到 embedUrl');

  // ② 创建嵌入上下文
  var ctx = await QuickSightEmbedding.createEmbeddingContext();

  // ★ 关键细节:SDK 会把 iframe append 进 container,但不会清除已有的
  //   loading 占位元素,不清空会出现「loading 文字盖住 iframe」——嵌入前手动清空
  document.getElementById('embed-slot').innerHTML = '';

  // ③ 嵌入 QuickChat,拿到可编程句柄 chatExp
  chatExp = await ctx.embedQuickChat(
    {
      url: data.embedUrl,
      container: '#embed-slot',
      height: '100%',
      width: '100%'
    },
    {
      agentOptions: { fixedAgentId: AGENT_ID },        // ★ 绑定具体 Agent
      promptOptions: { showInitialPromptMessage: true }
    }
  );
}
initEmbed();
</script>

3. 实现「页面上下文 → 推送给 Agent」

这是 SDK 方式的核心价值所在。做法很直白:把页面上的当前状态(控件选了什么、当前是哪个对象、用户的操作意图)拼成一句自然语言 prompt,再调用 chatExp.sendPrompt(text)。下面以「数据查询分析」举例,但无论拼的是客户信息、工单内容、申请材料还是筛选条件,写法都一样:

askButton.addEventListener('click', async function(){
  if(!chatExp) return;
  var prompt = buildPrompt();                  // 把页面上下文拼成自然语言
  var res = await chatExp.sendPrompt(prompt);  // ★ 推给 Agent,返回 {success:true}
});

以数据分析场景为例,buildPrompt() 拼出的文本类似:

请基于销售订单数据,对满足以下条件的订单按品类统计销售额与订单数,并按销售额从高到低排行:
时间范围 2024-01-01 至 2025-12-31、品类范围"电子产品"大类。

而换成 CRM 客户经营场景,同一段代码拼出的可能是:

请作为客户经营助手,基于以下页面上下文给出分析:
客户:上海某某科技有限公司(C-10086)
时间范围:2026-01-01 至 2026-06-30
关注模块:订单、工单、回款
任务:总结近期风险、关键原因和建议跟进动作。

这里有一个值得强调的设计本质:页面上下文不是通过某种「共享上下文」机制隐式传给 Agent 的,而是由你把它显式序列化为 prompt 文本推送进去。这反而更可控——哪些字段进入 prompt、如何措辞、附加什么指令,全部由前端代码决定。Agent 收到 prompt 后,经它绑定的 Action Connector(如 MCP)访问对应的数据或工具,完成查询、分析或其他处理。

3.3.5 SDK 能力清单

嵌入时可配置项(embedQuickChat 第二参数,来自 SDK 2.11.3 类型定义实测):

配置组 字段 作用
agentOptions fixedAgentId 锁定使用哪个 Chat Agent(核心)
promptOptions initialPrompt 加载时自动发送一次的 prompt
showInitialPromptMessage 是否把初始 prompt 显示给用户
allowFileAttachments 是否显示附件上传按钮
showAgentKnowledgeBoundary 是否显示「知识边界」菜单
showWebSearch 是否显示「联网搜索」按钮
showPromptArea 是否显示输入框与免责声明
showChatHistory 是否显示顶部历史/操作栏
enablePrivateMode 是否开启私密模式
footerOptions showBrandAttribution 是否显示品牌署名
showUsagePolicy 是否显示使用政策链接

运行时方法(embedQuickChat 返回的 chatExperience 对象):

方法 签名 作用
sendPrompt sendPrompt(prompt: string) => Promise<ResponseMessage> 从外层 JS 主动给 Agent 发送一条消息

initialPrompt(加载即发一次)与 sendPrompt(运行时随时发)配合,可以覆盖「打开页面自动产出一份结果」与「用户交互式追问」两类需求。

3.3.6 两种方式对比总结

维度 一键式嵌入 SDK 嵌入
浏览器中的渲染载体 <iframe>(你手写) <iframe>(SDK 创建并接管)
加载的 URL share URL(登录态鉴权、长期有效) embed URL(一次性令牌、即签即用)
后端 不需要 需要签发接口 + IAM 权限
鉴权模型 访问者自身 Quick Suite 登录态 服务端为注册用户签发(一次性令牌)
上线速度 最快(几分钟) 中(少量前后端代码)
页面联动 Agent sendPrompt
初始自动提问 initialPrompt
定制 Agent UI ✅ promptOptions / footerOptions
事件感知(加载完成等) ✅ onChange / onMessage
适合场景 内部门户、已登录用户直接使用 交互联动 / 受控嵌入 / 外部用户

3.4 常见问题速查

现象 根因
“We can’t open this chat agent” 绝大多数情况是签发 region ≠ Agent region(不是权限问题)
CLI list-agents 查不到 Agent region 不对,加 --region 指向 Agent 所在区域
loading 占位文字盖住 Agent 嵌入前没有清空 container
嵌入加载被拒绝 站点不是 HTTPS,或域名不在 AllowedDomains 白名单中
刷新页面后嵌入失败 embed URL 被缓存复用了——它是一次性的,每次加载需重新签发
无痕窗口看到 Sign in 页 iframe 方式的预期行为:依赖访问者登录态

四、总结

这套嵌入方案真正的价值,在于它让你复用 Quick 已经成熟的 Agent 能力,而无需在自己的产品里重复造一个智能体。

自建一个生产级对话式 Agent 并非易事:意图理解、工具编排、数据接入、权限治理、对话界面,每一块都要从头投入。而这些能力 Amazon Quick 已经沉淀在 Chat Agent 里,嵌入要做的,只是把这份现成能力连同界面一起搬进你的业务系统——数据分析、客户经营、客服支持、运营排查、审批合规、知识问答,都适用同一套做法。你无需自建 LLM 调用、对话管理与聊天组件,一段简单的集成代码,就能让 Agent 出现在需要它的页面上,结合知识库与页面上下文进行对话,省去重复开发、来回切换入口、反复交代背景的成本。换句话说,它把「企业级 Agent」从一个独立的产品入口,变成可以低成本嵌入任意业务系统的通用智能能力——让你用最小的工程代价,把 Amazon Quick 的 Agent 能力变成自有产品体验的一部分。

➡️ 下一步行动:

相关产品:

  • Amazon Quick — 人工智能助手,用于研究、业务洞察、自动化和无代码应用程序构建
  • Amazon QuickSight — 高速业务分析服务
  • Amazon IAM — 身份管理和访问权限
  • Amazon Bedrock — 用于构建生成式人工智能应用程序和代理的端到端平台
  • Amazon Connect — AI 客户体验解决方案

相关文章:

五、参考资料

*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。

本篇作者

孙大山

亚马逊云科技解决方案架构师,目前负责 ISV 领域相关客户云端架构设计与技术咨询,拥有 20 年数据领域和公有云行业技术售前与解决方案构建经验。对数据库、数据分析、数据治理、数字化转型有丰富的探索与实践。


AWS 架构师中心:云端创新的引领者

探索 AWS 架构师中心,获取经实战验证的最佳实践与架构指南,助您高效构建安全、可靠的云上应用