View a markdown version of this page

使用以下命令开始双向流式传输 WebSocket - 亚马逊基岩 AgentCore

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用以下命令开始双向流式传输 WebSocket

Amazon Bedrock AgentCore Runtime 允许您部署支持 WebSocket 流式传输的代理,实现实时双向通信。本指南引导您使用 WebSocket创建、测试和部署您的第一个双向流媒体代理。

在本部分中,您将学习:

  • AgentCore Runtime 如何支持 WebSocket 连接

  • 如何创建具有双向流媒体功能的代理应用程序

  • 如何在本地测试您的代理

  • 如何将代理部署到 AWS

  • 如何调用已部署的代理

  • 如何使用带有 WebSocket 连接的会话

有关该 WebSocket 协议的更多信息,请参阅 WebSocket RFC 645 5。

AgentCore Runtime 如何支持 WebSocket 连接

AgentCore Runtime WebSocket 支持在客户端和代理之间实现持久的双向流媒体连接。 AgentCore Runtime 期望容器8080在/ws路径的端口上实现 WebSocket 端点,这符合标准 WebSocket 服务器惯例。

AgentCore Runtime 的 WebSocket 支持提供了与之相同的无服务器、会话隔离、身份和可观察性功能。InvokeAgentRuntime此外,它使用SigV4或OAuth 2.0身份验证通过 WebSocket 连接实现低延迟、实时的双向消息传输,使其成为实时对话语音代理等应用程序的理想之选。

支持的 WebSocket 库

WebSockets 在 AgentCore Runtime 上使用的双向流式传输支持使用任何 WebSocket 语言库的应用程序。唯一的要求是客户端通过 WebSocket 协议连接连接到服务端点:

wss://bedrock-agentcore.<region>.amazonaws.com/runtimes/<agentRuntimeArn>/ws

使用一种支持的身份验证方法(SigV4 标头、SigV4 预签名 URL 或 OAuth 2.0),并且代理应用程序按照 HTTP 协议合同中的规定实现 WebSocket 服务合同。HTTP 协议合约

这种灵活性允许您在不同的编程语言和框架中使用您的首选 WebSocket 实现,从而确保与现有代码库和开发工作流程的兼容性。

WebSocket 与 AgentCore 运行时一起使用

在本入门教程中,您将使用 b edrock-agentcore Python SDK 和 CLI 进行部署,创建、测试和部署支持双向流式传输的代理应用程序。 AgentCore

先决条件

在开始之前,请确保:

  • AWS 配置了凭据的账户。要配置您的 AWS 证书,请参阅 C AWS LI 中的配置和凭据文件设置。

  • 已安装 Python 3.10+

  • Node.js 已安装 20 多个

  • AWS 权限:要使用 AgentCore CLI 创建和部署代理,必须具有相应的权限。有关更多信息,请参阅使用 AgentCore CLI 。

第 1 步:设置项目并安装依赖项

创建项目文件夹并安装所需的软件包:

mkdir agentcore-runtime-quickstart-websocket cd agentcore-runtime-quickstart-websocket python3 -m venv .venv source .venv/bin/activate

将 pip 升级到最新版本:

pip install --upgrade pip

安装以下必需的软件包:

  • bedrock-agentcore -用于构建 AI 代理的亚马逊 Bedrock AgentCore SDK,包括 python 库依赖项 websockets

pip install bedrock-agentcore

第 2 步:创建您的双向流媒体代理

为您的双向流媒体代理代码创建一个名websocket_echo_agent.py为的源文件。添加以下代码:

from bedrock_agentcore import BedrockAgentCoreApp app = BedrockAgentCoreApp() @app.websocket async def websocket_handler(websocket, context): """Simple echo WebSocket handler.""" await websocket.accept() try: data = await websocket.receive_json() # Echo back await websocket.send_json({"echo": data}) except Exception as e: print(f"Error: {e}") finally: await websocket.close() if __name__ == "__main__": app.run(log_level="info")

创建requirements.txt并添加以下内容:

bedrock-agentcore

包含 python websockets 库依赖关系

