在线AI教程 / AI部署

[Amazon Bedrock] 在 coding agent 用 Amazon Bedrock AgentCore Runtime 构建 Web 应用时…

· 转自:aws.amazon.com

在 coding agent 用 Amazon Bedrock AgentCore Runtime 构建 Web 应用时实时预览 coding agent 如今能构建出可运行的 W

转载本文转自「aws.amazon.com」,版权归原作者所有,内容已摘录正文、去除外部链接。

在 coding agent 用 Amazon Bedrock AgentCore Runtime 构建 Web 应用时实时预览

coding agent 如今能构建出可运行的 Web 应用:一个仪表盘、一个产品页、一个产品团队想试一试的原型。审视这些成果最快的方式,就是打开应用、用起来、要求一处改动,再核对结果。这个闭环在「应用继续跑在 agent 编辑它的那个地方」时运转得很好——于是每一处改动都能在几秒内出现在浏览器里。而如果应用必须先被拷贝出去、部署到别处,那么每一处改动都要等一次部署,审视的节奏就被拖慢到那个速度。

Amazon Bedrock AgentCore 是一个用于规模化地构建、连接和优化 agents 的平台,你可以自选 agent 框架和基础模型 (FM)。AgentCore runtime 是 Amazon Bedrock AgentCore 的一项能力,它把每个 agent session 运行在各自隔离的 microVM 中。借助 Session endpoints,你可以从自己的浏览器打开在该 session 中运行的应用。Session Endpoint 会为每个 session 提供一个经过认证的 URL,把每个 request 的 HTTP 方法、路径、query string 和 body,以及 WebSocket 连接,转发到你允许的端口上。你可以看着页面随着 agent 保存每一个文件而更新。

在本文中,你会部署一个 coding agent,让它在自己的 session 里持续运行一个 Vite 网站,然后打开一个本地页面——左边是聊天,右边是实时网站。你会要求 agent 把该网站切换成深色配色主题,跟随它流式返回的每一步操作,并看着网站无需刷新就发生变化。最后,你会看看内部发生了什么:同一个 session 里的第二个端口,以及 Session endpoint 会拒绝的请求。

完整示例——包括本文所跟随的那个 notebook——位于 agentcore-samples GitHub 仓库 的 14-remote-access 文件夹 中。

Session endpoint 如何工作

每个 session 都有它自己的 Session endpoint,有六个细节决定了你如何使用它。

由你决定它能触达哪些端口。 你在调用 CreateAgentRuntime 时设置 allowedPorts:1–5 个条目,每个是 8000–12000 范围内的单个端口或一段端口区间,且排除保留的平台端口。允许某个端口并不会启动一个服务器,所以你的应用必须监听该端口、并绑定到 0.0.0.0。

URL 随 session 一同抵达。 InvokeAgentRuntime 的响应会在 X-Amzn-Bedrock-AgentCore-Runtime-Session-Endpoint-Url 响应头里带上它;对该响应头有建模的 SDK 会把它暴露成 sessionEndpointUrl。

每一次 request 都要经过认证。 对于使用 AWS Identity and Access Management (IAM) 的 runtime,每个 HTTP request、每个 HTTP/2 stream 和每次 WebSocket 握手都带有一个 Signature Version 4 (SigV4) 签名。调用者还需要在该 runtime 及其 runtime endpoint 上具备 bedrock-agentcore:InvokeAgentRuntimeProxy 权限。对于配备了入站 JSON Web Token (JWT) 授权器的 runtime,每个 request 改为携带一个 bearer token。知道这个 URL 本身并不授予访问权限。

由主机名来选定端口。 无论目标端口是什么,你的客户端都在 443 端口上连接;而主机名上的一个前缀负责在 session 内部选定端口:

.runtime.bedrock-agentcore..on.aws/index.html .runtime.bedrock-agentcore..on.aws/status

它承载你的服务器所说的协议。 HTTP/1.1 和 HTTP/2 request(包括 server-sent events 和 gRPC)以及 WebSocket 连接都能透传。本演练使用 HTTP/1.1 和 WebSocket。

它的作用域限定在一个 session 之内。 这个 URL 在每次 request 上都需要凭证,且只在 session 存续期间有效,所以用它来构建、测试和审视你的 agent 产出的东西。要把应用交付给你的用户,请把它部署到诸如 AWS Amplify Hosting 这样的托管服务上。

