使用 Amazon Bedrock AgentCore runtime,在编码智能体构建 Web 应用时实时预览

AWS ML Blog 2026-10-31T03:58:25.419811

编码智能体已经能构建可运行的 Web 应用:一个仪表盘、一个产品页、一个产品团队想试试的原型。审查这类产出最快的办法,就是打开应用、用一用、提个修改需求、再确认效果。只要应用一直跑在智能体编辑它的地方,这个循环就很顺,每次改动几秒内就能出现在浏览器里。反过来,如果应用必须先拷出来、部署到别处,那每次改动都要等一次部署,审查节奏也就被拖到部署的速度了。

Amazon Bedrock AgentCore 是一个用来大规模构建、连接和优化智能体的平台,你可以自由选择智能体框架和大语言模型(FM,foundation model)。AgentCore runtime 是 Amazon Bedrock AgentCore 的一项能力,它把每个智能体会话跑在各自隔离的微型虚拟机(microVM)里。借助 Session endpoints,你可以直接从自己的浏览器打开该会话中运行的应用。Session Endpoints 会为每个会话提供一个经过身份认证的 URL,把每个请求的 HTTP 方法、路径、查询字符串、请求体,以及 WebSocket 连接,转发到你允许的端口。这样,智能体每保存一个文件,你就能看到页面随之更新。

本文会带你部署一个编码智能体,让它在自己的会话里持续运行一个 Vite 网站,然后打开一个本地页面,左边是聊天窗口,右边是实时网站。你让智能体把站点切换成深色主题,跟着它一步步流式输出的步骤操作,就能看到网站在不刷新的情况下发生变化。最后,你会看到内部发生了什么:同一个会话里的第二个端口,以及 Session endpoint 会拒绝哪些请求。完整示例(包括本文跟着操作的 notebook)位于 agentcore-samples GitHub 仓库的 14-remote-access 文件夹中。

Session endpoints 的工作原理

每个会话都有自己的 Session endpoint,有六个细节会影响你如何使用它。

InvokeAgentRuntime 的响应会把它放在 X-Amzn-Bedrock-AgentCore-Runtime-Session-Endpoint-Url 响应头里,支持这一特性的 SDK 会将它暴露为 sessionEndpointUrl。每个请求都需要通过身份验证。如果运行时使用 AWS Identity and Access Management(IAM,身份与访问管理),那么每个 HTTP 请求、HTTP/2 流和 WebSocket 握手都要携带 Signature Version 4(SigV4)签名。调用方还需要在运行时及其运行时端点上具备 bedrock-agentcore:InvokeAgentRuntimeProxy 权限。如果运行时使用入站 JSON Web Token(JWT)授权器,则每个请求改为携带 bearer token。知道 URL 并不等于有访问权限。

主机名决定端口。无论目标端口是什么,客户端都连 443 端口;主机名上的前缀则指定会话内部的端口:https://8090--<session-endpoint-id>.runtime.bedrock-agentcore.<region>.on.aws/index.html

https://8081--<session-endpoint-id>.runtime.bedrock-agentcore.<region>.on.aws/status

这个地址已经带上了你的服务器所使用的协议。HTTP/1.1 和 HTTP/2 请求(包括服务端发送事件推送和 gRPC)以及 WebSocket 连接都能通过。本次演示用的是 HTTP/1.1 和 WebSocket,范围限定在单个会话内。这个 URL 每次请求都要带上凭证,只在会话存活期间有效,因此适合用它来构建、测试和审阅 agent 生成的内容。要把应用正式提供给用户,还得部署到 AWS Amplify Hosting 这类托管服务上。

浏览器无法在页面自发发起的请求里附加 SigV4 签名或持有者令牌(bearer token)。为此,bedrock-agentcore SDK 里的 Session endpoint 客户端可以在你的本机开一个本地端点。你让浏览器打开 http://localhost:8088,本地端点会在每次请求和 WebSocket 握手时补上你的凭证,再转发出去。

Session endpoint 与 AgentCore runtime 已提供的 runtime endpoint 不是一回事。runtime endpoint(比如 DEFAULT)用来访问你的 agent,它决定调用方最终打到哪个版本。InvokeAgentRuntime 调用经由它解析,因此你可以让开发和线上分别跑不同版本,做版本晋级或回滚时无需改动调用方。Session endpoint 则用来查看 agent 在会话里跑出了什么,比如网页预览。它是一个需要认证的 URL,只开放你允许的端口,对会话运行中的任意版本都有效,会话一结束就失效。

