☁️ AgentCore
與 Nova Act 研究
🏗 平台選擇
🎯 什麼情境該想到我
當你「agent 要從 demo 走到正式環境,得決定是在自己的 K8s 上組一套,還是買雲端的代管平台(例如 AWS Bedrock AgentCore)」的時候。
⚙️ 怎麼用(步驟 / 公式)
1. 先認清難點不在 agent loop
開源框架(LangGraph、Strands、Claude Agent SDK)已經把「模型決定下一步 → 呼叫工具 → 看結果」的迴圈寫好了。自建真正難的是三件事,也是代管平台最值錢的地方:
| 難點 | 為什麼難 |
|---|---|
| ① 每個 session 的強隔離 | agent 可能執行它自己產生的程式碼。一般 container 共用 kernel,隔離不夠;要做到「每個 session 一台 microVM(Firecracker/gVisor/Kata)、用完即清、能縮到 0」得自己寫排程器 |
| ② 代替每位使用者保管第三方 OAuth token | 每家 SaaS 的 OAuth 細節都不同;token 要加密保存、自動刷新、撤銷,還要處理「agent 代替這位使用者行事」的授權鏈(見 工具-agent代使用者存取的身分設計) |
| ③ 長期記憶的萃取 | 什麼時候萃取、怎麼合併去重、新舊衝突怎麼辦、怎麼依使用者隔離,全部要自己設計,萃取本身還要花 token |
其餘元件(hosting、短期記憶、inbound 驗證、可觀測性)用現成方案接上就好,難度低。
2. 評估綁定程度:按「離開的代價」排序
以 AgentCore 為例(依原研究,查證 2026-09-30):
| 元件 | 離開代價 | 原因 |
|---|---|---|
| 模型、Runtime、Observability、Policy | 低 | 模型不綁廠商;Runtime 契約就是一般 HTTP container(POST /invocations、GET /ping);OTel;Cedar 是開源語言 |
| Harness(設定式 agent) | 中低 | 可 export 成 Python 程式碼,單向 |
| Gateway、Identity | 中 | agent 端是標準 MCP/OAuth,但 proxy 設定與 token vault 要重建;vault 裡的使用者 token 能否匯出,文件沒寫(推論:使用者要重新授權) |
| Memory | 中高 | 原始資料可以匯出,但萃取與檢索的行為帶不走,換方案後 agent「記事情的方式」會變 |
★ 真正黏的只有記憶層(Memory),其次是 Identity 的 token vault。很在意綁定的話,只把記憶層自建,其他用代管。
3. 成本的形狀(判斷,無實測數據)
- 代管平台多半按「實際用量」計費,等待 I/O 的時間不收 CPU 費用。agent 大部分時間都在等模型回應,正好吃到這個優勢;沒流量時費用趨近 0。
- 自建是「固定成本+人力」:叢集常駐、要有人值班、要追每季都在變的標準(MCP、A2A)。
- 流量高且穩定時自建才可能較便宜;但人力通常才是主要差距:光 ① 和 ② 兩項就是以「人月」計的工作量。
4. 決策表
| 情境 | 建議 |
|---|---|
| 資料必須留在特定地區,而平台在那裡沒有區域(例如 AgentCore 沒有台灣區) | 硬限制:自建或找當地雲 |
| 多雲、地端是硬需求 | 自建,或只把代管用在該雲那一側 |
| 已有成熟 K8s 平台團隊,且 agent 不執行不受信任的程式碼 | hosting 自建;只買 Identity 或程式碼沙箱 |
| 流量極高又穩定、成本優先 | 先評估平台的自帶機器方案(AgentCore Runtime Instances:用自己的 EC2,加 12% 管理費);還不划算才自建 |
| 以上都不是 | 用代管,從最簡單的設定式 agent 開始 |
5. 混合策略
- 全部代管,只有記憶層自建:降低最大的綁定點。
- agent 跑在自己的 EKS,只買最難的:outbound OAuth、程式碼/瀏覽器沙箱、工具治理(Gateway+Policy)。
- 先全部代管快速上線,把「export 成程式碼」當退場路線,規模起來再逐個替換。
6. 設定式 vs 程式碼式:什麼時候「畢業」
代管平台常分兩層:設定式(AgentCore 叫 Harness,改設定不用重新部署,換模型與 prompt 的實驗成本趨近零)與程式碼式(Runtime,自己寫 agent loop)。只有一種需求逼你畢業:要改變 agent loop 本身:
- 指定其他框架、graph/workflow 式編排、複雜多 agent 路由
- 在迴圈中改寫訊息或工具輸入(Harness 的 hook 只能 allow/deny,不能改內容)
- 不同階段用不同 prompt、雙向串流(即時語音)
其他客製需求(人工核准、內網 API、固定前後處理腳本、特殊工具鏈)通常都有逃生口,先別急著畢業。先用設定式找出模型×prompt 的組合,確定要掌控迴圈時再 export;export 之後,prompt 實驗就回到「改程式、重新部署」的循環。
機制細節 → AgentCore 總覽與Harness vs Runtime
🧪 我實際套用的紀錄
- 2026-09-30:AgentCore 研究的結論。這是官方文件加上工程判斷,自建端的難度沒有實際做過。
⚠️ 注意 / 什麼時候不適用
- 表中「自建難度」是工程判斷,會隨團隊能力大幅變動:有現成 microVM 平台的團隊,① 就不難。
- 代管平台的預設值要逐項檢查。例如 AgentCore Harness 用 API 建立時預設開啟代管記憶(持續計費)、
maxTokens預設無上限、內建 shell 工具每次呼叫多吃約 900 input token。 - 「按用量計費比較便宜」只對流量不穩定的工作負載成立(原研究判斷,無實際數據);穩定高流量要實算。
- 平台的區域、價格、配額變動很快,決策前重新查證。
🔗 相關工具
- AgentCore 總覽與Harness vs Runtime —— AgentCore 各元件與兩種部署模式的完整說明
- 工具-agent代使用者存取的身分設計 —— 難點 ② 的設計
- 工具-AI-Agent設計 —— agent 本身怎麼設計;這張卡管的是「跑在哪」
🔐 身分、入口與授權
🎯 什麼情境該想到我
當你「的 agent 要代表某位使用者去呼叫下游服務(內部 API、使用者的行事曆或 Slack),得決定用什麼身分、帶哪張 token」的時候。
⚙️ 怎麼用(步驟 / 公式)
1. 先分清三種 outbound 模式
| 模式 | OAuth 流程 | 適合 |
|---|---|---|
| 自主(M2M/2LO) | client credentials | agent 以自己的身分存取系統資源(查公司內部 API) |
| 使用者授權(3LO) | authorization code | 要使用者本人同意才能碰他的資料(他的 Google 行事曆) |
| 代理換發(OBO) | token exchange(RFC 8693)或 JWT bearer(RFC 7523) | 使用者已登入你的系統,不再詢問同意,換一張只給下游用的新 token |
2. 不要直接轉傳使用者的 token
| 直接轉傳 | OBO | |
|---|---|---|
| audience | 前端 app(下游其實不該接受) | 下游自己 |
| scope | 前端要的所有權限 | 只有下游需要的 |
| 下游知不知道是 agent 在操作 | 不知道 | 知道 |
| 外洩的影響 | 可冒充使用者呼叫所有接受這張 token 的服務 | 只能呼叫那一個下游 |
| 撤銷 | 只能撤掉使用者整個登入 | 可只撤 agent 的權限(依 IdP) |
★ 直接轉傳之所以「能動」,通常是因為下游根本沒檢查 audience,這本身就是漏洞。
3. OBO 的每一層:audience 只寫自己、scope 一路縮小
以「客服 agent 代使用者查訂單」為例:使用者 →(1) agent →(2) 工具閘道 →(3) 內部訂單 API
| 段 | aud | scope | 誰驗證 |
|---|---|---|---|
| (1) 使用者登入的 token | agent 的 app ID | agent.invoke | agent 的 JWT 驗證 |
| (2) 第一次換發 | 閘道的 app ID | tools.invoke | 閘道 inbound 驗證 |
| (3) 第二次換發 | 訂單 API 的 app ID | orders.read | 訂單 API 自己 |
- 每一層都要在 IdP 註冊成獨立的 app(resource server),才能當換發對象。
- 最後一段最重要:真正存取資料的 API 必須同時驗使用者與 agent,才做得到「本人可以改訂單,透過 agent 只能查」:
claims = verify_jwt(token, issuer=ISSUER, audience="api://orders") # 簽章、到期、aud
user = claims["sub"]
agent = claims.get("xms_act", {}).get("sub") # Entra 的寫法;claim 名稱依 IdP 而定
if agent is not None and request.method != "GET":
deny() # 透過 agent 只能查- 「agent 是誰」放在哪個 claim 由 IdP 決定,不是 RFC 8693 標準的
act。例如 Entra 把使用者放sub、中間層放xms_act.sub。換 IdP 就要改驗證碼。
4. 看你的 IdP 支不支援(依原研究,查證 2026-09-30)
- Entra ID:最成熟(
JWT_AUTHORIZATION_GRANT,自動帶requested_token_use=on_behalf_of)。常見錯誤AADSTS500131:使用者 token 的aud不是 agent app,登入 scope 要用<AGENT_CLIENT_ID>/.default。 - Okta:支援 token exchange,要多帶
audience;預設不發client_idclaim。 - Cognito:token 端點不支援 token exchange。實際做法:閘道用 service role 或 M2M 呼叫下游,使用者身分用 header 傳遞,並靠「只有閘道能呼叫下游」保證 header 可信(見 工具-讓Gateway當agent唯一入口)。這不是真正的 OBO,但好維護。
- 能用私鑰簽章(
PRIVATE_KEY_JWT)或雲端 IAM 簽發的 JWT 當 client 驗證,就不要用 client secret,少一個要輪替的機密。
5. 3LO:使用者同意流程的重點
- 有兩個 callback,別搞混:第三方(Google、Slack)後台註冊的是平台的 callback(平台用授權碼換 token);你自己的 callback 要自己實作,負責確認「按下同意的人」是誰,再通知平台完成(AgentCore 是
CompleteResourceTokenAuth)。 - session binding 只有一句話:callback 裡的使用者身分,只能從瀏覽器自己的登入 session(cookie)取得,不能從 query string 或遠端快取拿。否則攻擊者把授權連結丟給受害者,就能讓平台誤以為同意的人就是發起者,受害者的第三方授權因此綁到攻擊者身上(後半句為推論)。
- 補強做法:發出授權連結時記下「這個連結是給誰的」、一次性使用、10 分鐘過期;兩邊一致才完成。原研究的本機測試:沒登入 400、別人拿到連結 403、重放 400、過期 400。
- 授權 URL 怎麼送到前端:SDK 預設會卡住工具呼叫、每 5 秒輪詢、最多 10 分鐘。對話型應用通常更適合「中斷這一輪 → 把 URL 推給前端 → 授權完再重來」。
- 一定要開 refresh token(Google 帶
access_type=offline、Microsoft 加offline_access…),不然 access token 1–2 小時一過期就要重新授權。 - 使用者在第三方撤銷授權,平台偵測不到,會照樣回舊 token。在工具層包一層:呼叫第三方收到 401 → 強制重新授權(AgentCore 的
forceAuthentication=true)→ 送出新的授權 URL,不要讓模型自己對著 401 重試。
6. 多租戶的 token 保管
- credential provider 不是租戶單位:正常設計是每個第三方服務一個 provider(
google、slack),由 vault 依「agent+使用者」分開存每個人的 token。AgentCore 預設每帳號每區域各 50 個 provider(可調高)。 - 租戶隔離靠使用者 ID 命名(例如
tenantA+user123)加 IAM 條件(資源 ARN、aws:ResourceTag做 ABAC)。命名錯了就會拿到別人的 token,這是共用模型的主要風險。 - 企業客戶要求自帶 IdP/OAuth app → 為他們建專屬 provider。需要租戶各自一把 KMS 金鑰或完全隔離 → 分帳號(AgentCore 每帳號每區域只有一個 vault、一把 vault 金鑰)。
- 稽核「誰替誰拿了哪張 token」:CloudTrail 裡的 workload token 被遮蔽,看不到終端使用者,要靠 trace span 或串接其他事件還原。
機制細節 → AgentCore Identity
🧪 我實際套用的紀錄
- 2026-09-30:原研究的 3LO callback 做過本機實驗;OBO 設計沒有實際部署驗證,是依官方文件與範例推導。
⚠️ 注意 / 什麼時候不適用
- 下游一定要驗
aud,這是 OBO 安全性的來源;不驗的話,做了 OBO 也沒用。 - 只需要 agent 自己的身分(例如查公共資料、內部報表)時,用 M2M 就好,不必上 OBO。
- AgentCore 的 IAM ARN 格式文件前後不一致(
oauth2-credential-providervsoauth2credentialprovider)。寫錯格式不會報錯,只是靜默地不符合,一律以 IAM service reference 為準。 - 禁止「呼叫端自己指定要代表哪個使用者」(AgentCore 的
ForUserId類 API)要在兩處都 Deny;只 Deny agent 的 execution role 可能無效(推論:平台是透過 service-linked role 取 token)。
🔗 相關工具
- AgentCore Identity —— 三種模式的 API、3LO 參考實作、多租戶配額的完整說明
- 工具-讓Gateway當agent唯一入口 —— 身分鏈要成立,前提是沒人能繞過閘道
🎯 什麼情境該想到我
當你「在 agent 前面放了閘道做驗證、限流、授權規則,卻不確定有沒有人能繞過它直接呼叫後面的 agent」的時候。
⚙️ 怎麼用(步驟 / 公式)
核心:閘道上的所有控制(授權規則、限流、攔截器、guardrail)只對經過閘道的流量有效。只要使用者能直接呼叫 agent 執行環境,這些控制全部可以繞過。所以「加閘道」只做了一半,另一半是鎖死後門。
1. 架構
使用者/前端
│ JWT(inbound 驗證:audience、scope)
▼
Gateway ─ 限流(以使用者 sub 為維度)→ 攔截器 → 授權規則 → 路由
│ outbound:閘道自己的 service role(或 OAuth)
▼
Agent Runtime(只接受這個閘道的請求)
以 AgentCore 為例:把 Runtime 用 HTTP target 接到 Gateway 後面。這種 target 只能加到沒設定 protocol type 的 gateway,MCP 型的不行,所以要規劃兩個 gateway,或一開始就不設。原本呼叫 Runtime 的 client 只要換 endpoint。
2. 鎖住後門:依執行環境的驗證方式
- IAM 型:resource-based policy 只 Allow 閘道的 execution role,再加一條明確的 Deny 給其他所有 principal。只寫 Allow 的話,帳號內其他有呼叫權限的角色照樣能直接打。閘道 role 的 trust policy 也要用
aws:SourceArn鎖住:能 assume 這個 role 的人就能直接呼叫。 - JWT 型:在執行環境的 JWT 驗證加上「只接受身分鏈裡有指定閘道的請求」(AgentCore 的
allowedWorkloadConfiguration)。這樣使用者拿同一張有效的 JWT 直接打,也會被拒。- 陷阱:AgentCore CLI 不會設這個欄位;
UpdateAgentRuntime會整個取代設定,要「讀出 → 合併 → 寫回」,否則其他設定被清掉。
- 陷阱:AgentCore CLI 不會設這個欄位;
- 網路層(PrivateLink、VPC endpoint policy)只是補充,同一個 VPC 裡的其他服務仍能繞過;主要防線是上面的身分層。
3. 各種控制放哪一層
| 控制 | 放哪 | 不該拿來做 |
|---|---|---|
| inbound 驗證 | 閘道 | — |
| 授權規則(見 工具-把業務規則從prompt搬到授權層) | 閘道 | — |
| 攔截器(Lambda) | 閘道:格式轉換、補 header、遮罩 | 當主要授權機制 |
| 限流 | 閘道:流量管理、防單一使用者用光額度 | 安全控制(它是 fail-open 的) |
| 路由、canary、A/B | 閘道 | — |
| payload 驗證 | 執行環境 | — |
4. 使用者身分怎麼傳到後面
outbound 用閘道自己的 service role 時,後面看到的是閘道的身分。需要使用者身分,就用 REQUEST 攔截器把 JWT 的 sub 放進 header,並加進執行環境的 header allowlist。這個 header 可信的前提是「只有閘道能呼叫」,所以第 2 步不能省(推論:官方沒有這個情境的完整範例)。要真正代表使用者呼叫下游,改用 OBO(見 工具-agent代使用者存取的身分設計)。
5. 限流的兩個坑
- 維度用
$.context.jwt.sub做到每位使用者每分鐘 N 次;維度建立後不能改。 - fail-open:JWT 缺少當維度的 claim 時,整條限制被略過。要搭配 inbound 驗證的「必須有某 claim」條件。
6. 部署檢查清單
- 建沒設 protocol type 的 gateway;inbound 用 JWT 驗 audience 與 scope。
- 加執行環境的 target,outbound 用 service role。
- 鎖後門:IAM 型用 Allow+Deny 並鎖 trust policy;JWT 型用身分鏈白名單(讀、合併、寫回)。
- 設限流並確保維度 claim 一定存在。
- ★ 驗證繞不過去:用同一張 JWT(或同一個 IAM 身分)直接呼叫執行環境必須被拒,經過閘道則成功。這步最常被跳過,卻是整套設計的目的。
- client 換成閘道的 URL。
機制細節 → AgentCore Gateway
🧪 我實際套用的紀錄
- 2026-09-30:原研究依官方文件與範例推導,沒有實際部署驗證。
⚠️ 注意 / 什麼時候不適用
- 官方的「快速導入」組合,inbound 都不做授權(IAM 的
AUTHENTICATE_ONLY+呼叫者 IAM;JWT 的NONE+token 直通)。它們只是把流量先導進閘道,只適合過渡期。 - token 直通(passthrough)官方不建議用於正式環境;要代表使用者就走 OBO。AgentCore 文件寫 Runtime target 不支援 OBO,但官方範例用了,要實測。
- AgentCore 的攔截器不支援串流:SSE 回應不能用 RESPONSE 攔截器加工;Lambda 可能被重試,要做成冪等;同步呼叫有 6 MB 上限。
- 限流排在路由規則之前評估;攔截器與授權規則誰先,文件沒寫。
- 內部服務之間的呼叫全程用 IAM 最簡單,不一定需要這整套。
🔗 相關工具
- AgentCore Gateway —— target 類型、工具語意搜尋、LLM 代理等完整機制
- 工具-agent代使用者存取的身分設計 —— 閘道之後要代表使用者呼叫下游時
- 工具-把業務規則從prompt搬到授權層 —— 閘道上該放的授權規則怎麼寫
- 工具-限流器設計 —— 限流演算法本身;這張卡只管它放在哪、怎麼避免 fail-open
🎯 什麼情境該想到我
當你「把『退款不能超過 500 美元』『只能處理本人訂單』這類規則寫在 system prompt,卻沒辦法保證模型每次都照做」的時候。
⚙️ 怎麼用(步驟 / 公式)
為什麼不能只靠 prompt
| 做法 | 問題 |
|---|---|
| 寫在 system prompt | 模型是機率性的,不保證遵守;惡意輸入能誘導它違反 |
| 每個工具的後端各自檢查 | 規則散在各服務,難以一致、難以稽核;後端也不一定知道「哪個使用者透過哪個 agent」在呼叫 |
| 在工具呼叫的必經之路上做確定性授權 | 單一檢查點、宣告式、可驗證、可版本控管,跟模型行為完全無關 |
類比:IAM policy 之於 AWS API,就是授權層之於 agent 的工具呼叫。AgentCore 的實作是 Gateway+Cedar;自建可以在工具 proxy 前放 OPA 或 Cedar 開源引擎。
第 1 步:逐句分類 prompt 裡的規則
判準只有一條:模型不照做時,後果能不能接受?
| prompt 裡的句子 | 不照做的後果 | 放哪裡 |
|---|---|---|
| 單筆退款不能超過 500 美元,主管可到 5,000 | 直接損失金錢 | 授權層(數值比較+角色) |
| 只能處理使用者本人的訂單 | 越權存取 | 授權層(customerId 比對呼叫者) |
| 只服務美國和加拿大 | 違反法規或合約 | 授權層 |
| 退款一定要記錄原因 | 稽核缺漏 | 授權層,或直接把 schema 欄位設成必填 |
| 退款前先查訂單狀態 | 重複退款 | 需要「看歷史」的時序規則(AgentCore 叫 temporal policy) |
| 回覆裡不要透露其他客戶資料 | 個資外洩 | 根本做法是工具就不回傳別人的資料;輸出過濾只是補強 |
| 回答要禮貌、用繁體中文 | 體驗不佳 | 留在 prompt |
★ 搬過去之後,prompt 裡的規則照樣保留:prompt 讓模型「一開始就不會去做」,減少被擋後的亂重試;授權層保證「真的做了也會被擋」。沒寫在 prompt 的話,模型被拒後可能一直換參數重試(原研究推論)。
第 2 步:確認規則「看得到」需要的欄位
授權層只看得到工具呼叫的參數與呼叫者身分,看不到對話內容,也不會自己去查資料庫。所以很多規則搬不過去,問題不在 policy 語言,而在工具設計。為 policy 設計工具 schema:
- 金額用整數的「分」(
amountCents: integer),不要用浮點數:Cedar 的 decimal 會截到小數點後 4 位,時序加總也只能加整數。 - 資料歸屬要是明確欄位(
customerId),才能比對「這是不是呼叫者的」。後端 API 自己最好也再驗一次。 - 會被 policy 引用的欄位設成必填,不然每條規則都得先寫
has檢查,漏寫就出事。 - 避開
anyOf/oneOf、自由格式物件;被引用的欄位先別用enum(開源 schema 轉換器會把它轉成列舉 entity,不是字串)。 - 一個工具只做一件事:
manage_order(action: refund|cancel|query)拆成三個工具,規則才能直接用工具名區分。 - 「角色」「負責哪些客戶」要嘛放進 JWT claim,要嘛放進工具參數。
第 3 步:寫成 policy
// 一般使用者:上限 500 美元、只限美加、一定要有原因
permit (principal is AgentCore::OAuthUser,
action == AgentCore::Action::"OrderTarget___process_refund",
resource == AgentCore::Gateway::"<gateway ARN>")
when { context.input.amountCents <= 50000 &&
["US", "CA"].contains(context.input.country) &&
context.input has reason };
// 只能退自己的訂單,主管例外;forbid 永遠優先
forbid (principal is AgentCore::OAuthUser,
action == AgentCore::Action::"OrderTarget___process_refund",
resource == AgentCore::Gateway::"<gateway ARN>")
when { context.input.customerId != principal.id }
unless { principal.hasTag("role") && principal.getTag("role") == "supervisor" };- 「允許什麼」用
permit,「絕對不行」用forbid。Cedar 預設拒絕,forbid永遠優先,之後有人加了過寬的permit也繞不過它。 - 讀 tag 前先
hasTag、讀非必填欄位前先has;每個工具都要有permit,漏寫的會全被擋。
第 4 步:本機先驗證,別等部署
- 雲端建立 policy 的驗證常是非同步的,而且有些錯(引用了請求沒帶的欄位)建立時不報錯,到執行時才一律拒絕。
- 用開源 Cedar(例如 Python 的
cedarpy)加一份近似的 schema,在 CI 裡跑兩件事:schema 驗證、授權案例測試(「誰、帶什麼參數、預期允許或拒絕」)。原研究的實驗 10 個案例全過,而且本機 validator 直接抓到「沒先has就讀非必填欄位」的錯。 - 上線順序:本機測試 → 部署 → 只記錄不攔截(LOG_ONLY) 對照正式流量 → 切到強制執行。
機制細節 → AgentCore Policy
🧪 我實際套用的紀錄
- 2026-09-30:原研究的本機實驗(
cedarpy4.12.1)。正確的 policy 驗證通過;故意寫錯的那份被 validator 擋下(unable to guarantee safety of access to optional attribute);10 個授權案例全數符合預期。
⚠️ 注意 / 什麼時候不適用
- 本機 schema 是手寫近似版,跟平台從工具 schema 自動產生的可能有差(
enum、巢狀物件)。CI 測邏輯,上線前還是要用只記錄模式對照。 - policy 看不到對話內容:「不要透露某資訊」這類輸出規則,授權層只能部分處理,根本解法在工具的回傳設計。
- 誰能關掉 policy 也要算進攻擊面:AgentCore 裡有
UpdatePolicy權限的人能把單條 policy 改成只記錄不攔截。 - AgentCore 的 policy 沒有版本管理(
UpdatePolicy直接覆蓋),版本要靠自己的 Git。 - 風格、語氣、行為引導類規則留在 prompt,硬擋只會讓體驗變差。
🔗 相關工具
- AgentCore Policy —— Cedar/時序規則/Guardrails 的完整機制與配額
- 可逆性、審計與人類把關 —— 高風險動作的分級:授權層擋「不該做的」,把關流程處理「要人確認的」
- 工具集設計 —— 工具 schema 設計的通用規則,這張卡補上「為授權而設計」的角度
- 提示注入與分層防禦 —— prompt 會被注入攻破,正是要把規則搬出 prompt 的原因
🧪 品質
🎯 什麼情境該想到我
當你「改了 prompt、換了模型或工具,想在 CI 擋住 agent 退化,卻發現同樣的輸入每次輸出都不一樣」的時候。
⚙️ 怎麼用(步驟 / 公式)
核心:agent 跟傳統軟體最大的差別是同樣的輸入,輸出不固定。所以金字塔越底層越要用確定性的檢查,把 LLM 評審留給確定性方法判斷不了的部分(回答品質)。
1. 五層分工
| 層 | 測什麼 | 用什麼 | 頻率 |
|---|---|---|---|
| 單元測試 | 工具的商業邏輯、prompt 組裝、schema 驗證 | pytest/jest,不呼叫模型 | 每次 commit |
| 確定性 agent 測試 | 有沒有呼叫該呼叫的工具、有沒有呼叫禁止的工具、格式、個資 | 題庫+軌跡比對+程式寫的評估器 | 每次 PR |
| 品質回歸 | 正不正確、有沒有幫助、有沒有捏造 | 題庫+LLM 評審(附標準答案或斷言) | 合併主線、換 prompt/模型時 |
| 情境擴展 | 多輪、使用者不照劇本走 | LLM 扮演使用者(simulation) | 上線前、每週 |
| 正式監控 | 品質趨勢、找低分 session | 線上抽樣評估 | 持續,不擋部署 |
★ 軌跡比對是投報率最高的一層:不花 token、結果確定,而且抓得到 agent 最常見的退化,也就是「該查資料卻沒查」「多叫了不該叫的工具」。
2. 軌跡比對:三種嚴格度
預期 [calculator, weather] 時:
| 模式 | 規則 | 例 |
|---|---|---|
| 完全一致(Exact) | 工具與順序都一樣,不能多 | [calculator, weather, calculator] ✗ |
| 依序出現(InOrder) | 依序出現即可,中間可夾別的 | [calculator, search, weather] ✓ |
| 都出現(AnyOrder) | 順序不拘 | [weather, calculator] ✓ |
- 預設用 InOrder。Exact 太嚴,模型多查一次資料就失敗,測試會很抖;只有「多做一步就是錯」的流程才用它。
- 軌跡比對只比工具名稱,不比參數;參數要另外用評估器檢查。
3. 門檻:依評估器類型分開設
| 評估器 | 門檻 | 理由 |
|---|---|---|
| 程式寫的不變式(「回覆不能有 email」「不能呼叫刪除類工具」) | min = 1.0 | 任何一題違規就是失敗 |
| 軌跡比對 | min = 1.0,或容許少數題失敗 | 評分確定,但 agent 行為本身不確定 |
| LLM 評審 | 看 mean,min 設寬鬆 | 單題有雜訊 |
- ★ 反例:AgentCore 官方 CI 範例對每個評估器「保留最高分」再跟 0.8 比,等於只要一題過就過,幾乎不可能失敗。
- 門檻跟主線基準比(例如不能比基準低超過 0.05),不要用絕對值:題庫變難時絕對門檻會一直紅,變簡單時又抓不到退化(判斷)。
- 平台通常沒有「低於多少就失敗」的設定,門檻要在 CI 腳本自己判斷。
4. 題數要夠:用標準誤估算
分數是 0/1 的通過率,平均的標準誤 = √(p(1−p)/n)。以通過率 p = 0.7 為例:
| 題數 n | 標準誤 |
|---|---|
| 10 | √(0.21/10) ≈ 0.14 |
| 50 | ≈ 0.065 |
| 200 | ≈ 0.03 |
題數太少時,正常浮動就大於你想抓的退化幅度。想抓 0.05 的退化,10 題根本看不出來。
5. 讓測試不要太抖
- 失敗的題目自動重跑一次,兩次都失敗才算真失敗。
- agent 的 temperature 能設 0 就設 0。
- PR 只擋確定性層;LLM 評審的結果以留言呈現,由人判斷。
- 區分「沒有結果」和「分數太低」:評估資料要先進監控系統(AgentCore 要等 2–5 分鐘),沒等到通常是基礎設施問題,不該算成品質退化。做法是先短暫等待,再輪詢到有結果;用不同的結束碼區分(原研究的 gate 腳本:通過 0、分數太低 1、缺結果 2)。
- 題庫版本要固定:CI 引用不可修改的題庫版本,不同次的分數才能比較。
6. 成本分層
依原研究(查證 2026-09-30),AgentCore 內建 LLM 評估器每次約 0.04;50題×3個評估器的PR檢查約6,還沒算 agent 本身的模型費。軌跡比對不花 token。每次 PR 跑幾乎免費的確定性層,合併主線才跑 LLM 評審。
機制細節 → AgentCore Evaluations與Optimization
🧪 我實際套用的紀錄
- 2026-09-30:原研究的 CI gate 腳本在本機測過三種情況:全部通過 exit 0;有一題很差 exit 1(
Correctness mean 0.68 < 0.8;min 0.30 < 0.5);缺評估器結果 exit 2。沒有在 AWS 上跑過。
⚠️ 注意 / 什麼時候不適用
- 程式寫的評估器最容易錯在 span 欄位名稱:不同框架的 trace 結構差很多,接真實 agent 前先撈一份真的 trace 對照(原研究推論)。
- LLM 評審本身要先校準才能信(見 LLM-as-Judge);拿沒校準的評審當門檻,擋下的可能是評審的偏誤。
- simulation 的對話事先無法預測,只能用斷言,不能比標準答案或軌跡。
- 平台配額會卡並行 CI:AgentCore 的 batch 評估同時只能 5 個 job,多個 PR 一起跑要排隊或重試。
- 這張卡管「CI 怎麼擋」。上線後的逐案 diff、子群崩壞、版本回退見 上線閘門與線上評估。
🔗 相關工具
- 上線閘門與線上評估 —— 平台中立的五層閘門與線上評估;這張卡補上 agent 專屬的軌跡比對與 CI 實作
- LLM-as-Judge —— 評審的偏誤與校準
- Agent 評估 —— agent 的評估指標
- AgentCore Evaluations與Optimization —— 評估器、A/B、Optimization 的平台細節
📖 型錄:全局與執行
[[AgentCore 總覽與Harness vs Runtime]] [[AgentCore 框架整合]] [[AgentCore Runtime]]、[[AgentCore Memory]] [[AgentCore Built-in Tools]]
📖 型錄:入口、身分、授權
[[AgentCore Gateway]]、[[AgentCore Identity]] [[AgentCore Policy]]、[[AgentCore Payments]]
📖 型錄:品質與營運
[[AgentCore Observability]] [[AgentCore Evaluations與Optimization]]
📖 型錄:Nova Act
[[Nova Act 總覽與SDK]] [[Nova Act 部署維運與HITL]] [[Nova Act 與AgentCore整合及安全]]