浏览器无法给一个页面自行发出的 request 加上 SigV4 签名或 bearer token,所以 bedrock-agentcore SDK 里的 Session endpoint 客户端可以在你的机器上开一个本地 endpoint。你的浏览器打开 endpoint 会在转发之前把你的凭证加到每个 request 和 WebSocket 握手之上。

Session endpoint 与 runtime endpoint 不同,后者是 AgentCore runtime 已经提供的。用 runtime endpoint(例如 DEFAULT)来触达你的 agent,它决定了调用者会触达该 agent 的哪个版本。InvokeAgentRuntime 调用经由它来解析,于是你可以让开发和生产处于不同版本,并在不改动调用者的情况下完成提升或回滚。用 Session endpoint 来看你的 agent 在其 session 里运行的东西,比如一个 Web 预览。它是一个经过认证的 URL,只触达你允许的端口、与 session 所运行的任意版本都能配合,并在 session 结束时停止工作。完整文档参见 Connect to runtime sessions through a session endpoint。

方案概览

这个示例由四个部分组成。一个 coding agent 在 session 内的 8080 端口上运行,并用四个工具来编辑网站的文件:list、read、write 和 edit。agent 在 8090 端口上启动一个 Vite 开发服务器,它负责提供网站服务,并通过其热重载 WebSocket 把每一处保存的改动推送到浏览器。在你的机器上,PreviewApp 提供预览页面、把你的 prompts 发给 InvokeAgentRuntime,并为该网站开一个本地 endpoint。如图 1 所示,预览页面经由本地 endpoint 和 Session endpoint,从 8090 端口上的 Vite 开发服务器加载网站;并把你的 prompts 经由 InvokeAgentRuntime 发给 8080 端口上的 agent。图中的数字标出了一个 request 各步骤的顺序。

图 1:方案架构

在第 1 步之前,PreviewApp 已经调用过一次 InvokeAgentRuntime 来启动 session,从而启动了 agent 和 Vite 开发服务器。PreviewApp 从那个响应中读取了 Session endpoint 的 URL,并为 8090 端口开了一个本地 endpoint。图 1 中带编号的步骤随后跟随一次「请求改动」的流程:

预览页的网站窗格从 localhost:8088 上的本地 endpoint 加载网站。本地 endpoint 会把你的凭证加到每个 request 和 WebSocket 握手之上,并把它们转发给 Session endpoint。Session endpoint 会对照 allowedPorts 校验签名与端口,然后把它们转发到 8090 端口上的 Vite 开发服务器。页面会一直保持 Vite 的热重载 WebSocket 开启。 你从聊天窗格发出一个 prompt。PreviewApp 把它作为一个用你的 AWS 凭证签名的标准 AWS API 调用发给 InvokeAgentRuntime,runtime 再把它投递给 8080 端口上的 agent。agent 在工作时,其步骤会流式回传到聊天窗格。 agent 调用 Amazon Bedrock 里的 Claude Haiku 5.5,以决定要改什么。 agent 读取网站的各个文件,并保存它改动的那些。Vite 开发服务器负责提供这些文件的服务,并监视它们的变化。 当一个文件被保存时,Vite 通过第 1 步中建立的那条 WebSocket 把改动推送回来,经由 Session endpoint 和本地 endpoint,网站窗格无需刷新就完成更新。 PreviewApp 从 notebook 里,经由同一个 Session endpoint 读取 agent 在 8081 端口上的 /status 路由。这里只有端口变了。

8080 端口并不在 allowedPorts 之中,因为 InvokeAgentRuntime 触达 agent 并不经过 Session endpoint。

前置条件

要跟随本演练,你需要:

一个 AWS 账号,位于 AgentCore runtime 的 Session endpoints 可用的某个 AWS Region,且已配置好凭证。 创建一个 AWS Identity and Access Management (IAM) 角色、上传到 Amazon Simple Storage Service (Amazon S3)、以及创建一个 runtime 的权限,外加在该 runtime 及其 DEFAULT runtime endpoint 上的 bedrock-agentcore:InvokeAgentRuntime 和 bedrock-agentcore:InvokeAgentRuntimeProxy。详情参见 IAM permissions for AgentCore runtime。 Python 3.10 或更高版本,配合 bedrock-agentcore 1.25.2 或更高版本,以及 boto3 1.43.122 或更高版本。 Git,用于克隆示例仓库;以及一个 Jupyter 环境(如 JupyterLab,或装了 Jupyter 扩展的 Visual Studio Code),用于运行 notebook。 对 Amazon Bedrock 中 Claude Haiku 5.5 的访问权限。按 Region 的 model 可用性,参见 Regional availability by models。 Node.js 22 或更高版本,并配有 npm——部署脚本用它来打包 agent 和网站。

