编码代理现在能够构建可运行的网页应用:包括仪表盘、产品页面以及产品团队想要测试的原型。检验这些应用最快捷的方式是打开应用、使用它、提出修改要求,然后查看结果。当应用在代理编辑时持续运行时,这种循环效果很好,因为每次修改都会在几秒内出现在浏览器中。如果必须先将应用复制出来并部署到其他位置,那么每次修改都需要等待部署完成,检验过程就会相应减慢。
Amazon Bedrock AgentCore 是一个用于大规模构建、连接和优化智能体的平台,用户可选择不同的智能体框架和基础模型(FM)。AgentCore runtime是 Amazon Bedrock AgentCore 的一项功能,它让每个智能体会话在独立的微虚拟机器中运行。通过 Session endpoints,你可以从自己的浏览器打开该会话中的应用。Session Endpoints 为每个会话提供经过认证的 URL,能够将每个请求的 HTTP 方法、路径、查询字符串和主体以及 WebSocket 连接转发到你允许的端口。当智能体保存文件时,你可以看到页面实时更新。
在本文中,你部署了一个编码代理,该代理会在其会话中保持 Vite 网站运行。然后打开一个本地页面,左侧为聊天界面,右侧为实时网站。你要求代理将网站切换为深色主题,按照其步骤进行操作,同时观察网站变化无需刷新。最后,你查看内部发生的情况:同一会话中的第二个端口以及会话端点拒绝的请求。
完整的示例文件,包括本帖所涉及的笔记本文件,位于 14-remote-access 文件夹中,该文件夹属于 agentcore-samples GitHub 仓库。
会话端点如何工作
每个会话都有属于自己的会话端点,而六项细节决定了您如何使用它。
您选择它到达的端口。 您设置 allowedPorts 当您调用时 创建代理运行环境:1–5项记录,每项为一个单独的端口或8000–12000范围内的范围,不包括 保留平台端口允许端口并不会启动服务器,因此您的应用程序必须在该端口上监听,并绑定到该端口 0.0.0.0.
该 URL 随会话一同发送。 InvokeAgentRuntime 的响应会在 X-Amzn-Bedrock-AgentCore-Runtime-Session-Endpoint-Url 头中传递,那些对其进行建模的 SDK 会将其暴露为 sessionEndpointUrl。
每个请求都经过认证。对于使用AWS Identity and Access Management (IAM)的运行时,每个 HTTP 请求、HTTP/2 流以及 WebSocket 握手都包含签名版本 4 (SigV4)签名。调用方还需要运行时及其运行时端点上具备bedrock-agentcore:InvokeAgentRuntimeProxy权限。对于使用 inbound JSON Web Token (JWT) 授权器的运行时,每个请求则包含持票令牌。仅知道 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。
它仅适用于一个会话。 每次请求时都需要凭证,并且仅持续整个会话时间,因此可用于构建、测试和审查您的代理产生的内容。若要将应用提供给用户,请将其部署到如AWS Amplify Hosting这样的托管服务中。
浏览器无法自行为页面发出的请求添加 SigV4 签名或持有令牌,因此会话端点客户端在 bedrock-agentcore SDK 可以在您的机器上打开本地端点。您的浏览器将自动打开 http://localhost:8088,而本地端点会在转发之前,将您的凭证添加到每个请求和 WebSocket 握手过程中。
会话端点与运行时端点不同,后者是由 AgentCore 运行时直接提供的。使用运行时端点,例如 DEFAULT,可以访问你的代理,该代理决定了调用者将访问的版本。InvokeAgentRuntime 调用会通过该端点进行解析,因此你可以让开发版本和生产版本使用不同的版本,并在不更改调用者的情况下进行升级或回退。使用会话端点可以查看你的代理在会话中的运行情况,例如网页预览。这是一个经过认证的 URL,仅能访问你允许的端口,适用于会话运行的任何版本,且当会话结束时就会停止工作。有关完整文档,请参考 通过会话端点连接运行时会话。
解决方案概述
该示例包含四个部分。编码代理在 8080 端口的会话中运行,并使用四种工具来编辑网站文件:列表、读取、写入和编辑。代理在 8090 端口启动 Vite 开发服务器,该服务器负责提供网站服务,并通过热重载 WebSocket 将每次保存的更改推送到浏览器中。在你的机器上,PreviewApp 负责显示预览页面,将你的提示发送到 InvokeAgentRuntime,并为网站打开一个本地端点。如图 1 所示,预览页面通过本地端点和会话端点到 8090 端口的 Vite 开发服务器加载网站内容,然后通过 InvokeAgentRuntime 将你的提示发送给 8080 端口的代理。这些数字表示单个请求中各个步骤的顺序。
图 1:解决方案架构
在步骤 1 之前,PreviewApp 已经调用了一次 InvokeAgentRuntime 来启动会话,从而启动代理和 Vite 开发服务器。PreviewApp 从该响应中读取了会话端点 URL,并打开了端口为 8090 的本地端点。图 1 中的编号步骤则会在收到更改请求后依次执行。
- 预览页面的站点面板从
localhost:8088的本地端点加载网站。该本地端点会将您的凭证添加到每个请求和 WebSocket 握手过程中,并将其转发到会话端点。会话端点会检查签名和端口是否落在allowedPorts范围内,然后将其转发到端口为 8090 的 Vite 开发服务器。该页面会保持 Vite hot-reload WebSocket 连接开启状态。 - 您从聊天窗格发送提示词。
PreviewApp使用您的 AWS 凭据作为标准 AWS API 调用,将提示词发送给InvokeAgentRuntime,运行时则通过 8080 端口将其传输给智能体。智能体的操作步骤会在执行过程中实时反馈到聊天窗格中。 - 代理调用 Amazon Bedrock 中的 Claude Haiku 5.5,以决定需要做什么更改。
- 代理程序读取网站的文件,并保存它修改过的文件。Vite 开发服务器会提供这些文件,并监控它们是否发生变化。
- 当文件被保存时,Vite 会将更改通过第1步中打开的 WebSocket 传回,经过会话端点和本地端点,然后网站窗格会自动更新而无需刷新。
- 从笔记本中,
PreviewApp通过相同的会话端点,在 8081 端口上读取代理的/status路径。只有端口发生了变化。
端口 8080 不在 allowedPorts 中,因为 InvokeAgentRuntime 无需通过会话端点即可访问代理。
先决条件
要跟随演示步骤,您需要:
- 位于 AWS 区域中的 AWS 账户,该账户拥有 AgentCore 运行时会话端点,且凭据已配置好。
- 创建 AWS 身份和访问管理 (IAM) 角色以及上传内容的权限 亚马逊简单存储服务(Amazon S3),并创建一个运行时,此外
bedrock-agentcore:InvokeAgentRuntime和bedrock-agentcore:InvokeAgentRuntimeProxy在那种运行时及其DEFAULT运行时间端点。有关详情,请参考 AgentCore 运行时的 IAM 权限. - Python 3.10 或更高版本,且包含
bedrock-agentcore1.25.2 或更高版本以及boto31.43.122 或更高版本。 - Git,用于克隆示例仓库;以及一个 Jupyter 环境,如 JupyterLab 或带有 Jupyter 扩展的 Visual Studio Code,以便运行笔记本。
- 在 Amazon Bedrock 中访问 Claude Haiku 5.5。关于各地区的模型可用情况,请参考 各模型在地区的可用性。
- Node.js 22 或以上,且
npm即部署脚本用来打包代理和网站的文件。
该示例将代理作为 ZIP 文件部署到 Amazon S3 中,并使用 Node.js 直接代码部署方式,因此无需使用 Docker 或 Amazon Elastic Container Registry (Amazon ECR) 仓库。会话端点适用于 microVM 运行时,而非实例计算类型;会话端点的 URL 可通过公共 HTTPS 访问。AWS PrivateLink 不支持入站连接。
部署代理及其网站
首先,您需部署运行时环境,而在此选择的配置决定了会话端点可以访问哪些端口。部署脚本会将代理程序打包到一个文件中,添加网站及其依赖项以适配 Linux on Arm64 系统,然后将压缩包上传到 Amazon S3,最后生成运行时环境。
以下来自 deploy.py 的片段展示了与本文相关的两个设置。protocolConfiguration 指定了代理监听 InvokeAgentRuntime 的地址,allowedPorts 则列出了会话端点可以访问的端口:网站使用 8090 端口,代理状态路径使用 8081 端口。端口 8080 不在列表中,因为 InvokeAgentRuntime 无需该端口即可连接到代理。关于端口和路径设置,请参考 配置代理的服务端口和调用路径。
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 配置使得开发服务器能够从会话端点访问。它监听 0.0.0.0 地址的 8090 端口,并且不限制 Host 标头(server.allowedHosts 为 true),因为请求是依据运行时分配的主机名而非 localhost 发送的。会话端点在请求到达服务器之前对其进行身份验证,因此服务器无需进行自己的主机检查。
部署运行时环境:
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
2. 从示例文件夹中打开 session_endpoints_preview.ipynb。
3. 运行安装单元,该单元将安装 Python 依赖项。
4. 运行 %run deploy.py 单元格。部署过程需要几分钟时间,主要是等待运行时达到 READY 状态。
打开预览
当运行环境准备就绪后,即可开始预览。一次调用会完成三件事:启动会话(从而启动网站),打开端口为 8090 的本地端点,并在 localhost:8087 上提供预览页面。
from preview_app import PreviewApp
app = PreviewApp().start()
print("Open", app.url)
在 start() 内部,使用 Session 端点的调用较为简短。第一个 InvokeAgentRuntime 调用会在响应头中返回 URL,session_endpoint_url 负责读取该 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的单元格。 - 在浏览器中打开打印出的链接
http://localhost:8087。
页面右侧显示的是网站,该网站通过会话中的端口 8090 提供服务;左侧则有一个简短指南,包含建议的请求内容。
向代理请求更改
现在您请求进行更改,然后观察更改的完成过程。每个提示信息都通过 InvokeAgentRuntime 传递给代理。代理会读取它需要的文件,写入其修改的内容,并实时报告每一步操作。当文件保存完成后,Vite 开发服务器会通过 WebSocket、Session 端点和本地端点将更改推送到服务器,从而使网站即时更新。
请求修改:
- 在预览页面上,选择 将此网站切换为深色咖啡馆主题颜色。
- 在聊天窗口中按照代理的步骤操作,它会读取并保存文件。
- 查看网站窗格。当代理程序保存样式表时,该窗格会发生变化,并且有一个横幅标识出引起变化的文件。
以下视频展示了代理处理多个请求时的预览页面。选择建议中的请求后,该请求会被发送给代理;聊天窗口会列出代理读取并保存的每个文件;右侧的网站窗口则无需刷新即可更新,从深色主题变为绿色的“开始订单”按钮。
图 2:代理运行时的预览页面
步骤会持续进行,因为当你要求它时,代理会响应服务器发送的事件。你可以用 Python 发送相同的提示。 app.ask,该工具可以读取流数据 iter_events 从 bedrock-agentcore SDK。打开页面更新方式也相同:
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.
同一会话中到达第二个端口
该网站并非您可以访问的唯一服务器。代理服务在 8081 端口上提供 /status 接口,该接口会列出每个提示词以及它所修改的文件。相同的会话端点也可以访问该服务,唯一的区别是端口参数不同。
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
会话端点拒绝的内容
当运行时系统拒绝请求时,它会通过响应头返回 HTTP 状态、空正文和错误代码,这样你就能区分出应用程序返回的拒绝和错误。该笔记本向允许的端口之外的端口发送请求,也发送没有凭证的请求,运行时系统都会以 403 AccessDenied 表示拒绝。
以下表格列出了您在使用 Session endpoints 进行构建时可能会遇到的拒绝情况。
| 请求 | 运行时的响应 |
一个不在 allowedPorts 中的端口 |
403 AccessDenied |
| 一个没有有效凭证的请求 | 403 AccessDenied 或 401 AuthenticationRequired |
| 一个允许的端口,没有任何连接在该端口上的设备 | 502 PortNotReachable |
| 一个会话已不存在的URL | 404 SessionNotFound |
如何保护您的会话访问权限
运行时在转发请求之前会移除自身的认证头信息,因此网站无法收到您的签名。请求会被记录在 AWS CloudTrail 中,作为 InvokeAgentRuntimeProxy 事件,事件来源为 bedrock-agentcore.amazonaws.com。本地端点使用您的凭据进行操作,因此限制了可使用的用户。它仅监听 127.0.0.1,只响应指向其本地地址的请求,并拒绝来自其他源的页面所建立的 WebSocket 连接。仅在使用预览功能时运行本地端点。有关更多信息,请参阅 CloudTrail 中的会话端点请求日志。
访问控制不会将网站与代理分开。两者都在同一会话中运行,因此只需给执行角色赋予代理所需的权限即可。如果运行时替代了会话的计算功能,打开的连接会关闭,且除非会话使用持久存储,否则代理的修改可能无法保留。如果需要让文件在计算结束后仍然保留,请参考AgentCore运行时的文件系统配置。
代理的文件工具会处理站点文件夹内的所有路径,而拒绝文件夹外的路径。因此,提示无法让代理更改会话中的其他文件。如果其他人可以向你的编码代理发送提示,请考虑使用Amazon Bedrock Guardrails来过滤有害提示和响应,并在发布之前审核代理所做的更改。
清理
为了避免持续收费,请停止预览并删除示例创建的资源。代理编辑的网站存在于会话中,因此会随会话一起被删除。
清理操作:
1. 运行“停止单元格”操作,当笔记本提示时按 Enter 键。这样即可停止预览页面、本地端点以及会话。
2. 运行 %run cleanup.py 单元格,该操作会删除运行时文件、上传的代码以及 IAM 角色。
结论
会话端点允许您通过 HTTP/1.1、HTTP/2 和 WebSocket 在允许的端口上,使用自己的工具在 AgentCore 运行时会话中获得经过身份验证的访问权限。在这篇帖子中,您将一个编码代理部署到其会话中,并使用了 Vite 网站;通过本地端点在浏览器中打开实时网站,请求代理采用深色主题,然后观察着代理保存文件后变化的发生。 您也在同一会话中到达了第二个端口,并确认了会话端点所拒绝的内容。
若要进一步操作,请在站点文件夹中运行笔记本,或使用与您的编码代理工作方式相匹配的代理工具。关于所有选项的完整说明,包括端口范围、OAuth、HTTP/2 和 gRPC,请参考 通过会话端点连接运行时会话。
若要更改 InvokeAgentRuntime 在您自己的代理中使用的端口或路径,请参考 配置代理的服务端口和调用路径。如果您的代理还需要在同一会话中运行构建或测试命令,请参考 在 AgentCore 运行时会话中执行 shell 命令。若需按照此示例从 zip 文件部署自己的 Node.js 代理,请参考 Node.js 的直接代码部署。对于该服务提供的其他功能,请从 使用 Amazon Bedrock AgentCore 运行时托管代理或工具开始,并在 agentcore-samples GitHub 仓库中查找更多示例。