完整文档参见:Connect to runtime sessions through a session endpoint。

解决方案概述

这个示例分四部分。一个编程 agent 在会话里监听 8080 端口,通过 list、read、write、edit 四个工具编辑网站文件。该 agent 启动一个 Vite 开发服务器,监听 8090 端口,负责提供网站内容,并通过热重载 WebSocket 把每次保存的改动推送到浏览器。在你的本机上,PreviewApp 负责渲染预览页面、把你的提示词发给 InvokeAgentRuntime,并为网站打开一个本地端点。

如图 1 所示,预览页面通过本地端点和 Session 端点,从 8090 端口的 Vite 开发服务器加载网站,并通过 InvokeAgentRuntime 把你的提示词发送到 8080 端口的 agent。图中的数字表示单次请求的步骤顺序。

图 1:解决方案架构

在执行第 1 步之前,PreviewApp 已经调用过一次 InvokeAgentRuntime 来启动会话,这会同时启动 agent 和 Vite 开发服务器。PreviewApp 从那次响应中读取 Session 端点 URL,并为 8090 端口打开一个本地端点。图 1 中带编号的步骤,对应一次修改请求的完整流程:

  1. 预览页面的站点面板通过 localhost:8088 上的本地端点加载网站。本地端点会给每个请求和 WebSocket 握手加上你的凭证,然后转发到 Session 端点。Session 端点校验签名,并检查端口是否在 allowedPorts 中,通过后再转发给 8090 端口的 Vite 开发服务器。页面会一直保持 Vite 热重载的 WebSocket 连接不关闭。

  2. 你在聊天面板发送一条提示词。PreviewApp 把它作为标准 AWS API 调用发送给 InvokeAgentRuntime,并用你的 AWS 凭证签名,runtime 再把它交给 8080 端口的 agent。

  3. agent 的工作步骤会实时流式返回聊天面板。agent 调用 Amazon Bedrock 中的 Claude Haiku 5.5 来决定要改什么。它读取站点文件,并保存修改过的文件。

  4. Vite 开发服务器负责提供这些文件,并监听文件变化。文件保存后,Vite 通过第 1 步建立的 WebSocket 推送变更,经 Session 端点和本地端点传回,站点面板无需刷新即可更新。

PreviewApp 也会从 notebook 出发,通过同一个 Session 端点读取 agent 在 8081 端口上的 /status 路由。这里只有端口不同。8080 端口不在 allowedPorts 中,因为 InvokeAgentRuntime 访问 agent 时并不经过 Session 端点。

前提条件

要跟着本教程操作,你需要:

需要具备以下权限:创建 AWS Identity and Access Management(IAM)角色、上传到 Amazon Simple Storage Service(Amazon S3)、创建 runtime,以及在该 runtime 及其 DEFAULT runtime 端点上使用 bedrock-agentcore:InvokeAgentRuntime 和 bedrock-agentcore:InvokeAgentRuntimeProxy。详情请参阅 AgentCore runtime 的 IAM 权限。

这个示例采用 Node.js 的直接代码部署方式,把 agent 打成 zip 文件上传到 Amazon S3,因此不需要 Docker,也不需要 Amazon Elastic Container Registry(Amazon ECR)仓库。

Session 端点只能配合 microVM runtime 使用,不支持 Instances 计算类型。Session 端点 URL 可通过公网 HTTPS 访问,入站连接不支持 AWS PrivateLink。

部署 agent 及其网站

首先部署 runtime。你在这里选择的配置,决定了 Session 端点能访问哪些端口。部署脚本会把 agent 打包成单个文件,加入网站及其依赖(针对 runtime 的 Linux on Arm64 系统),把 zip 上传到 Amazon S3,然后创建 runtime。

下面这段 deploy.py 节选展示了与本文相关的两个设置。protocolConfiguration 指定 agent 在哪里监听 InvokeAgentRuntime,allowedPorts 列出 Session 端点可以访问的端口:网站用 8090,agent 的状态路由用 8081。8080 端口不在列表里,因为 InvokeAgentRuntime 访问 agent 不需要它。端口和路径的设置详情请参阅配置 agent 的服务端口和调用路径。

agentRuntimeArtifact={"codeConfiguration": {
"code": {"s3": {"bucket": code_bucket(), "prefix": S3_PREFIX}},

"runtime": "NODE_22",

"entryPoint": ["app.js"],

}},
protocolConfiguration={"serverProtocol": "HTTP", "port": 8080, "path": "/invocations"},