理解代码

  • BedrockAgentCoreApp: 创建代理应用程序,用于扩展 Starlette 以进行 AI 代理部署,提供 WebSocket 支持、HTTP 路由、中间件和异常处理功能

  • WebSocket 装饰器:@app.websocket装饰器自动处理端口 8080 上/ws路径上的连接

  • Echo Logic:使用发送回接收到的数据 {"echo": data}

  • 错误处理:使用 try/except /finally 结构来确保正确的错误记录和正常关闭连接。

第 3 步:在本地测试您的双向流媒体代理

启动您的双向流媒体代理

打开终端窗口,使用以下命令启动双向流媒体代理:

python websocket_echo_agent.py

您应该看到表明服务器正在端口 8080 上运行的输出。

测试 WebSocket 连接

创建一个名为的本地 WebSocket 客户端websocket_agent_client.py:

import asyncio import websockets import json async def local_websocket(): uri = "ws://localhost:8080/ws" try: async with websockets.connect(uri) as websocket: # Send a message await websocket.send(json.dumps({"inputText": "Hello WebSocket!"})) # Receive the echo response response = await websocket.recv() print(f"Received: {response}") except Exception as e: print(f"Connection failed: {e}") if __name__ == "__main__": asyncio.run(local_websocket())

打开另一个终端窗口并运行客户端,在本地测试您的双向流媒体代理:

python websocket_agent_client.py

成功:您应该看到类似的回复Received: {"echo":{"inputText":"Hello WebSocket!"}}。在运行代理的终端窗口中,输入Ctrl+C以停止代理。

第 4 步:将双向流媒体代理部署到 AgentCore Runtime

安装部署工具

安装 C AgentCore LI:

npm install -g @aws/agentcore

验证安装:

agentcore --version

有关可用的命令和选项,请参阅 AgentCore CLI 参考。

创建项目并部署到 AWS

为您的双向流媒体代理创建一个新项目:

cd .. agentcore create --project-name WebSocketProject --no-agent cd WebSocketProject agentcore add agent \ --name WebSocketAgent \ --type byo \ --language Python \ --framework Strands \ --model-provider Bedrock \ --memory none \ --protocol HTTP \ --code-location ../agentcore-runtime-quickstart-websocket \ --entrypoint websocket_echo_agent.py

部署您的代理:

agentcore deploy

该 AgentCore 项目引用了现有的agentcore-runtime-quickstart-websocket源目录。

部署后,您将收到一个代理运行时 ARN,如下所示:

arn:aws:bedrock-agentcore:us-west-2:accountId:runtime/websocket_echo_agent-xyz123

保存此 ARN,因为您需要它来调用已部署的代理。

第 5 步:调用已部署的双向流媒体代理

设置环境变量

设置所需的环境变量:

  1. 导出您的代理 ARN:

    export AGENT_ARN="arn:aws:bedrock-agentcore:us-west-2:accountId:runtime/websocket_echo_agent-xyz123"
  2. 如果使用 OAuth,请导出您的持有者令牌:

    export BEARER_TOKEN="your_oauth_token_here"

身份验证方法

InvokeAgentRuntimeWithWebSocketStreamAPI 操作建立了支持客户端和代理之间双向流式传输的 WebSocket 连接。您可以使用以下方法对 WebSocket 连接进行身份验证:

  • AWS 签名版本 4 标头:使用您的 AWS 证书对 WebSocket 握手请求标头进行签名

  • AWS 签名版本 4 Pre-signed 网址:使用 SigV4 签名作为查询参数创建预签名 WebSocket URL

  • OAuth 持有者令牌:在授权标头中传递 OAuth 令牌以进行外部身份提供商集成

提示

确保你有bedrock-agentcore:InvokeAgentRuntimeWithWebSocketStream权限。

使用 SigV4 签名标头进行连接

以下示例显示如何使用 SigV4 签名标头建立 WebSocket 连接并与代理运行时通信:

