# 策展 · X (Twitter) 🔥

> 📖 本站完整內容索引（documentation index）：[llms.txt](/llms.txt)

> 作者：Larsen Cundric (@larsencc) · 平台：X (Twitter) · 日期：2026-07-14

> 原始來源：https://x.com/larsencc/status/2076744742776488351

## 中文摘要

# 我們如何利用 AWS Bedrock AgentCore 建構安全且可擴展的 Agent 基礎架構

在 Browser Use，我們在生產環境中運行數百萬個不受信任的 AI Agent，每個 Agent 都運行在一個不含任何憑證的私有微型虛擬機（micro-VM）中。所有的對外呼叫都會經過一個控制平面（control plane），且整個系統會隨著需求自動擴展或縮減。

# 架構設計

六個月前，我曾撰寫過關於我們如何沙盒化（sandbox）不受信任 Agent 的文章：使用零秘密（zero-secret）的微型虛擬機、一個持有所有憑證的控制平面，以及一套在任何地方都能運行的映像檔。這種抽象層至今仍是保護我們整個 Agent 叢集的關鍵。而底層改變的是執行環境：現在由 AWS Bedrock AgentCore 來配置並排程每個會話（session）專屬的微型虛擬機，每個虛擬機都掛載了一個與該會話綁定的持久化 `/mnt/workspace`。

![此圖展示了 Amazon Bedrock AgentCore session 的架構，說明了 MicroVM 與工作目錄及外部介面的連接關係。](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/2d37ed9a0ba50908.jpg)

<details class="chart-data"><summary>展開畫面重點</summary><div class="me-note">此圖為一個系統架構示意圖，標題為「AgentCore session」，包含以下組件與文字：
1. 虛線框內包含：
   - 「MicroVM」（藍色方塊）
   - 「/mnt/workspace」（橘色方塊）
   - 箭頭顯示 MicroVM 與 /mnt/workspace 之間有雙向連接。
2. 虛線框外右側包含：
   - 「Control plane」（藍色方塊）
   - 「Public HTTPS」（綠色方塊）
3. 虛線框右側邊緣延伸出兩個箭頭，分別指向「Control plane」與「Public HTTPS」。</div></details>

# 保護 Agent 憑證的沙盒

虛擬機位於一個私有 VPC 中，其執行角色（execution role）僅能從 ECR 拉取映像檔並將日誌寫入 CloudWatch。它無法自行存取 S3、資料庫或任何其他 AWS API。對外連線（Egress）僅允許連至控制平面以及公開的 HTTPS 服務。

虛擬機內也沒有預先寫入任何秘密資訊。執行環境只持有控制平面的 URL，其他所有資訊（如會話 token、會話 ID、單次執行旗標）皆透過每次請求的 `/invocations` 負載傳入，因此虛擬機在兩次執行之間不會保留任何敏感資料。

此外，每個會話都有其專屬的微型虛擬機，並掛載一個僅限該會話 ID 使用的 `/mnt/workspace`，確保各個會話之間無法互相存取。

# 全端原生 AWS 架構

我們的其餘技術堆疊皆為 AWS 原生（ECS、RDS、S3、IAM 等）。在 AgentCore 上運行沙盒意味著執行層也屬於同一個生態系統：

- **IAM 範疇的執行角色**：執行環境透過 IAM 角色從 ECR 拉取映像檔並將日誌寫入 CloudWatch，這與任何 ECS 任務的運作方式相同。

- **標準 VPC 網路**：執行環境位於我們的 VPC 內，並配置了專屬的安全群組。不接受任何入站連線。對外連線僅允許連至控制平面的內部 ALB（用於 LLM 代理、回呼）、ECR 與 CloudWatch 的 VPC 端點，以及用於瀏覽器 CDP URL 和預簽名 URL（presigned URL）的公開 HTTPS。

- **AgentCore 管理的會話儲存**：每個會話都會獲得一個隔離的 1 GB workspace，掛載於 `/mnt/workspace`，在停止或恢復會話時資料依然持久存在。

- **Terraform 管理**：每個環境對應一個 `aws_bedrockagentcore_agent_runtime` 資源，外加一個標準的執行角色。

- **按量計費**：沒有閒置成本。

# 你的 Agent 永遠接觸不到真實憑證

將控制平面想像成一個代理服務。沙盒本身無法直接存取外部世界，每一項請求都必須透過控制平面進行中轉。需要呼叫大型語言模型？透過控制平面。需要上傳檔案到 S3？透過控制平面。這是 Agent 與虛擬機外部進行互動的唯一途徑。

![這張架構圖展示了 Sandbox 與 LLM API 之間透過 Control plane 進行請求轉發與金鑰管理的流程。](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/62902c96a2960fc4.jpg)

