

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 互動式 shell （終端機）
<a name="harness-command-shell"></a>

`InvokeAgentRuntimeCommandShell` 操作會透過 WebSocket 在執行中的 AgentCore 繫帶工作階段中開啟持久的互動式終端機。API 會使用執行期工作階段 ID 來識別此繫帶工作階段。與一次性命令執行不同，互動式 shell 會維護其環境變數、工作目錄、命令歷史記錄，以及跨輸入執行程序。

當您需要跨命令保留 shell 狀態時，請使用互動式 shell 進行偵錯、反覆開發或長時間執行的程序。

對於 SigV4 和 SigV4 預先簽署的請求，發起人需要 集合的`bedrock-agentcore:InvokeAgentRuntimeCommandShell`許可。承載字符請求必須滿足繫帶傳入授權方。

**重要**  
在啟動時，AgentCore CLI 命令和高階 AgentCore SDK shell 協助程式不支援繫帶目標。直接透過 `InvokeAgentRuntimeCommandShell` WebSocket API 連接到繫帶殼層，如本頁所示。

## 運作方式
<a name="harness-command-shell-how-it-works"></a>

 `InvokeAgentRuntimeCommandShell` 在執行繫帶工作階段的 microVM 中，建立與互動式 shell 程序的 WebSocket 連線。連線使用二進位影格以雙向串流終端機輸入和輸出。

如果繫帶使用預設環境，殼層會在受管繫帶環境中執行。如果繫帶使用自訂容器，殼層會在該容器中執行。利用互動式終端機目前僅支援 Bash。

連線支援：


| 功能 | 說明 | 
| --- | --- | 
| 持久性狀態 | 環境變數、工作目錄、命令歷史記錄和執行中的程序會保留在相同的 shell 中。 | 
| 重新連線 | 提供相同的執行期工作階段 ID 和 `shellId`，以重新連線至分離的 shell。服務會重播最多 256 KB 的緩衝輸出。 | 
| 多個並行 shell | 在一個繫帶工作階段上開啟最多 10 個作用中 Shell 工作階段。分離的殼層不會計入此限制。每個 shell 都有獨立的終端機程序，並共用工作階段檔案系統。 | 

## 先決條件
<a name="harness-command-shell-prerequisites"></a>
+ 處於 `READY` 狀態的繫帶
+ 所選身分驗證方法的授權：SigV4 `bedrock-agentcore:InvokeAgentRuntimeCommandShell` 的 IAM 許可，或安全機制傳入授權方接受的承載字符
+ 支援二進位影格和請求標頭或預先簽章 URLs WebSocket 用戶端
+ 對於自訂容器，Bash 安裝在 `/bin/bash`。`dash`目前不支援其他 Shell，包括 `sh`和 。

