在浏览器实时预览云端 Agent 开发结果
Amazon Bedrock AgentCore 的会话端点为运行时会话提供认证 URL,可将 HTTP 请求和 WebSocket 连接转发到获准端口。教程部署运行 Vite 网站的编程 Agent,让浏览器实时呈现其文件修改结果。
AI 深度解读
AI 编程代理改完页面,为什么还得等部署才能验收?AWS 给出的方案是:把代理和 Vite 开发服务器放在同一个隔离会话里,通过带鉴权的 Session endpoint,让本地浏览器直接访问远端页面。代理保存文件,浏览器就能收到热更新。
这篇教程值得看的,是它把「边聊边改边预览」拆成了一套可理解的工程链路:提示词怎么送进去,页面怎么打开,WebSocket 怎么穿过鉴权,以及临时预览与正式上线之间有哪些边界。
页面实时变化,靠的是打通 Vite 的访问链路
作者搭建了一个左右分栏的预览页:左边与代理聊天,右边显示咖啡店网站。用户要求切换深色主题,代理读取并修改样式文件,右侧页面随即更新,无须手动刷新。
这里没有特殊的页面渲染技术。代理通过 list、read、write、edit 四种文件工具修改网站,Vite 负责监听文件并通过热更新 WebSocket 通知浏览器。
关键做法是让代理编辑的文件,就是开发服务器正在提供的文件。
AgentCore runtime 为每个代理会话提供独立的 microVM。样例把三个服务放进同一个会话:代理在 8080 接收调用,Vite 在 8090 提供网站,8081 提供 /status,记录提示词及其修改的文件。
本地 PreviewApp 则承担两项工作:通过 InvokeAgentRuntime 发送提示词,通过本地代理访问远端网站。预览页位于 http://localhost:8087,网站访问入口位于 http://localhost:8088,二者别混在一起。
代理按需通过服务端事件(SSE)流式报告步骤,Python 端也可以用 app.ask 提问,并由 SDK 的 iter_events 读取事件。这条通道展示「读取了哪个文件、保存了哪个文件」;页面变化走的是另一条 Vite WebSocket 通道。
原文演示了切换深色主题,以及用 Make the Order ahead button green 修改按钮颜色。它证明了这套链路可以工作,但没有给出延迟、并发量或与部署预览方案的对照数据。
为什么拿到会话 URL,仍然不能直接打开页面
Session endpoint 是通向会话内服务的鉴权入口。它转发 HTTP 方法、路径、查询参数、请求体和 WebSocket 连接,但只允许访问事先声明的端口。
创建 runtime 时,CreateAgentRuntime 的 allowedPorts 可配置 1–5 项,每项可以是单个端口或端口范围;范围须在 8000–12000 内,并排除平台保留端口。声明允许访问,并不会替你启动服务,应用仍须监听 0.0.0.0。
下面这段配置把代理调用入口和网站预览入口分开:
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}],
要看最后两行:8080 通过 InvokeAgentRuntime 到达,因此没有放进 allowedPorts;Session endpoint 只开放 8090 和 8081。
客户端始终连接 HTTPS 443,目标端口由主机名前缀选择,例如 8090--<session-endpoint-id>.runtime.bedrock-agentcore.<region>.on.aws。协议层支持 HTTP/1.1、HTTP/2、SSE、gRPC 和 WebSocket,但本文实际走通的是 HTTP/1.1 与 WebSocket。
使用 IAM 鉴权时,每个 HTTP 请求、HTTP/2 流和 WebSocket 握手都需要 SigV4 签名,调用者还需要在 runtime 及其 runtime endpoint 上拥有 bedrock-agentcore:InvokeAgentRuntimeProxy 权限。配置入站 JWT authorizer 时,则携带 bearer token。只知道 URL 并不足以访问。
普通页面请求不会自动附带这些凭证,所以 SDK 在本地启动代理,逐个补上鉴权信息:
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()
注意 open_local_endpoint 的两个端口:8090 是远端服务,8088 是本地入口。会话 URL 来自响应头 X-Amzn-Bedrock-AgentCore-Runtime-Session-Endpoint-Url,支持该字段的 SDK 会将其暴露为 sessionEndpointUrl。
还要区分 runtime endpoint 与 Session endpoint。前者如 DEFAULT,用于选择代理版本、支持发布和回滚;后者访问某个具体会话中的服务,会话结束后就失效。
跑通样例之前,要接受哪些环境和安全约束
样例要求 Python 3.10 或以上、bedrock-agentcore 1.25.2 或以上、boto3 1.43.122 或以上,以及 Node.js 22 或以上和 npm;还需要 Git、Jupyter 环境、已配置的 AWS 凭证,以及支持 Session endpoints 的 Region。
部署需要创建 IAM role、上传 Amazon S3、创建 runtime 的权限,还需要 bedrock-agentcore:InvokeAgentRuntime 和前述代理访问权限。原文指定模型为 Amazon Bedrock 中的 Claude Haiku 5.5,但没有给出模型 ID,复现时仍需核对模型及区域可用性。
部署脚本将代理打成单文件,连同网站及 Linux Arm64 依赖一起压缩上传 S3,通过 Node.js direct code deployment 运行,无须 Docker 或 Amazon ECR。Notebook 为 session_endpoints_preview.ipynb,部署执行 %run deploy.py,等待状态变成 READY,再调用 PreviewApp().start()。
原文的样例位置存在矛盾:开头写 14-remote-access,后面的命令指向 01-features/02-host-your-agent/01-runtime/03-advanced/16-session-endpoints,不能把两处都当成准确路径。
安全边界也有几处必须理解:
- Session endpoints 支持 microVM runtime,不支持
Instancescompute type;入口通过公共 HTTPS 访问,入站连接不支持 AWS PrivateLink。 - Vite 使用
server.allowedHosts=true,以接受平台分配的主机名。这依赖前方 Session endpoint 的鉴权,不能直接当作普通公网 Vite 服务的配置建议。 - Notebook 对未授权端口和无凭证请求的测试,均返回
403 AccessDenied。平台拒绝时响应体为空,错误码放在响应头中,但原文没有提供完整错误表。 - 本地代理只监听
127.0.0.1,检查请求目标地址,并拒绝其他来源页面发起的 WebSocket 连接;它仍然使用你的凭证,应只在预览期间运行。
平台会移除自身鉴权头,再转发给网站;请求以 InvokeAgentRuntimeProxy 事件记录在 AWS CloudTrail,事件源为 bedrock-agentcore.amazonaws.com。
不过,网站与代理共享会话,访问控制没有在两者之间建立额外隔离。执行角色仍应采用最小权限。作者还让文件工具将路径限制在网站目录,但这只是文件访问约束,不能替代整个运行环境的权限设计。
我的判断
我认可它对问题的拆分:实时预览需要同时解决远端端口访问、逐请求鉴权和 WebSocket 转发,单独给代理增加文件编辑能力,并不足以形成顺畅的验收过程。
对已经使用 AgentCore 的团队,这套方案有直接价值。代理版本入口与会话预览入口分开,也让控制面和页面访问各有职责。
但作者没有证明它比本地开发、SSH 隧道或其他远程开发环境更快、更便宜。若代理本来就在开发者机器上运行,本地 Vite 已经能完成热更新,迁到云端还会增加 IAM、会话生命周期和资源清理成本。
这套教程展示的是临时预览闭环,不能替代正式部署验收。
开发服务器的热更新成功,不代表生产构建、静态资源路径或部署环境配置都正确。原文建议面向最终用户时部署到 AWS Amplify Hosting 等托管服务,这个边界是合理的。
还有一个容易漏掉的问题:runtime 更换会话计算资源时,连接会断开;未配置持久存储,代理的修改可能丢失。预览结束后,代码如何可靠导出、提交和恢复,原文没有展开。
能拿来做什么
- 如果你正在开发云端 AI 编程工具,可以先复用「代理修改文件、Vite 提供页面、本地代理补鉴权」这条最小链路,验证 HTTP 与热更新 WebSocket 都能通过,再扩展界面。
- 为 Node.js 代理划分调用端口、预览端口和状态端口,并按用途配置
allowedPorts。调试时可用app.endpoint.request("GET", "/status", port=8081)读取修改记录。 - 把文件保存、预览更新和代码留存分开处理。需要保留成果时配置持久存储或明确的导出流程,发布前再检查代理修改和生产构建结果。
- 跑样例时把清理也纳入流程:执行 stop 单元格并按 Enter,随后运行
%run cleanup.py,删除 runtime、上传代码和 IAM role;结束会话也会带走未持久保存的网站。