该示例以 direct code deployment for Node.js 的方式,把 agent 作为一个 zip 文件部署到 Amazon S3 中,所以你不需要 Docker,也不需要 Amazon Elastic Container Registry (Amazon ECR) 仓库。Session endpoints 适用于 microVM runtimes,而不适用于 Instances 计算类型;Session endpoint 的 URL 可经由公开 HTTPS 访问,入站连接不支持 AWS PrivateLink。

部署 agent 及其网站

首先,你部署 runtime,而你在此处选择的配置决定了 Session endpoint 能触达哪些端口。部署脚本把 agent 打包成一个文件,附上为 runtime 的 Linux on Arm64 系统准备的网站及其依赖,把 zip 上传到 Amazon S3,并创建该 runtime。

下面这段摘自 deploy.py 的片段,展示了与本文相关的两项设置。protocolConfiguration 说明 agent 在何处监听 InvokeAgentRuntime,而 allowedPorts 列出 Session endpoint 能触达的端口:8090 用于网站,8081 用于 agent 的状态路由。8080 端口不在列表中,因为 InvokeAgentRuntime 触达 agent 并不需要它。关于端口和路径的设置,参见 Configure your agent's serving port and invocation path。

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 endpoint 触达。它在 0.0.0.0 的 8090 端口上监听,且不限制 Host 头(server.allowedHosts 为 true),因为 request 抵达时所用的主机名是 runtime 分配的,而不是 localhost。Session endpoint 会在 request 到达服务器之前对它完成认证,所以服务器不需要自己再做一次主机名校验。

要部署该 runtime:

克隆示例仓库,并切换到示例文件夹:

git clone cd agentcore-samples/01-features/02-host-your-agent/01-runtime/03-advanced/16-session-endpoints

从示例文件夹中打开 session_endpoints_preview.ipynb。

运行 install 单元格,它安装 Python 依赖。

运行 %run deploy.py 单元格。部署需要几分钟,主要是在等 runtime 达到 READY 状态。

打开预览

runtime 就绪后,你启动预览。一次调用做三件事:它启动一个 session(进而启动网站)、为 8090 端口开一个本地 endpoint,并在 localhost:8087 上提供预览页面。

from preview_app import PreviewApp

app = PreviewApp().start() print("Open", app.url)

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

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 的那个单元格。 在浏览器中打开打印出来的链接

页面在右侧显示网站(由 session 内 8090 端口提供服务),在左侧显示一份附带了若干建议请求的简短指南。

向 agent 请求一处改动

现在你请求一处改动,并看着它到来。每个 prompt 都经由 InvokeAgentRuntime 送到 agent。agent 读取它需要的文件、写出它改动的那些,并随着每一步的发生实时汇报。当一个文件被保存时,Vite 开发服务器通过它的 WebSocket 把改动推送出去,经由 Session endpoint 和本地 endpoint,网站就在原地完成更新。

要请求一处改动:

在预览页上,选择 把这个网站切换成深色的咖啡馆配色主题。 在聊天窗格里跟随 agent 读写和保存文件的各个步骤。 盯着网站窗格。当 agent 保存样式表时它就变化,并有一条横幅点明改动来自哪个文件。

下面的视频展示了 agent 依次处理数个请求时预览页的样子。选择一个建议请求就会把它发给 agent,聊天窗格会列出 agent 读取和保存的每个文件,而右侧的网站窗格无需刷新就更新——从深色主题,到一个绿色的「Order ahead」按钮。

图 2:agent 工作时的预览页

步骤之所以是流式的,是因为当你要求时,agent 会用 server-sent events 作答。你可以在 Python 里用 app.ask 发出同样的 prompts,它借助 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 The Order ahead button is now green instead of brown, with white text kept for contrast. You can see it in the hero section, just below the "Small batch coffee, roasted every morning" heading at the top of the page.