如需完整繫帶許可模型的詳細資訊，請參閱 [呼叫者所需的 IAM 許可](harness-security.md#harness-iam-permissions)。

## 透過 WebSocket API 連線
<a name="harness-command-shell-connect"></a>

開啟下列 URL 的 WebSocket 連線：

```
wss://bedrock-agentcore.<region>.amazonaws.com/runtimes/<url-encoded-harness-arn>/ws/shells
```

使用繫帶 ARN，而不是其受管執行期的 ARN。將完整的繫帶 ARN 放入路徑之前，先進行 URL 編碼。繫帶 ARN 的格式如下：

```
arn:aws:bedrock-agentcore:<region>:<accountId>:harness/<harnessId>
```

使用 WebSocket 升級請求傳送下列值：


| Value | 必要 | 說明 | 
| --- | --- | --- | 
| 身分驗證 | 是 | 使用 Signature 第 4 版 (SigV4) 簽署請求、使用 SigV4 預先簽署的 URL，或傳送 `Authorization`標頭中繫帶傳入授權方設定的承載字符。SigV4 服務名稱為 `bedrock-agentcore`。 | 
|  `X-Amzn-Bedrock-AgentCore-Runtime-Session-Id` 標頭或查詢參數 | 否 | 以現有的繫帶工作階段為目標，或使用提供的 ID 建立一個。值必須至少包含 33 個字元。如果您省略它，服務會建立執行期工作階段 ID，並在回應中傳回它。 | 
|  `Sec-WebSocket-Protocol`  | 否 | 對於 SigV4 連線，選擇性提供 `v1.command.agentcore.aws.dev`來識別命令殼層二進位通訊協定。Bearer-token 連線會改用此表格後所述的身分驗證子通訊協定。 | 
|  `shellId` 查詢參數 | 否 | 重新連線至現有的 shell。將其與建立 shell 的相同執行期工作階段 ID 搭配使用。 | 

對於無法設定 `Authorization` 標頭的瀏覽器用戶端，Base64url 會編碼承載字符，並透過 同時提供 `base64UrlBearerAuthorization.<encoded-token>`和 `base64UrlBearerAuthorization` sentinel`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`和 Shell ID。無法讀取 WebSocket 升級回應標頭的用戶端可以從第一個`STATUS`影格讀取 Shell ID。框架不包含執行階段工作階段 ID，因此這些用戶端必須在連線之前產生並保留執行階段工作階段 ID。當您建立預先簽章的 URL 時，請在簽署 URL 之前將執行階段工作階段 ID 納入為查詢參數。

WebSocket 升級逾時僅適用於直到服務傳回 為止`101 Switching Protocols`。Shell 和自訂容器初始化可以在升級後繼續。等待初始`STATUS`影格，再將 shell 視為就緒、在等待時套用個別的應用程式逾時，並將關閉程式碼處理`1011`為 shell 初始化或伺服器故障。

下列 Python 範例使用一般 WebSocket 用戶端，且`botocore`僅用於簽署升級請求。它不使用 AgentCore SDK shell 協助程式。

```
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())
```

## 二進位影格通訊協定
<a name="harness-command-shell-protocol"></a>

每個應用程式層級訊息都是二進位 WebSocket 框架。第一個位元組識別頻道，其餘位元組則是承載。


| Channel | Direction | 酬載 | 
| --- | --- | --- | 
|  `0x00` - STDIN | 用戶端到服務 | 原始終端機輸入。 | 
|  `0x01` - STDOUT | 用戶端的服務 | 原始 PTY 輸出。PTY 在此頻道上結合命令 stdout 和 stderr。 | 
|  `0x02` - STDERR | 用戶端的服務 | 服務或平台診斷。Command stderr 是 `0x01` PTY 輸出的一部分。 | 
|  `0x03` - 狀態 | 用戶端的服務 | 包含連線中繼資料或 Shell 結束狀態的 UTF-8 JSON。 | 
|  `0x04` - RESIZE | 用戶端到服務 | UTF-8 JSON，格式為 `{"width":120,"height":40}`。每個維度必須介於 1 到 1，000 之間。 | 
|  `0x05` - HEARTBEAT | 兩個方向 | 選用的應用程式活動訊號。服務會回應承載。也支援 WebSocket ping 影格。 | 
|  `0xFF` - 關閉 | 兩個方向 | 結束 shell 工作階段。 | 

文字影格不屬於通訊協定。此服務會忽略隔離的文字影格，並在連續五個文字影格`1003`後關閉與程式碼的連線。

第一個`STATUS`影格會確認連線，並包含類似以下的中繼資料：

```
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    "shellId": "my-shell",
    "reconnected": false
  },
  "status": "Success"
}
```

當 Shell 以非零狀態結束時，最終`STATUS`影格會在 中包含`ExitCode`原因`details.causes`。

## 重新連線至 shell
<a name="harness-command-shell-reconnect"></a>

同時存放執行階段工作階段 ID 和 shell ID。若要重新連線，請使用相同的執行階段工作階段 ID 標頭，並將 URL 編碼的 Shell ID 新增為查詢參數：

```
wss://bedrock-agentcore.<region>.amazonaws.com/runtimes/<url-encoded-harness-arn>/ws/shells?shellId=<shell-id>
```

shell 程序會在連線分離時繼續執行。重新連線時，服務會重播最多 256 KB 的緩衝輸出。如果分離`metadata.bytesDropped`的殼層產生的輸出超過重播緩衝區可以保留的輸出，則連線`STATUS`框架會`metadata.reconnected`設定為 `true`並包含 。

使用相同的 Shell ID 開啟另一個連線會取代現有的連線。取代的用戶端會收到關閉碼 `4000`。

## 常用案例
<a name="harness-command-shell-use-cases"></a>

互動式偵錯  
檢查已安裝的套件、檔案、程序和環境組態，這些套件、檔案、程序和環境組態都位於與 harness 代理程式相同的環境中。

自訂環境驗證  
對於具有自訂容器的繫帶，請從該容器內部驗證已安裝的相依性和檔案系統掛載。

編碼代理程式終端機存取  
提供持久性執行環境，用於編碼需要建立檔案、執行測試、檢查輸出和反覆運算的代理程式。

長時間執行的程序  
啟動程序、從 WebSocket 分離，然後稍後重新連線以檢查進度或提供輸入。

## 安全考量
<a name="harness-command-shell-security"></a>

**重要**  
可以開啟 Harness shell 的委託人具有繫帶工作階段的互動式命令存取權。僅限於`bedrock-agentcore:InvokeAgentRuntimeCommandShell`信任的委託人和特定的集合 ARNs。

shell 可以在選取的環境或掛載的檔案系統上存取客戶提供的資料、檔案和秘密。它也可以連接到工作階段可以到達的網路目的地。shell 環境使用允許清單，不會插入 AgentCore 平台或工作負載登入資料。shell 會保留在工作階段隔離的 microVM 中，且無法存取其他客戶的工作負載。

AgentCore 會將請求 ID 和連線中繼資料傳送至 Amazon CloudWatch Logs 中的 harness Runtime 日誌群組。服務不會記錄終端機輸入或輸出。

 AWS CloudTrail 會記錄 `InvokeAgentRuntimeCommandShell` API 呼叫，包括呼叫者身分、時間戳記、來源 IP 地址、已解析的執行時間資源和回應狀態。CloudTrail 不會記錄終端機輸入或輸出。

如需更多利用安全指引，請參閱 [安全性和存取控制](harness-security.md)。

## 錯誤處理
<a name="harness-command-shell-errors"></a>

WebSocket 升級可能會傳回下列錯誤：

 **ValidationException**   
請求參數無效。確認執行階段工作階段 ID 至少包含 33 個字元、殼層 ID 有效，且功能可在目標區域中使用。在請求路徑中使用 URL 編碼的繫帶 ARN；直接使用受管執行期 ARN 會遭到拒絕。

 **AccessDeniedException**   
發起人沒有 集合的`bedrock-agentcore:InvokeAgentRuntimeCommandShell`許可。

 **ResourceNotFoundException**   
指定的繫帶不存在。確認 URL 包含 URL 編碼的繫帶 ARN。

 **ServiceQuotaExceededException (429)**   
最多 10 個作用中 Shell 已開啟。結束作用中 shell 或將其分離，然後重試。

 **RuntimeClientError (424)**   
無法達到執行時間。

 **ThrottlingException**   
請求超過 API 速率限制。以指數退避重試。

 **RetryableConflictException (409)**   
服務正在佈建或銷毀目標工作階段。以短指數退避重試。

連線後，以下關閉代碼會指出連線結束的原因：


| Code | 意義 | 用戶端動作 | 
| --- | --- | --- | 
|  `1000`  | shell 已順利退出。 | 視為正常終止。 | 
|  `1003`  | 用戶端將五個連續的文字影格傳送至僅限二進位的通訊協定。 | 切換到二進位影格。不要自動重新連線相同的行為。 | 
|  `1006`  | 由於網路故障或服務中斷，連線在沒有關閉影格的情況下結束。 | 使用儲存的 Shell ID 重新連線。 | 
|  `1008`  | 一小時連線持續時間已過期、影格率超過每秒 250 個影格，或寫入緩衝區溢位。 | 重新連線持續時間到期。對於速率或緩衝區違規，請在重新連線之前關閉。 | 
|  `1009`  | 框架承載超過 64 KB。 | 將承載分割為小於 64 KB 的影格，然後重新連線。 | 
|  `1011`  | 發生非預期的伺服器故障。 | 以指數退避重試。 | 
|  `4000`  | 使用相同 shell ID 連線的另一個用戶端。 | 不要自動重新連線。通知使用者另一個用戶端連接到 shell。 | 

## 最佳實務
<a name="harness-command-shell-best-practices"></a>
+ 為每個邏輯終端機產生並保留唯一的 Shell ID。
+ 使用 Shell ID 保留執行階段工作階段 ID。需要這兩個值才能重新連線。
+ 立即讀取輸出，讓連線寫入緩衝區不會填滿。
+ 將大型輸入分割為小於 64 KB 的二進位影格。
+ 如果 shell 必須保留更長的可用時間，請在一小時連線限制之前或之後重新連線。
+ 不再需要 shell 時，明確結束 shell。分離的殼層不會計入 10-active-shell 限制。此服務會保留最多 20 個作用中和分離的 shell 項目，並在必要時移出最舊的分離 shell。
+ 當連線可以啟動冷繫帶工作階段時，請使用至少 330 秒的升級逾時。在升級後等待初始`STATUS`影格時套用個別的逾時。

## 配額和限制
<a name="harness-command-shell-limits"></a>


| 限制 | Value | 說明 | 
| --- | --- | --- | 
| 影格承載上限 | 64 KB | 較大的影格會導致關閉程式碼 `1009`。 | 
| 影格播放速率 | 每秒 250 個影格 | 超過限制會導致關閉程式碼 `1008`。 | 
| 連線持續時間上限 | 1 小時 | 使用相同的執行階段工作階段 ID 和 Shell ID 重新連線以繼續。 | 
| 每個集合工作階段的並行作用中 Shell | 10 | 當 10 個 Shell 處於作用中狀態時，會拒絕新的連線。分離的殼層不會計入此限制。 | 
| 保留的作用中和分離的 shell 項目 | 20 | 達到限制時，服務會先移出最舊的分離殼層，再建立另一個殼層。 | 
| 重新連線緩衝區 | 256 KB | 重新連線後重新播放的最大輸出。 | 

如需完整的服務限制，請參閱 [Amazon Bedrock AgentCore 的配額](bedrock-agentcore-limits.md)。

## 相關主題
<a name="_related_topics"></a>
+  [環境和檔案系統](harness-environment.md) - 設定預設環境或自訂容器
+  [安全性和存取控制](harness-security.md) - 控制對繫帶及其執行環境的存取
+  [可觀測性和成本控制](harness-operations.md) - 監控 Harness 活動和成本
+  [AgentCore 執行期的互動式 Shell](runtime-get-started-command-shell.md) 