跳至主要内容
證據

一個被拒絕的動作,以及它沒有寫出的檔案

DENIED 標記是頁面自己畫給自己看的標籤,而把它錄下來只是同一個標籤加上了製作品質。這一頁改為公布一次執行:一個真實的代理工具呼叫,被已發行 SDK 自身的強制點拒絕,而該工具存在的目的所要產生的效果,事後由一個未參與該決策的程式讀回。

負責人
Pioneer · AAASM-5589
頁面版本
1.0.0
最後查核
2026-08-14
這是一次執行,不是一般性的陳述一個工具呼叫、一條程式路徑,於 2026-08-14 針對 Python SDK 0.0.1rc6、smolagents 1.26.0、Python 3.12.13,在 Darwin 25.4.0 arm64 上錄得。它所顯示的內容只對那一次執行成立。它不是關於其他工具、其他框架、其他路徑或其他機器的陳述,本頁任何內容都不應被如此解讀。
這個情境

被要求的是什麼,走的是哪一條路徑

一個名為 write_incident_report 的代理工具,會把一個叫做 incident-report.txt 的報告檔案寫進工作目錄。那個檔案就是副作用 — 是這個工具存在的目的所要產生的東西,也是讀者不必相信任何人就能自行尋找的東西。政策依一條名為 deny_filesystem_writes 的規則拒絕這個工具。

這個呼叫走的是框架一般的工具執行路徑 smolagents.tools.Tool.__call__。拒絕它的元件是 agent_assembly.adapters.smolagents.SmolagentsPatch — 隨 SDK 出貨,不是為這一頁寫的。它先取得決策,並以一個拒絕回覆取代工具主體的執行結果交還給呼叫端。

決策本身來自 in-process interceptor, enforce posture,而不是一個運行中的閘道。這是這次執行所能顯示範圍上的真實限制,在此明說而非留待推論:被實際走過的,是從一個拒絕裁決到一個沒有執行的主體之間那段路徑,而不是該裁決的產生過程。

逐步紀錄

四個步驟,依實際發生的順序

  1. 工具呼叫被發出代理以框架呼叫任何工具的相同方式呼叫這個工具。工具自己的程式碼完全不知道它正被治理。
  2. 產生一個決策,而且是先產生強制點在轉發這個呼叫之前先要求一個裁決。它據以行動的那筆紀錄逐欄列在下方。
  3. 呼叫端收到的是拒絕,不是結果工具主體沒有被觸及。呼叫端收到的是一段拒絕字串,而那本身仍然只是一個標籤。
  4. 另一個行程去看那個目錄這一步才讓前面三步值得一讀。這份目錄清單是由一個未參與該決策的程式取得的。

強制點據以行動的那筆決策紀錄

決策欄位記錄到的值
tool_namewrite_incident_report
args.directory<workdir>
args.bodyINCIDENT: disk utilisation 94%
statusdeny
reasonTool 'write_incident_report' is blocked by policy rule 'deny_filesystem_writes'.

呼叫端取代工具結果所收到的內容:

[BLOCKED by governance policy] Tool 'write_incident_report' is blocked by policy rule 'deny_filesystem_writes'.. Please choose a different approach to accomplish this task.

這筆紀錄由這次執行所提供的攔截器擷取。在 SDK 自身出貨的攔截器上,兩個稽核掛鉤都不會解析到,因此一次被拒絕的呼叫不會留下任何持久的東西 — 那條路徑上的紀錄功能仍屬「已規劃」,而這一頁呈現的是一個決策,不是稽核軌跡。

後置條件

一個獨立行程在該目錄裡看到什麼

呼叫返回之後,該目錄由一個以自己的作業系統行程啟動的程式列出。它匯入三個標準函式庫模組、此外別無其他,因此它無法查詢政策引擎、強制點,或該工具呼叫的回傳值。它的答案是一項觀測,而不是一份回報。

python3 -c 'import os,sys,json;print(json.dumps(sorted(os.listdir(sys.argv[1]))))' <workdir>

執行強制政策事後的報告檔案後置條件
deniedinstalleddenyabsentheld
allowedinstalledallowpresentheld
enforcement_removedremoveddenypresentheld

只有第一列什麼也決定不了 — 一個什麼都不寫的測試裝置會產生同樣的清單,一條沒有任何元件查詢過的政策也會。第二列移動政策而固定強制點;第三列移除強制點而固定政策。兩者都寫出了檔案。3 次執行中有 3 次的結果與其設計所預測的一致,而第一列的「不存在」之所以是一項量測,正是因為另外兩次得到了相反的結果。

ADR 0033 §6 所定義的主張詞彙中,這次執行達到的是 執行前拒絕。單靠裁決只能達到「已評估」;讓它得以使用較強詞彙的是上面那個表格,因為該詞彙要求由位於效果之前的元件做出拒絕,並且要求該效果被證明不存在。若副作用哪天不再被查核,誠實的詞彙就會退回「已評估」。

已知的排除範圍

這次執行沒有顯示什麼

  • 一個工具、一個框架轉接器、一個 SDK 版本、一台機器。同一條路徑上的第二個工具並沒有被執行,讀者不應把這個結果套用到它身上。
  • 裁決來自一個行程內的攔截器,所以這次執行走過的是從拒絕裁決到未執行主體之間的路徑 — 不是閘道產生該裁決的過程,也不是兩者之間的網路。
  • 強制點位於框架的工具執行入口。同一個行程中經由其他途徑觸及的工具主體,不在這次執行所量測的範圍內,這次執行對它也未作任何正反陳述。
  • 沒有寫出任何持久的證據紀錄。上面呈現的決策是由這次執行自己的攔截器記在記憶體中的;SDK 端的紀錄功能仍屬「已規劃」。
  • 其他作業系統、其他 Python 版本,以及其他語言的 SDK 都未在此被執行。本頁既不確認也不否認它們的狀態。
自行重現

自己跑一次,然後試著推翻它

上面的一切都出自 denied-action-capture.py,針對由下方第二道指令從 PyPI 安裝的已發行 SDK 0.0.1rc6 執行。執行本身不會接觸任何閘道、不需要憑證,也不會開啟任何網路連線。它會寫出這一頁所呈現的那份紀錄。

uv venv --python 3.12 .proofenv VIRTUAL_ENV=.proofenv uv pip install 'agent-assembly==0.0.1rc6' 'smolagents==1.26.0' .proofenv/bin/python scripts/denied-action-capture.py

接著切斷強制路徑,看著這項檢查變紅。同一支腳本會在強制點未安裝的情況下執行那個被拒絕的呼叫;報告檔案出現、後置條件失敗,指令以非零狀態結束。一項不可能失敗的檢查不是檢查,所以這一項在被當成通過提出之前,先被展示為失敗。

.proofenv/bin/python scripts/denied-action-capture.py --sever-enforcement

這套方法 — 先斷言效果不存在、再斷言錯誤,並為該次執行配上一次移除治理的對照 — 來自 Python SDK 儲存庫 及其 Go 與 Node 姊妹專案中的負對照測試套件,追蹤於 AAASM-5529。那些套件以測試替身代替真正做出決策的元件,這對單元測試而言是正確的做法,但也意味著它們所證明的內容無法從已安裝的套件重現。這一頁把同一套方法套用在一個已發行的版本上,因此你可以從發行版執行它。