触达同一个 session 里的第二个端口

网站并不是你唯一能触达的服务器。agent 在 8081 端口上提供 /status,它列出每个 prompt 及其改动的文件。同一个 Session endpoint 就能触达它,唯一的差别是端口参数。

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 Make the Order ahead button green -> src/style.css

Session endpoint 会拒绝什么

当 runtime 拒绝一个 request 时,它会以一个 HTTP 状态、一个空的 body,以及一个放在响应头里的错误码来作答,于是你可以把它的拒绝与你的应用返回的错误区分开来。notebook 会发出一个指向 allowedPorts 之外端口的 request,以及一个不带凭证的 request,而 runtime 对两者都以 403 AccessDenied 拒绝。

下面的表格列出了你在用 Session endpoints 构建时很可能遇到的各种拒绝。

请求runtime 的响应 一个不在 allowedPorts 中的端口403 AccessDenied 一个没有有效凭证的 request403 AccessDenied 或 401 AuthenticationRequired 一个被允许、但上面没有任何监听的端口502 PortNotReachable 一个所属 session 已不存在的 URL404 SessionNotFound

对你的 session 的访问是如何受保护的

runtime 在转发一个 request 之前,会先移除它自己的认证头,所以网站不会收到你的签名。request 会被记录到 AWS CloudTrail 中,作为 InvokeAgentRuntimeProxy 事件,其事件源为 bedrock-agentcore.amazonaws.com。本地 endpoint 是以你的凭证行事的,所以它限制了谁能使用它:它只在 127.0.0.1 上监听,只回应发给其自身本地地址的 request,并拒绝由其他源的页面发起的 WebSocket 连接。请只在你使用预览期间运行本地 endpoint。更多信息见 Log session endpoint requests in CloudTrail。

这些访问控制并不会把网站与 agent 隔离开。两者运行在同一个 session 中,所以只授予执行角色以 agent 真正需要的权限。如果 runtime 更换了该 session 的计算,已建立的连接就会断开,而除非该 session 使用持久化存储,agent 的编辑可能无法留存。如果你需要文件比计算实例活得更久,参见 File system configurations for AgentCore runtime。

agent 的文件工具会把每个路径都解析到 site 文件夹内部,并拒绝位于其外的路径,所以一个 prompt 无法让 agent 去改动 session 里的其他文件。如果别人也能向你的 coding agent 发送 prompts,请考虑用 Amazon Bedrock Guardrails 来过滤有害的 prompts 和 responses,并在发布 agent 的改动之前先审视一遍。

清理

为避免持续产生费用,请停止预览并删除该示例创建的资源。agent 编辑的那个网站就存在于 session 之内,所以它会随 session 一同消失。

要清理:

运行 stop 单元格,并在 notebook 提示时按 Enter。这会停掉预览页、本地 endpoint 和 session。

运行 %run cleanup.py 单元格,它删除 runtime、上传的代码以及那个 IAM 角色。

结语

Session endpoints 让你从自己的工具、经由 HTTP/1.1、HTTP/2 和 WebSocket,在你允许的端口上,对所处 AgentCore runtime session 里的应用进行经过认证的访问。在本文中,你部署了一个在其 session 里带有 Vite 网站的 coding agent,通过一个本地 endpoint 在浏览器中打开了实时网站,向 agent 请求了一个深色主题,并看着改动随 agent 保存文件而到来。你还触达了同一个 session 里的第二个端口,并确认了 Session endpoint 会拒绝什么。

想更进一步,可以在 site 文件夹里放入你自己的网站来运行这个 notebook,或者改动 agent 的工具以契合你的 coding agent 的工作方式。完整的一组选项(包括端口区间、OAuth、HTTP/2 和 gRPC),参见 Connect to runtime sessions through a session endpoint。

要在你自己的 agent 中更改 InvokeAgentRuntime 所用的端口或路径,参见 Configure your agent's serving port and invocation path。如果你的 agent 还需要在同一个 session 里运行构建或测试命令,参见 Execute shell commands in AgentCore runtime sessions。想像本示例这样从一个 zip 文件部署你自己的 Node.js agent,参见 Direct code deployment for Node.js。至于该服务提供的其余一切,从 Host agent or tools with Amazon Bedrock AgentCore runtime 开始,并在 agentcore-samples GitHub 仓库 中找到更多示例。

关于作者