allowedPorts=[{"port": 8090}, {"port": 8081}],

网站的 Vite 配置让开发服务器可以从 Session 端点访问。它监听 0.0.0.0 的 8090 端口,并且不限制 Host 头(server.allowedHosts 设为 true),因为请求到达时用的 host 名是 runtime 分配的,而不是 localhost。Session 端点会在每个请求到达服务器之前先做身份验证,所以服务器本身不必再做 host 检查。

部署 runtime 的步骤:

  1. 克隆示例仓库并进入对应的文件夹:
git clone https://github.com/awslabs/agentcore-samples.git

cd agentcore-samples/01-features/02-host-your-agent/01-runtime/03-advanced/16-session-endpoints
  1. 打开示例文件夹里的 session_endpoints_preview.ipynb。

  2. 运行安装单元格,它会安装 Python 依赖。

  3. 运行 %run deploy.py 单元格。

部署需要几分钟,主要时间花在等待 runtime 进入 READY 状态。

打开预览

runtime 就绪后,就可以启动预览了。一次调用完成三件事:启动一个 session(也就是启动网站)、为 8090 端口打开本地端点、在 localhost:8087 上提供预览页面。

from preview_app import PreviewApp

app = PreviewApp().start()

print("Open", app.url)

在 start() 内部,用到 Session 端点的调用都很简短。第一次 InvokeAgentRuntime 调用会在响应头里返回 URL,session_endpoint_url 读取它,然后 Session 端点客户端为 8090 端口打开本地端点:

answer = client.invoke_agent_runtime(
    agentRuntimeArn=runtime_arn, runtimeSessionId=session_id,
    payload=json.dumps({"prompt": ""}).encode(), contentType="application/json",
)

endpoint = client.session_endpoint_client(session_endpoint_url(answer))
local = endpoint.open_local_endpoint(port=8090, local_port=8088).start()

打开预览的步骤:运行启动 PreviewApp 的那个单元格(cell),然后在浏览器中打开打印出来的链接 http://localhost:8087。页面上,右侧显示网站本身(由会话中的 8090 端口提供),左侧是一份简短指南,附有可尝试的请求建议。

让 agent 做一次修改

现在你来提一个修改,然后看着它生效。每个提示都通过 InvokeAgentRuntime 发给 agent。agent 会读取需要的文件,写入改动过的文件,并在每一步发生时实时汇报。文件一保存,Vite 开发服务器就通过自己的 WebSocket 把改动推出去,经由 Session endpoint 和本地 endpoint 送达,网站随即原地更新。

提出修改的步骤:

下面的视频展示了 agent 处理多个请求时的预览页面。选择一个推荐请求就会把它发给 agent,聊天面板列出 agent 读取和保存的每个文件,右侧的站点面板无需刷新就自动更新——从深色主题换成绿色的 Order ahead 按钮。

图 2:agent 工作时的预览页面

这些步骤是流式返回的,因为只要你要求,agent 就会用服务器发送事件(server-sent events,SSE)来回应。你也可以用 Python 的 app.ask 发送同样的提示,它通过 bedrock-agentcore SDK 的 iter_events 读取这个流。已打开的页面会以同样的方式更新:

for event in app.ask("Make the Order ahead button green"):

if "step" in event:

print("  ", event["step"])

elif "done" in event:

print(event["done"]["reply"])

这个 Python 脚本的输出大致如下:

Looking at the site's files

Reading src/main.js

Reading src/style.css

Reading index.html

Saved src/style.css

“Order ahead”按钮现在是绿色,不再是之前的棕色,文字仍保持白色以确保对比度。你可以在首屏区域看到它,就在页面顶部“Small batch coffee, roasted every morning”标题的正下方。

在同一会话中访问第二个端口

这个网站并不是你能访问的唯一服务。agent 还在 8081 端口上提供 /status,用于列出每条 prompt 以及它改动的文件。同样通过 Session 端点访问,唯一区别是 port 参数。

status = app.endpoint.request("GET", "/status", port=8081)

print("GET /status on port 8081: HTTP", status.status)

for edit in status.json()["edits"]:
    print("  ", edit["prompt"], "->", ", ".join(edit["files"]))

这段 Python 脚本的输出大致如下:

GET /status on port 8081: HTTP 200

把“Order ahead”按钮改成绿色 -> src/style.css

会话端点会拒绝哪些请求

runtime 拒绝请求时,会返回一个 HTTP 状态码、空的响应体,并在响应头里给出错误码。这样一来,你就能把它主动拒绝的请求和应用自己返回的错误区分开。

