本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
交互式外壳(终端)
该InvokeAgentRuntimeCommandShell操作将在正在 AgentCore 运行的Harness会话中打开一个持久的交互式终端 WebSocket。API 使用运行时会话 ID 来标识此线束会话。与一次性命令执行不同,交互式 shell 会跨输入维护其环境变量、工作目录、命令历史记录和正在运行的进程。
当你需要在命令之间保留 shell 状态时,使用交互式 shell 进行调试、迭代开发或长时间运行的进程。
对于 Sigv4 和 SigV4 的预签名请求,调用者需要bedrock-agentcore:InvokeAgentRuntimeCommandShell获得该工具的许可。 Bearer-token 相反,请求必须满足线束入站授权者的要求。
重要
启动时, AgentCore CLI 命令和高级别 AgentCore SDK shell 助手不支持线束目标。直接通过 InvokeAgentRuntimeCommandShell WebSocket API 连接到安全带外壳,如本页所示。
工作原理
InvokeAgentRuntimeCommandShell在运行您的线束会话的 microVM 中建立与交互式 shell 进程的 WebSocket 连接。该连接使用二进制帧来双向传输终端输入和输出。
如果线束使用默认环境,则外壳将在托管线束环境中运行。如果安全带使用自定义容器,则外壳将在该容器中运行。Harness 交互式终端目前仅支持 Bash。
该连接支持:
| 功能 | 说明 |
|---|---|
|
持续状态 |
环境变量、工作目录、命令历史记录和正在运行的进程保存在同一 shell 中。 |
|
重新连接 |
提供相同的运行时会话 ID 并重新 |
|
多个并发外壳 |
在一个安全带会话中打开最多 10 个活跃的 shell 会话。分离的炮弹不计入此限制。每个 shell 都有一个独立的终端进程并共享会话文件系统。 |
先决条件
-
安全带处于
READY状态 -
所选身份验证方法的授权:Sigv4
bedrock-agentcore:InvokeAgentRuntimeCommandShell的 IAM 权限,或线束入站授权者接受的持有者令牌 -
支持二进制帧以及请求标头或预签名 URL 的 WebSocket 客户端
-
对于自定义容器,Bash 安装在。
/bin/bash目前不支持其他 shelldash,包括sh和。
有关完整工具权限模型的更多信息,请参阅来电者必需的 IAM 权限。
通过 WebSocket API 进行连接
打开 WebSocket 与以下 URL 的连接:
wss://bedrock-agentcore.<region>.amazonaws.com/runtimes/<url-encoded-harness-arn>/ws/shells
使用安全工具 ARN,而不是其托管运行时的 ARN。 URL-encode 将其放入路径之前的完整安全带 ARN。安全带 ARN 的格式如下:
arn:aws:bedrock-agentcore:<region>:<accountId>:harness/<harnessId>
在 WebSocket 升级请求中发送以下值:
| 值 | 必需 | 说明 |
|---|---|---|
|
身份验证 |
是 |
使用签名版本 4 (Sigv4) 对请求进行签名,使用 Sigv4 预签名 URL,或者在标头中发送由线束入站授权方配置的不记名令牌。 |
|
|
否 |
以现有安全带会话为目标或使用提供的 ID 创建一个。该值必须至少包含 33 个字符。如果省略它,则该服务会创建一个运行时会话 ID 并在响应中返回。 |
|
|
否 |
对于 SigV4 连接,可以选择提供标识命令行 |
|
|
否 |
重新连接到现有的外壳。将其与创建 shell 相同的运行时会话 ID 一起使用。 |
对于无法设置Authorization标头的浏览器客户端,base64url 对持有者令牌进行编码,然后同时提供两者以及哨兵。base64UrlBearerAuthorization.<encoded-token> base64UrlBearerAuthorization Sec-WebSocket-Protocol也不要在持有者令牌连接v1.command.agentcore.aws.dev上提供。
101 Switching Protocols响应会返回和X-Amzn-Bedrock-AgentCore-Shell-Id标头中的运行时会话 ID X-Amzn-Bedrock-AgentCore-Runtime-Session-Id 和外壳 ID。无法读取 WebSocket 升级响应标头的客户端可以从第一STATUS帧读取 shell ID。框架不包含运行时会话 ID,因此这些客户端在连接之前必须生成并保留运行时会话 ID。创建预签名 URL 时,请在签名 URL 之前将运行时会话 ID 作为查询参数包括在内。
WebSocket 升级超时仅在服务返回之前适用101 Switching Protocols。升级后,Shell 和自定义容器的初始化可以继续。等待初始STATUS帧后再将 shell 视为就绪,在等待时应用单独的应用程序超时,将关闭代码1011作为 shell 初始化或服务器故障处理。
以下 Python 示例使用通用 WebSocket 客户端,并且botocore仅用于签署升级请求。它不使用 AgentCore SDK 外壳助手。
pip install "boto3>=1.34" "websockets>=15"
import asyncio import json import urllib.parse import uuid import botocore.session import websockets from botocore.auth import SigV4Auth from botocore.awsrequest import AWSRequest REGION = "us-west-2" HARNESS_ARN = ( "arn:aws:bedrock-agentcore:us-west-2:123456789012:" "harness/MyHarness-a1b2c3d4e5" ) SESSION_ID = str(uuid.uuid4()) # 36 characters SUBPROTOCOL = "v1.command.agentcore.aws.dev" def signed_headers(url): request = AWSRequest( method="GET", url=url, headers={ "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id": SESSION_ID, }, ) credentials = botocore.session.Session().get_credentials() SigV4Auth(credentials, "bedrock-agentcore", REGION).add_auth(request) return dict(request.headers) async def main(): encoded_arn = urllib.parse.quote(HARNESS_ARN, safe="") host = f"bedrock-agentcore.{REGION}.amazonaws.com" path = f"/runtimes/{encoded_arn}/ws/shells" https_url = f"https://{host}{path}" websocket_url = f"wss://{host}{path}" async with websockets.connect( websocket_url, additional_headers=signed_headers(https_url), subprotocols=[SUBPROTOCOL], open_timeout=330, ) as websocket: shell_id = websocket.response.headers.get( "X-Amzn-Bedrock-AgentCore-Shell-Id" ) print(f"Connected to shell {shell_id}") # Channel 0x00 carries terminal input. await websocket.send(b"\x00echo 'Hello from my harness'\n") await websocket.send(b"\x00exit\n") async for frame in websocket: if isinstance(frame, str) or not frame: continue channel, payload = frame[0], frame[1:] if channel == 0x01: # PTY output (command stdout and stderr) print(payload.decode("utf-8", errors="replace"), end="") elif channel == 0x02: # Service or platform diagnostics print(payload.decode("utf-8", errors="replace"), end="") elif channel == 0x03: # STATUS status = json.loads(payload) shell_id = status.get("metadata", {}).get("shellId", shell_id) print(f"\nStatus: {status}") asyncio.run(main())
二进制帧协议
每条应用程序级消息都是二进制 WebSocket 帧。第一个字节标识频道,其余字节是有效载荷。
| 频道 | 方向 | 有效载荷 |
|---|---|---|
|
|
客户到服务 |
原始终端输入。 |
|
|
为客户提供服务 |
未处理的 PTY 输出。PTY 在这个频道上结合了命令 stdout 和 stderr。 |
|
|
为客户提供服务 |
服务或平台诊断。命令 stderr 是 |
|
|
为客户提供服务 |
UTF-8 包含连接元数据或外壳退出状态的 JSON。 |
|
|
客户到服务 |
UTF-8 表单中的 JSON |
|
|
两个方向 |
可选的应用程序心跳。该服务会回显有效载荷。 WebSocket 还支持 ping 帧。 |
|
|
两个方向 |
结束外壳会话。 |
文本框架不是协议的一部分。该服务会忽略孤立的文本框架,并在连续五个文本框架1003后关闭与代码的连接。
第一STATUS帧确认连接,并包含类似于以下内容的元数据:
{ "kind": "Status", "apiVersion": "v1", "metadata": { "shellId": "my-shell", "reconnected": false }, "status": "Success" }
当 shell 以非零状态退出时,最后一STATUS帧会在中包含ExitCode原因。details.causes
重新连接到外壳
存储运行时会话 ID 和外壳 ID。要重新连接,请使用相同的运行时会话 ID 标头并将 URL-encoded 外壳 ID 添加为查询参数:
wss://bedrock-agentcore.<region>.amazonaws.com/runtimes/<url-encoded-harness-arn>/ws/shells?shellId=<shell-id>
断开连接后,shell 进程将继续运行。重新连接时,该服务最多可重放 256 KB 的缓冲输出。metadata.bytesDropped如果分离的 shell 产生的输出超过了重播缓冲区所能保留的输出量,则连接STATUS帧将设置metadata.reconnected为并包含。true
打开另一个具有相同 shell ID 的连接会替换现有连接。被替换的客户端会收到关闭码4000。
常见使用案例
- 交互式调试
-
在与线束代理相同的环境中检查已安装的软件包、文件、进程和环境配置。
- 自定义环境验证
-
对于带有自定义容器的线束,请从该容器内部验证已安装的依赖项和文件系统安装情况。
- 编码代理终端访问权限
-
为需要创建文件、运行测试、检查输出和迭代的编码代理提供持久的执行环境。
- Long-running 进程
-
启动进程,与分离,稍后重新连接以检查进度或提供输入。 WebSocket
安全注意事项
重要
可以打开 Harness shell 的主体可以交互式命令访问线束会话。仅限bedrock-agentcore:InvokeAgentRuntimeCommandShell于受信任的委托人和特定的线束 ARN。
shell 可以在选定的环境或已安装的文件系统上访问客户提供的数据、文件和机密。它还可以连接到会话可以到达的网络目的地。shell 环境使用许可名单,不注入 AgentCore 平台或工作负载凭证。shell 保留在会话的隔离式 microVM 中,无法访问其他客户的工作负载。
AgentCore 将请求 ID 和连接元数据发送到 Amazon Logs 中的 harness 运行时 CloudWatch 日志组。该服务不记录终端的输入或输出。
AWS CloudTrail 记录 InvokeAgentRuntimeCommandShell API 调用,包括呼叫者身份、时间戳、源 IP 地址、已解析的运行时资源和响应状态。 CloudTrail 不记录终端输入或输出。
如需了解更多 Harness 安全指南,请参阅安全性和访问控制。
错误处理
WebSocket 升级可能会返回以下错误:
- ValidationException
-
请求参数无效。验证运行时会话 ID 是否包含至少 33 个字符,外壳 ID 是否有效,并且该功能在目标区域中可用。在请求路径中使用 URL-encoded 安全带 ARN;直接使用托管运行时 ARN 被拒绝。
- AccessDeniedException
-
来电者没有使用安全带的
bedrock-agentcore:InvokeAgentRuntimeCommandShell权限。 - ResourceNotFoundException
-
指定的安全带不存在。验证 URL 是否包含 URL-encoded 线束 ARN。
- ServiceQuotaExceededException (429)
-
最多已打开 10 个活跃炮弹。结束活动外壳或将其分离,然后重试。
- RuntimeClientError (424)
-
无法达到运行时间。
- ThrottlingException
-
该请求超出了 API 速率限制。使用指数回退进行重试。
- RetryableConflictException (409)
-
该服务正在配置或删除目标会话。使用短的指数回退重试。
连接后,以下关闭代码指示连接结束的原因:
| 代码 | 含义 | 客户操作 |
|---|---|---|
|
|
炮弹干净利落地退出。 |
视为正常终止。 |
|
|
客户端向仅限二进制协议连续发送了五个文本框架。 |
切换到二进制帧。不要以相同的行为自动重新连接。 |
|
|
由于网络故障或服务中断,连接在没有关闭帧的情况下结束。 |
使用存储的外壳 ID 重新连接。 |
|
|
一小时的连接持续时间已过期,帧速超过每秒 250 帧,或者写入缓冲区溢出。 |
在持续时间到期后重新连接。对于速率或缓冲区违规,请在重新连接之前退出。 |
|
|
帧有效载荷超过 64 KB。 |
将有效负载分成小于 64 KB 的帧,然后重新连接。 |
|
|
服务器出现意外故障。 |
使用指数回退进行重试。 |
|
|
另一台使用相同外壳 ID 连接的客户端。 |
不要自动重新连接。通知用户有另一台客户端连接到 shell。 |
最佳实践
-
为每个逻辑终端生成并保留一个唯一的 shell ID。
-
保留运行时会话 ID 和外壳 ID。这两个值都是重新连接所必需的。
-
立即读取输出,这样连接写入缓冲区就不会被填满。
-
将较大的输入分割成小于 64 KB 的二进制帧。
-
如果 shell 必须保持更长的可用时间,则在一小时连接限制之前或之后重新连接。
-
当不再需要外壳时,明确结束外壳。分离的炮弹不计入 10 个主动炮弹的上限。该服务最多保留 20 个活动和已分离的 shell 条目,并在必要时驱逐最旧的分离外壳。
-
当连接可以启动冷安全带会话时,使用至少 330 秒的升级超时。升级后,在等待初始
STATUS帧时单独应用超时。
限额和限制
| 限制 | 值 | 说明 |
|---|---|---|
|
最大帧有效载荷 |
64 KB |
较大的帧会导致代码接近尾声 |
|
帧率 |
每秒 250 帧 |
超过限制会导致代码关闭 |
|
最大连接持续时间 |
1 小时 |
使用相同的运行时会话 ID 和 shell ID 重新连接以继续。 |
|
每个安全带会话并发活动外壳 |
10 |
当 10 个 shell 处于活动状态时,新连接将被拒绝。分离的炮弹不计入此限制。 |
|
保留了活动和已分离的 shell 条目 |
20 |
达到限制后,该服务会在创建另一个 shell 之前驱逐最旧的分离外壳。 |
|
重新连接缓冲区 |
256 KB |
重新连接后重播的最大输出。 |
有关完整的服务限制,请参阅 Amazon Bedrock AgentCore 配额。