Tool 收到請求時,要驗證 User、Agent workload、Agent instance,還是三者的組合?
假設財務 Agent 替 Alice 查詢逾期帳款,最後把摘要交給內部郵件 Tool。Tool 只看見一個 sub=alice 的 token,會以為 Alice 親自發出請求;只看見 sub=finance-agent,又無法知道這次是否真的獲得 Alice 的委派。若 Agent 把 X-User: alice 放在 HTTP header,任何能呼叫 Tool 的程式都能偽造它。
這不是在問「JWT 怎麼驗簽」,而是在問一次 Action 的責任鏈:誰是直接執行者、它代表誰、請求要送給哪個資源,以及哪個元件作出 allow。
固定後端服務通常只需辨認服務本身。Agent 會在同一個 runtime 連續提出多個、由模型決定參數的 Tool Call,且可在不同 Task 代表不同使用者。因此 authentication 的 subject 與 authorization 的 effective principal 必須分開。
若只傳 User token,會遺失 workload attribution;若只傳 Agent token,會把 Agent 自身權限誤當成 User delegation。Agent 的請求至少要有 subject(代表誰)、actor(哪個 instance 執行)、aud(給哪個 Tool)與 task_id(哪個任務)。
Naive 設計是 Agent 直接呼叫 Tool,Tool 信任 X-Agent-Id 與 X-User-Id,或只驗證一個共用 bearer token。攻擊者若能重放 token,便能冒充 Agent;若能改 header,便能把自己的查詢記成 Alice 的委派操作。更隱蔽的錯誤是 token audience 是整個 API 平台,郵件 Tool 可拿同一 token 去呼叫 CRM。
exp、aud,並確認 credential 是給本 Tool 的。actor。sub;它不是直接連線者。sub 和 actor 的關係仍需由 delegation policy 驗證,不能由 caller 自行拼接。RFC 8693 的 act claim 正是用來表達 delegation 後的 acting party;RFC 8707 則說明以 resource indicator 限定 token 的目標資源。兩者都不是「自動允許寄信」的規則,PDP 仍要檢查 Action。
Agent --共用 token + 可偽造 headers--> Tool
Tool 無法可靠區分 caller、代表人與 audience,且 Agent 能繞過 policy。
由受信任的 issuer 簽發含 sub、act、aud、exp、task_id 的 token;Tool Gateway 驗證 token,再把 canonical request 交給 PDP。Agent 只能提出 Action,不能自行變更 sub 或 scope。

User/issuer、Agent runtime、Gateway/PDP、Tool 是不同 trust boundary。Gateway 是 identity enforcement point;PDP 是 authorization decision point;Tool 仍應拒絕沒有 Gateway 可驗證 caller context 的直接呼叫。Tool audit 要同時記 sub=Alice 與 actor=agent://finance/v3/i-7。
以下只用 Python 標準庫,模擬簽章已由受信任 issuer 驗證後的 claims。它刻意拒絕只有 User、錯誤 audience、缺 actor 的請求。
import base64, json
def token(**claims):
return base64.urlsafe_b64encode(json.dumps(claims).encode()).decode()
def authenticate(raw, expected_aud="tool://mail"):
c = json.loads(base64.urlsafe_b64decode(raw + "=" * (-len(raw) % 4)))
required = {"iss", "sub", "act", "aud", "exp"}
if not required <= c.keys() or c["iss"] != "issuer://corp":
return False, "missing-or-untrusted-claims"
if c["aud"] != expected_aud or c["exp"] <= 100:
return False, "wrong-audience-or-expired"
return True, c
cases = {
"delegated": token(iss="issuer://corp", sub="alice", act={"sub":"agent://mail/i-7"}, aud="tool://mail", exp=200),
"user_only": token(iss="issuer://corp", sub="alice", aud="tool://mail", exp=200),
"wrong_audience": token(iss="issuer://corp", sub="alice", act={"sub":"agent://mail/i-7"}, aud="tool://crm", exp=200),
}
for name, raw in cases.items():
print(name, authenticate(raw)[0])
assert authenticate(cases["delegated"])[0]
assert not authenticate(cases["user_only"])[0]
assert not authenticate(cases["wrong_audience"])[0]
預期輸出為 delegated True、其餘 False。實際系統還必須驗證 JWT 簽章、issuer key rotation、nonce/重放、delegation scope 與 resource authorization;本例只證明 claims 的最小邊界。
act、aud、iss 和 expiry 是可驗證輸入,不是 Agent 自報 header。下一篇進一步問:如果 Agent 只有一把靜態 API Key,這把 key 能否證明上述四件事?
act actor claim)