Notebook 里会发两个请求做演示:一个发往 allowedPorts 之外的端口,另一个不带凭证。runtime 对两者都返回 403 AccessDenied。

下表列出你在使用会话端点开发时可能遇到的拒绝情况。

请求 runtime 的响应
端口不在 allowedPorts 里 403 AccessDenied
请求没有有效凭证 403 AccessDenied 或 401 AuthenticationRequired
端口允许,但上面没有服务在监听 502 PortNotReachable
URL 对应的会话已不存在 404 SessionNotFound

会话访问是如何保护的

runtime 在转发请求之前,会先摘掉自己的认证头,所以网站收不到你的签名。所有请求都会以 InvokeAgentRuntimeProxy 事件记入 AWS CloudTrail,事件来源是 bedrock-agentcore.amazonaws.com。

本地端点是以你的凭证运行的,因此它限制了谁能使用它:只监听 127.0.0.1,只响应发往它自己本地地址的请求,并拒绝来自其他源(origin)的页面发起的 WebSocket 连接。

请只在需要预览时运行本地端点。更多信息参见“在 CloudTrail 中记录会话端点请求”。

这些访问控制并不会把网站和智能体隔开。两者运行在同一个会话里,所以执行角色只应授予智能体必需的权限。

如果 runtime 替换了会话所用的计算资源,已打开的连接会被断开,智能体的改动也可能丢失,除非会话使用了持久化存储。如果需要文件在计算资源被替换后仍然保留,请参考 AgentCore runtime 的文件系统配置。

智能体的文件工具会把所有路径解析到站点文件夹内部,并拒绝指向文件夹之外的路径,因此一段提示词无法让智能体去改动会话里的其他文件。

如果其他人也能向你的编码代理发送提示词,可以考虑用 Amazon Bedrock Guardrails 过滤有害的提示词和回复,并在发布前先审核代理的改动。

清理

为避免持续产生费用,请停止预览并删除示例创建的资源。代理编辑过的网站存放在会话里,所以会随会话一起消失。清理步骤如下:

  1. 运行 stop 单元格,笔记本询问时按 Enter。这会停止预览页面、本地端点和会话。
  2. 运行 %run cleanup.py 单元格,它会删除运行时、上传的代码和 IAM 角色。

结论

通过 Session endpoint,你可以从自己的工具访问 AgentCore 运行时会话中的应用,走 HTTP/1.1、HTTP/2 和 WebSocket,端口由你放行,访问经过身份验证。

本文中,你部署了一个编码代理,它的会话里有一个 Vite 网站。你通过本地端点在浏览器中打开了这个在线网站,让代理改成深色主题,并在代理保存文件时看到改动实时生效。你还在同一个会话中访问了第二个端口,并确认了 Session endpoint 会拒绝哪些请求。

想进一步探索,可以把你自己的网站放进 site 文件夹再运行笔记本,或者修改代理的工具,让它匹配你的编码代理的工作方式。完整选项(包括端口范围、OAuth、HTTP/2 和 gRPC)请参阅 Connect to runtime sessions through a session endpoint。

要在你自己的代理中修改 InvokeAgentRuntime 使用的端口或路径,请参阅 Configure your agent's serving port and invocation path。

如果你的代理还需要在同一会话中运行构建或测试命令,请参阅 Execute shell commands in AgentCore runtime sessions。

想和本示例一样,从 zip 文件部署你自己的 Node.js 代理,请参阅 Direct code deployment for Node.js。

该服务的其他功能,可以先看 Host agent or tools with Amazon Bedrock AgentCore runtime,更多示例见 agentcore-samples GitHub 仓库。

关于作者

Sundar Raghavan 是 AWS 的资深解决方案架构师,隶属 Agentic AI Foundations 团队。

他负责 Bedrock AgentCore 的开发者体验,主管 SDK 和 CLI,并推动框架与生态集成的策略。他关注的是开发者如何在 AWS 上构建、部署和扩展生产级 AI Agent(智能体),同时通过 Strands Robots 把这套 Agent 开发体验延伸到物理 AI(Physical AI)领域。

Amazon Bedrock AgentCore 的 Session 端点会为每个运行时会话提供一个带认证的 URL,把任意 HTTP 方法、路径和 WebSocket 连接转发到你允许的端口。本文中,你会部署一个编码代理,让 Vite 网站持续运行在它的会话里,然后在代理编辑文件时,直接在浏览器中查看网站的实时更新。

查看原文