from bedrock_agentcore.runtime import AgentCoreRuntimeClient import websockets import asyncio import json import os async def main(): # Get runtime ARN from environment variable runtime_arn = os.getenv('AGENT_ARN') if not runtime_arn: raise ValueError("AGENT_ARN environment variable is required") # Initialize client client = AgentCoreRuntimeClient(region="us-west-2") # Generate WebSocket connection with authentication ws_url, headers = client.generate_ws_connection( runtime_arn=runtime_arn ) try: async with websockets.connect(ws_url, additional_headers=headers) as ws: # Send message await ws.send(json.dumps({"inputText": "Hello!"})) # Receive response response = await ws.recv() print(f"Received: {response}") except websockets.exceptions.InvalidStatus as e: print(f"WebSocket handshake failed with status code: {e.response.status_code}") print(f"Response headers: {e.response.headers}") print(f"Response body: {e.response.body.decode()}") except Exception as e: print(f"Connection failed: {e}") if __name__ == "__main__": asyncio.run(main())

运行客户端来测试您部署的代理:

python websocket_agent_client_sigv4_headers.py

成功:你应该看到如下回复:

Received: {"echo":{"inputText":"Hello!"}}

使用预签名 URL 进行连接(通过查询参数进行 SigV4)

以下示例说明如何使用 SigV4 查询参数创建 WebSocket URL 并建立连接:

from bedrock_agentcore.runtime import AgentCoreRuntimeClient import websockets import asyncio import json import os async def main(): runtime_arn = os.getenv('AGENT_ARN') if not runtime_arn: raise ValueError("AGENT_ARN environment variable is required") client = AgentCoreRuntimeClient(region="us-west-2") # Generate WebSocket pre-signed URL (with SigV4 via query parameters) # wss://...amazonaws.com/runtimes/.../ws?X-Amz-Algorithm=AWS4-HMAC-SHA256 # &X-Amz-Credential=...&X-Amz-Date=...&X-Amz-Expires=300 # &X-Amz-SignedHeaders=...&X-Amz-Signature=... sigv4_url = client.generate_presigned_url( runtime_arn=runtime_arn, expires=300 # 5 minutes ) try: async with websockets.connect(sigv4_url) as ws: await ws.send(json.dumps({"inputText": "Hello!"})) response = await ws.recv() print(f"Received: {response}") except websockets.exceptions.InvalidStatus as e: print(f"WebSocket handshake failed with status code: {e.response.status_code}") print(f"Response headers: {e.response.headers}") print(f"Response body: {e.response.body.decode()}") except Exception as e: print(f"Connection failed: {e}") if __name__ == "__main__": asyncio.run(main())

运行客户端来测试您部署的代理:

python websocket_agent_client_sigv4_query_parameters.py

成功:你应该看到如下回复:

Received: {"echo":{"inputText":"Hello!"}}

使用 OAuth 连接

AgentCore 运行时支持对连接进行 OAuth 持有者令牌身份验证。 WebSocket 要使用 OAuth 身份验证,您需要按照 “使用入站身份验证和出站身份验证和出站身份验证进行身份验证和授权” 的 JWT 入站授权和 OAuth 出站访问示例部分中所述,使用 JWT 授权配置代理运行时。

完成 OAuth 设置并按照步骤 4:使用不记名令牌调用 OAuth 指南中的代理获得持有者令牌后,即可使用该令牌建立连接。 WebSocket

带有 OAuth 的 Python 客户端

以下示例显示如何使用 OAuth 与 Python 建立 WebSocket 连接:

from bedrock_agentcore.runtime import AgentCoreRuntimeClient import websockets import asyncio import json import os async def main(): # Get runtime ARN from environment variable runtime_arn = os.getenv('AGENT_ARN') if not runtime_arn: raise ValueError("AGENT_ARN environment variable is required") # Get OAuth bearer token from environment variable bearer_token = os.getenv('BEARER_TOKEN') if not bearer_token: raise ValueError("BEARER_TOKEN environment variable required for OAuth") # Initialize client client = AgentCoreRuntimeClient(region="us-west-2") # Generate WebSocket connection with OAuth ws_url, headers = client.generate_ws_connection_oauth( runtime_arn=runtime_arn, bearer_token=bearer_token ) try: async with websockets.connect(ws_url, additional_headers=headers) as ws: # Send message await ws.send(json.dumps({"inputText": "Hello!"})) # Receive response response = await ws.recv() print(f"Received: {response}") except websockets.exceptions.InvalidStatus as e: print(f"WebSocket handshake failed with status code: {e.response.status_code}") print(f"Response headers: {e.response.headers}") print(f"Response body: {e.response.body.decode()}") except Exception as e: print(f"Connection failed: {e}") if __name__ == "__main__": asyncio.run(main())

