短效 authority 如何降低 Agent credential 洩漏風險,又不破壞多步任務?
客服 Agent 取得一個可以查詢、更新工單的權限,接著等待外部 API 回覆。若它拿的是八小時有效的 bearer token,token 被 log、trace 或錯誤回傳帶走後,攻擊者可以在剩餘時間重播;若只把 access token 設成五分鐘,長任務又可能在下一步突然失敗。
Agent 的特殊性是它會自己排程下一個 Tool Call,且每一步的風險與 resource 可能不同。因此 TTL 不是「token 的一個設定」而是每個 Action 的 authority constraint:誰、代表誰、為哪個 Task、對哪個 audience、在什麼 expiry 前可做什麼,都要在執行時驗證。
人類 session 常以互動時間描述;Agent Task 卻可能跨越 queue、retry、approval 與多個 Tool。把 User session 的長度直接複製給 Agent,會讓一個短暫的模型計畫變成長效自動化權力;把所有步驟綁成一把短 token,則讓低風險 read 和高風險 write 共用相同 blast radius。
Naive gateway 在 Task 開始時簽發 8 小時 records:write token,後續只檢查 signature。Agent 取得 token 後卡在 queue,隔兩小時才執行 delete;即使 User 已取消 Task,token 仍然有效。另一種錯誤是讓 Agent 自己用 refresh token 續期,卻沒有重新檢查 Task 狀態,形成無限續期。
短效 credential 應至少有 actor、subject、task_id、audience、scope、issued_at、expires_at 與 grant_id。RFC 8693 的 token exchange 允許 authorization server 依 target resource(resource)等資訊發出不同 token;這適合把通用身分交換成只給某個 Tool Gateway 的短效 authority,而不是把原 token 轉送給每個 Tool。
TTL 仍不是撤銷的替代品。取消 Task、撤銷 User delegation 或發現 Agent compromise 時,PDP/PEP 必須在 expiry 前也能拒絕 grant_id。續期只能是新的 authorization decision:Task 仍 active、原始 delegation 未撤銷、Agent identity/assurance 沒降級、下一個 Action 符合 policy,才可換發更窄的 grant。排隊中的 call 到期應拒絕並重新決策;已開始的不可中斷 side effect 則由 Tool 的 transaction/compensation policy 處理,不能假裝 token expiry 能回滾。
Task start 時簽發長效 bearer token,所有 Tool 共用 audience 與 scope;Agent 可用 refresh token 自行延長,PEP 不查 Task/revocation。
Task Orchestrator 只保存 stable task record。每次 step 前,Gateway 向 PDP 送出 actor、subject、task state、canonical Action、resource 與 audience;PDP 回傳短效 grant 或 deny。高風險 Action 使用更短 TTL/approval,且每次續期都產生新的 grant_id 與 evidence。
Agent 可提出下一步,但不能簽發、延長或修改 grant。Token Service/PDP 是 authority issuer;PEP 與 Tool 不能盲信 Agent 送來的 expires_at。Revocation store、Task store 與 clock source 必須在受信任控制面。
User → Task grant → Agent instance → Tool Gateway。Gateway 交換的 token audience 只包含目標 Tool,且只含本 step 的 operation/resource constraint。Token expiry、Task expiry、delegation expiry 三者取最早者。
決策為 allow(grant, ttl) 或 deny:task_active ∧ not_revoked ∧ audience_match ∧ action_in_scope ∧ now < min(all_expiry)。PEP 執行前再次檢查,並記錄 grant、policy version、clock time、queue delay 與 outcome。

import time
def decide(grant, now, task_active, revoked, audience, action):
return (task_active and not revoked and grant["aud"] == audience
and action in grant["actions"] and now < grant["exp"])
now = time.time()
g = {"aud": "tool://tickets", "actions": ["read"], "exp": now + 300}
assert decide(g, now + 10, True, False, "tool://tickets", "read")
assert not decide(g, now + 301, True, False, "tool://tickets", "read")
assert not decide(g, now + 10, False, False, "tool://tickets", "read")
assert not decide(g, now + 10, True, True, "tool://tickets", "read")
assert not decide(g, now + 10, True, False, "tool://billing", "read")
print("short-ttl=allow expiry/task/revocation/audience=deny")
Day 22 將把「短效」再收窄:權限不只活五分鐘,還要只能服務這一個 Task 的 goal、resource 與 workflow instance。