當 read Action 合法時,架構如何限制 Agent 將結果送往不允許的 Tool、domain 或 recipient?
客服 Agent 被允許查詢含個資的 ticket,目的是在內部產生摘要。若它接著呼叫外部 webhook、寄信 Tool 或另一個不受信任 Agent,單次 read 的 allow 已經無法回答「資料能去哪裡」。把結果放進模型 context 也不能使資料變成公開資料:摘要、embedding、錯誤訊息與 prompt trace 都可能是衍生外洩。
傳統 read permission 通常只看 caller、operation、resource;Agent 會把一個 Tool 的 output 當成下一個 Tool 的 input,自主形成 source-to-sink data flow。授權單點 allow 會漏掉跨步驟的 destination、資料標籤、purpose 與最終 recipient。
read_customer_ticket 對 Alice 的 Agent 是 allow。模型為了「通知客戶」把結果送到 https://hooks.example;egress Tool 只驗 Agent scope,未看 input label,完整地址與電話因此離開 trust domain。即使外送的是模型摘要,若摘要保留個人識別資訊,仍是同一條資料流。
把每個 result 包成帶 label/provenance 的資料物件:classification、source、task_id、purpose、allowed_destinations、retention 與 derived_from。Label 不是 Agent 可任意降低的字串;Resource service 或 trusted classifier 發出,衍生結果採最嚴格或依經批准的 transformation rule 繼承。
NIST SP 800-53 的 AC-4 將 information flow enforcement 視為獨立控制,說明這不只是 access control。Policy 要在 source read 與 sink write/egress 兩端執行:內部摘要可在同一 trust domain allow;external webhook 對 confidential label deny,公開資料才可送出。模型 context、logs、telemetry 也應視為 sink,並採最小化與 redaction。
Read PEP 回傳 raw JSON,Agent 可將任何字串交給任意 Tool;egress 只看 destination allowlist,不驗資料分類、Task purpose 或 provenance。
Source PEP 在 read 時產生 labeled result。Agent 可整理但不能移除 label;每個 sink PEP 以 source label + destination + recipient + transformation + task 重新決策。需要外送時只能走 approved declassification/approval path,並留下 flow evidence。
Resource metadata、label issuer、DLP/classifier 與 egress gateway 是受信任控制面。Agent/model、Tool description 與一般 prompt 都是不可信的 data-flow input;任何缺 label 或 provenance 的資料 default deny。
User/subject + Agent/actor + Task → source read → labeled result → Agent context → sink PEP → internal tool or external destination。每次 hop 保留 task_id、source_ids、classification 與 digest,禁止只傳 raw value。
allow = source grant ∧ destination policy ∧ label permits flow ∧ purpose match ∧ recipient approved ∧ transformation allowed。read allow 不推導 egress allow;若資料已進入 context,仍須在每個外流邊界檢查。

def egress_allowed(data, destination, purpose):
return (destination in data["allowed_destinations"]
and (data["classification"] == "public" or destination == "internal")
and purpose == data["purpose"])
conf = {"classification":"confidential", "allowed_destinations":{"internal"}, "purpose":"support"}
public = {"classification":"public", "allowed_destinations":{"internal", "external"}, "purpose":"marketing"}
assert not egress_allowed(conf, "external", "support")
assert egress_allowed(conf, "internal", "support")
assert egress_allowed(public, "external", "marketing")
assert not egress_allowed(public, "external", "support")
print("confidential-external=deny confidential-internal/public-approved=allow")
Day 24 會把資料流問題延伸到能力流:即使每個 Tool Call 個別 allow,某些 Tool 的組合是否仍然不應被同一 Task 執行?