<details class="chart-data"><summary>展開畫面重點</summary><div class="me-note">該圖表描述了一個 API 請求的中介處理流程，包含三個主要節點：
1. **Sandbox**：發送請求至 Control plane。
2. **Control plane**：作為中介層，接收來自 Sandbox 的請求，並將其轉發至下游。
3. **LLM API**：接收來自 Control plane 的請求並回傳結果。

文字轉錄：
- 左側節點：Sandbox
- 中間節點：Control plane
- 右側節點：LLM API
- 請求路徑（左至中）：POST /api/v4/llm/ ... + Bearer
- 回應路徑（中至左）：response (no upstream key)
- 請求路徑（中至右）：upstream + real API key
- 回應路徑（右至中）：response

重點解讀：此架構顯示了 Control plane 負責處理 API 請求的安全性與轉發。當 Sandbox 發送請求時，Control plane 會在轉發給 LLM API 之前，將請求中的憑證替換為真實的 API 金鑰（real API key），並在回傳給 Sandbox 的回應中移除上游金鑰資訊，確保敏感資訊不會洩漏回 Sandbox。</div></details>

這是一個無狀態的 FastAPI 服務。來自沙盒的每一項請求都會攜帶一個包含會話 token 的標頭（header）。控制平面會根據 token 查詢會話、驗證其是否有效，並使用真實憑證執行操作。

## LLM 代理

Agent 的 SDK 會呼叫其標準的服務供應商端點，唯一的差別在於基礎 URL 指向的是控制平面（例如 `/api/v4/llm/anthropic/v1`、`/api/v4/llm/openai/v1` 等）。控制平面會驗證會話 token，將其替換為真實的上游 API 金鑰，進行用量計費，然後轉發給服務供應商。回應也會以同樣的方式回傳，且不包含上游金鑰。

沙盒永遠不會看到真實的 API 金鑰，也不會直接與服務供應商對話，所有的成本上限與帳單計算都在中轉過程中完成。

## Agent 安全的檔案存取

每個會話在 `/mnt/workspace` 都有一個隔離的 1 GB workspace，由 AgentCore 的託管會話儲存提供支援。這是會話專屬的，在停止或恢復時資料持久存在，且其他會話無法存取。

對於 Agent 需要移入或移出的檔案（會話檔案、workspace 共享檔案、瀏覽器下載內容），沙盒從不持有 AWS 憑證。它會向控制平面請求一個該會話專屬的預簽名 URL：

1. 沙盒向控制平面請求預簽名 URL（用於上傳或下載，僅限該會話使用）。

2. 控制平面使用其自身的 S3 憑證產生該 URL。

3. 沙盒透過標準 HTTPS 使用該 URL。

Agent 在執行期間產生的檔案會在執行結束時透過控制平面同步到 S3，因此即使虛擬機被刪除，資料也不會遺失。

## 會話狀態在停止與恢復後依然存在

沙盒設計為可拋棄式的，但某些會話狀態的重建成本很高。Bcode 的 SQLite 狀態（`bcode.db`）存放在持久化的 `/mnt/workspace` 中，因此它可以在以下情況中存活：

- 閒置停止（15 分鐘閒置逾時）。

- 會話回收（最長 8 小時生命週期）。

只有在執行環境版本更新，或會話閒置超過 14 天時，資料才會被清除。在此之前，控制平面是冷啟動恢復的唯一真理來源。持久化掛載是一個快取，讓熱恢復（warm resume）變得非常快速且低成本。

# 從零到數千個併發 Agent 的擴展能力

我們的工作負載波動很大。Agent 的執行量會劇烈聚集，我們可以在短時間內從極度冷清瞬間飆升至數千個併發沙盒，隨後又降回原點。

![此圖表展示了隨時間變化的並行代理（agent）執行量，呈現出在安靜期（quiet stretches）之間出現需求（demand）急增（spike）的週期性波動特徵。](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/fdb8ceb5bcdaec1f.jpg)

<details class="chart-data"><summary>展開數據表</summary><table><thead><tr><th></th><th>起始</th><th>峰值1</th><th>中間</th><th>峰值2</th><th>結束</th></tr></thead><tbody><tr><td>Concurrent agent runs</td><td>quiet stretches (低)</td><td>spike (高)</td><td>quiet stretches (低)</td><td>spike (高)</td><td>quiet stretches (低)</td></tr></tbody></table></details>

面對這樣的曲線，固定規模的叢集並不是正確的選擇。如果你為了尖峰需求配置容量，大部分時間你都在為閒置的資源付費；如果你為了平均需求配置，在尖峰時刻就會發生流量丟失或排隊。

![相較於固定容量（Fixed fleet）會因為閒置資源而產生額外成本（paying for idle），彈性執行期（Elastic runtime (AgentCore)）的容量能緊密追隨需求波動（capacity tracks demand），有效節省成本。](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/d1c692d35116b55b.jpg)