运行客户端来测试您部署的代理:

python websocket_agent_client_oauth.py

成功:你应该看到如下回复:

Received: {"echo":{"inputText":"Hello!"}}
带有 OA JavaScript uth 的浏览器客户端

浏览器的本机 WebSocket API 不提供在握手期间设置自定义标头的方法。为了支持浏览器的 OAuth 身份验证, AgentCore Runtime 在握手期间接受Sec-WebSocket-Protocol标头中嵌入的持有者令牌。 WebSocket

该令牌必须采用 base64url 编码并以前缀为前缀base64UrlBearerAuthorization.,然后是哨兵子协议。base64UrlBearerAuthorization

以下示例显示如何 JavaScript 使用 OAuth 与浏览器建立 WebSocket 连接:

<!DOCTYPE html> <html> <body> <button onclick="connect()">Connect</button> <div id="output"></div> <script> function connect() { const bearerToken = "your_oauth_token_here"; const runtimeArn = "arn:aws:bedrock-agentcore:us-west-2:accountId:runtime/agent-xyz123"; // Base64url encode token const base64url = btoa(bearerToken) .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=/g, ''); const ws = new WebSocket( `wss://bedrock-agentcore.us-west-2.amazonaws.com/runtimes/${runtimeArn}/ws`, [`base64UrlBearerAuthorization.${base64url}`, "base64UrlBearerAuthorization"] ); ws.onopen = () => ws.send(JSON.stringify({ inputText: "Hello!" })); ws.onmessage = (e) => document.getElementById("output").innerText = e.data; } </script> </body> </html>
注意

此身份验证方法适用于无法设置自定义标头的基于浏览器的客户端。对于非浏览器客户端(Python、 Node.js 服务器等),使用带有 OAuth 的 P ython 客户端中显示的 OAuth 标头身份验证。

注意

尚不支持除base64UrlBearerAuthorization之外的子协议。

重要

这是一个参考示例。不建议在生产代码中对令牌进行硬编码。

会话管理

在 WebSocket 连接上提供 session_id (X-Amzn-Bedrock-AgentCore-Runtime-Session-Id)(作为 URL 查询参数或请求标头)会将连接路由到隔离的运行时会话。代理可以访问存储在该会话中的对话上下文,通过引用先前的交互来实现对话的连续性。不同的会话 ID 访问不同的隔离上下文,从而确保用户或对话之间的完全隔离。

有关包括跟踪、清理和错误处理在内的全面会话生命周期管理,请参阅为代理使用隔离会话。

使用带有 WebSocket 连接的会话

要使用带有 WebSocket 连接的会话,请为每个用户或对话生成一个唯一的会话 ID,并在建立连接时将其传递:

例
SigV4 Headers
  1. from bedrock_agentcore.runtime import AgentCoreRuntimeClient import websockets import asyncio import json import os async def websocket_with_session(): client = AgentCoreRuntimeClient(region="us-west-2") session_id = "user-123-conversation-456" runtime_arn = os.getenv('AGENT_ARN') ws_url, headers = client.generate_ws_connection( runtime_arn=runtime_arn, session_id=session_id ) try: async with websockets.connect(ws_url, additional_headers=headers) as ws: await ws.send(json.dumps({"inputText": "Hello!"})) response = await ws.recv() print(f"Response: {response}") except websockets.exceptions.InvalidStatus as e: print(f"WebSocket handshake failed with status code: {e.response.status_code}") print(f"Response headers: {e.response.headers}") print(f"Response body: {e.response.body.decode()}") except Exception as e: print(f"Connection failed: {e}") asyncio.run(websocket_with_session())
SigV4 Pre-signed URL
  1. from bedrock_agentcore.runtime import AgentCoreRuntimeClient import websockets import asyncio import json import os async def websocket_with_session(): client = AgentCoreRuntimeClient(region="us-west-2") session_id = "user-123-conversation-456" runtime_arn = os.getenv('AGENT_ARN') presigned_url = client.generate_presigned_url( runtime_arn=runtime_arn, session_id=session_id, expires=300 ) try: async with websockets.connect(presigned_url) as ws: await ws.send(json.dumps({"inputText": "Hello!"})) response = await ws.recv() print(f"Response: {response}") except websockets.exceptions.InvalidStatus as e: print(f"WebSocket handshake failed with status code: {e.response.status_code}") print(f"Response headers: {e.response.headers}") print(f"Response body: {e.response.body.decode()}") except Exception as e: print(f"Connection failed: {e}") asyncio.run(websocket_with_session())
OAuth
  1. from bedrock_agentcore.runtime import AgentCoreRuntimeClient import websockets import asyncio import json import os async def websocket_with_session(): client = AgentCoreRuntimeClient(region="us-west-2") session_id = "user-123-conversation-456" runtime_arn = os.getenv('AGENT_ARN') bearer_token = os.getenv('BEARER_TOKEN') ws_url, headers = client.generate_ws_connection_oauth( runtime_arn=runtime_arn, session_id=session_id, bearer_token=bearer_token ) try: async with websockets.connect(ws_url, additional_headers=headers) as ws: await ws.send(json.dumps({"inputText": "Hello!"})) response = await ws.recv() print(f"Response: {response}") except websockets.exceptions.InvalidStatus as e: print(f"WebSocket handshake failed with status code: {e.response.status_code}") print(f"Response headers: {e.response.headers}") print(f"Response body: {e.response.body.decode()}") except Exception as e: print(f"Connection failed: {e}") asyncio.run(websocket_with_session())
提示

为获得最佳结果,请为会话 ID 使用 UUID 或其他唯一标识符,以避免不同用户或对话之间发生冲突。

通过对相关 WebSocket 连接使用相同的会话 ID,您可以确保在同一个对话中保持上下文,从而使您的代理能够在先前的交互基础上提供连贯的响应。

带有 WebSocket 连接的会话生命周期

对于 WebSocket 连接,每次客户端和代理之间有消息活动时,会话的空闲超时都会重置。这包括任何 WebSocket 消息交换,例如从客户端发送数据、接收代理到客户端的响应或 WebSocket ping/pong 框架。这意味着,只要消息继续流动,活跃的 WebSocket 对话就会使会话保持活动状态,从而防止在持续互动期间过早终止会话。

有关配置生命周期设置的更多信息,请参阅配置 Amazon Bedrock AgentCore 生命周期设置。要通过代理运行状况更直接地控制会话生命周期,请参阅运行时会话生命周期管理。

停止运行时会话

要在可配置会话IdleRuntimeSessionTimeout(默认为 15 分钟)之前停止正在运行的会话,请参阅停止正在运行的会话。

可观测性

亚马逊基岩可 AgentCore 观测性可帮助您跟踪、调试和监控您在亚马逊基岩 AgentCore 运行时托管的代理。首先,按照启用 Amazon Bedrock AgentCore 运行时可观察性中的说明启用 CloudWatch 交易搜索。要观察您的代理,请参阅查看您的亚马逊 Bedrock AgentCore 代理的可观测性数据。

对于 WebSocket 连接,跟踪代表完整的连接会话,而不是单个消息交换。

自定义标头

自定义标头允许您在初始 WebSocket 连接时将来自应用程序的上下文信息直接传递到代理代码。有关自定义标头支持、配置和限制的完整信息,请参阅将自定义标头传递给 Amazon Bedrock AgentCore Runtime 。

此外,前缀为的标头X-Amzn-Bedrock-AgentCore-Runtime-Custom-可以作为 WebSocket 连接中的 URL 查询参数传递。

例如,您可以在 WebSocket URL 中将自定义标头作为查询参数传递:

wss://bedrock-agentcore.<region>.amazonaws.com/runtimes/<agentRuntimeArn>/ws?X-Amzn-Bedrock-AgentCore-Runtime-Custom-TestHeader=query-param-test-value

代理应用程序容器将接收这些作为标头:

"headers": { "x-amzn-bedrock-agentcore-runtime-custom-testheader": "query-param-test-value" }

附录

安全注意事项

提示

有关所有运行时安全建议的综合视图,请参阅 AgentCore 运行时安全最佳实践。

身份验证

所有 WebSocket 连接都需要通过 SigV4 或 OAuth 2.0 进行正确的 AWS 身份验证

会话隔离

每个会话都在带有专用资源的隔离执行环境中运行

传输安全

所有连接均使用 HTTPS 上的 WSS(WebSocket 安全)进行加密通信

访问控制

IAM 策略控制 WebSocket 连接权限和对特定代理的访问权限

问题排查

常见 WebSocket-specific 问题

以下是您可能会遇到的常见问题:

连接失败

验证您的代理应用程序是否在处理连接请求 /ws

身份验证方法不匹配

确保您的客户端使用与代理配置相同的身份验证方法(OAuth 或 SigV4)

由于超出限制,连接已关闭

如果超出限制,例如消息帧速率或消息帧大小限制,连接将自动关闭。有关完整的限额信息,请参阅亚马逊 Bedrock 的配额 AgentCore

已超过消息帧大小

配置消息帧分段或实现分块以保持在 32KB 帧大小限制以下。在发送之前,将大型消息拆分成较小的块

运行状况检查失败

确保您的代理容器按照 HTTP 协议合同中的规定实现/ping终端节点。此端点可验证您的代理是否处于运行状态并已准备好处理请求,从而实现服务监控和自动恢复

错误处理

WebSocket 错误分两个阶段出现,具体取决于它们发生的时间。

建立连接( WebSocket 升级之前)

打开连接是一个标准的 HTTP 请求。HTTP 状态码反映异常,x-amzn-ErrorType响应标头带有异常名称。该服务在建立 WebSocket 连接之前可能会返回以下任何错误。

HTTP 错误代码 运行时异常 (x-amzn-ErrorType) 说明

400

ValidationException

请求数据或参数无效

401

UnauthorizedException

需要进行身份验证或凭据无效(OAuth-configured 代理)

402

ServiceQuotaExceededException

请求将超过服务配额

403

AccessDeniedException

请求的操作权限不足

404

ResourceNotFoundException

请求的资源不存在

409

ConflictException

资源冲突-资源已经存在

409

RetryableConflictException

会话操作正在进行中,请重试

424

RuntimeClientError

您的代理的容器返回了 4xx 或 5xx 错误-请检查您的日志 CloudWatch

429

ThrottlingException

请求过多-已超过请求速率限制

500

InternalServerException

处理请求时出现意外错误

注意

当您打开与该服务正在配置或断开的会话的 WebSocket 连接时,该服务将返回 RetryableConflictException (HTTP 409Session operation in progress, please retry)。这种情况是暂时的,可以重试。使用短暂的指数退避重试。这适用于针对同一会话的并发调用。 Already-running 会话不受影响。

活动连接( WebSocket 升级后)

一旦确定,将 WebSocket 使用标准 WebSocket 关闭代码而不是 HTTP 状态码来传达错误。常见的关闭代码包括:

  • 1000-正常关闭

  • 1001-走开

  • 1008-违反政策(超过限制)

  • 1009-消息太大(超过消息帧大小限制)

  • 1011-服务器错误

WebSocket 与其他协议的对比

何时使用 WebSocket:

  • Real-time 使用即时音频流进行语音对话,实现自然对话流程

  • 双向 audio/text /二进制数据流(将数据块从客户端流式传输到代理,反之亦然)

  • 中断处理(用户可以在对话中打断代理)

何时使用 HTTP:

  • 无需双向流式传输的请求响应模式的 HTTP

其他入门示例

有关在 AgentCore Runtime 中使用 WebSocket 双向流式传输的其他示例,请参阅WebSocket 双向流式传输 GitHub 示例:

  • 声波实现 (Python):原生 Amazon Nova Sonic WebSocket 实现,支持实时音频对话、语音选择和中断

  • Strands 实现 (Python):使用 Strands Framework-based BidiAgent 实现,通过自动会话管理和工具集成来简化实时音频对话

  • Echo 实现 (Python):用于测试 WebSocket 连接和身份验证的简单 echo 服务器