<details class="chart-data"><summary>展開數據表（1）Fixed fleet</summary><table><thead><tr><th></th><th>起始</th><th>結束</th></tr></thead><tbody><tr><td>provisioned capacity (橘色虛線)</td><td>高水位</td><td>高水位</td></tr><tr><td>demand (藍色實線)</td><td>低水位</td><td>低水位</td></tr><tr><td>註記：paying for idle (兩線之間的陰影區域)。</td><td></td><td></td></tr></tbody></table></details><details class="chart-data"><summary>展開數據表（2）Elastic runtime (AgentCore)</summary><table><thead><tr><th></th><th>起始</th><th>峰值1</th><th>谷值</th><th>峰值2</th><th>結束</th></tr></thead><tbody><tr><td>demand (藍色實線)</td><td>低水位</td><td>高</td><td>低</td><td>高</td><td>低水位</td></tr><tr><td>capacity tracks demand (綠色虛線)</td><td>低水位（略高於需求）</td><td>高</td><td>低</td><td>高</td><td>低水位（緊密追隨需求曲線）。</td></tr></tbody></table></details>

AgentCore 將每個 Agent 會話視為一個獨立的基礎單元。會話隨需啟動、閒置時停止，且僅針對活躍的會話時間計費。容量會跟隨需求曲線變化，而不是高於需求曲線。

控制平面則獨立擴展。它運行在私有子網路的 ECS Fargate 上，位於 ALB 後方，並根據 CPU 使用率自動擴展。沙盒則透過 AgentCore 獨立擴展。每個會話都有自己的虛擬機，而 AgentCore 負責處理排程。

![此架構圖展示了系統各層級如何根據其特定的瓶頸進行獨立擴展。](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/a6449e270f29599f.jpg)

<details class="chart-data"><summary>展開畫面重點</summary><div class="me-note">該圖表描述了一個分層的系統架構，標題為「Each layer scales on its own bottleneck」（每一層都根據其自身的瓶頸進行擴展），並將系統劃分為四個主要層級：

1. **Backend（後端）**：包含多個「Backend task」，擴展方式為「auto-scale on CPU」。
2. **Control plane（控制平面）**：包含多個「CP task」，擴展方式為「auto-scale on CPU」。
3. **AgentCore sandboxes**：包含多個「session」，擴展方式為「one VM per session」（每個會話使用一個虛擬機）。
4. **External infra（外部基礎設施）**：包含「LLM API」、「S3」與「Browser」，受限於「provider limits」（供應商限制）。

圖表強調了系統架構的模組化設計，允許不同層級根據各自的負載特性（如 CPU 使用率、虛擬機實例數或外部服務配額）進行獨立的資源調度與擴展。</div></details>

# 在 AgentCore 上運行

對於好奇的開發者，以下是 AgentCore 整合的端到端實際運作方式。

會話被限制在我們自己的會話 ID 中（`runtimeSessionId = session_id`），因此 AgentCore 的會話概念與我們的是一致的。一個會話 ID 對應一個熱啟動的虛擬機、一個 workspace 和一個生命週期。

執行環境僅由兩次針對 `bedrock-agentcore` 客戶端的 `boto3` 呼叫所驅動：

```python
# 將任務派送到 Agent 會話中。
client.invoke_agent_runtime(
    agentRuntimeArn=RUNTIME_ARN,
    runtimeSessionId=session_id,
    payload=json.dumps(invocation).encode(),
    contentType="application/json",
    accept="application/json",
)

# 終止執行中的會話。
client.stop_runtime_session(
    agentRuntimeArn=RUNTIME_ARN,
    runtimeSessionId=session_id,
)
```

會話上下文（context）包含在 `/invocations` 負載中，而不是在虛擬機的環境變數中。同一個虛擬機上的兩次執行可以攜帶完全不同的上下文，且在請求返回後都不會保留。

在生產環境中有兩個重要的設定：

- 閒置逾時：15 分鐘無活動。

- 最大生命週期：8 小時。每個會話的硬性上限。

# 總結

我們在沙盒文章中所押注的抽象層依然穩固。零秘密微型虛擬機加上持有所有憑證的控制平面，這一核心架構沒有改變。改變的是執行層現在也變成了 AWS 原生服務。

對我們而言，其優勢在於：

- 彈性擴展以追蹤波動的需求曲線，無需手動調整叢集規模。

- 從頭到尾皆為 IAM、VPC、S3、CloudWatch 堆疊。關鍵路徑上少了一個陌生的概念。

- 每個會話都有一個隔離的微型虛擬機與持久化狀態，並位於不含任何憑證的私有 VPC 中。

與最初的結論相同：你的 Agent 應該不具備任何值得竊取的東西，也不需要保存任何東西。

如果你想在這種架構上運行 Browser Use Agent 而不想自行託管，我們提供的 Browser Use Cloud 服務就是為此而生。

## 標籤

Agent, 自動化, Deployment, 資安, AWS, browser-use
