
Archon 變量替換完全指南Workflow 與命令中的占位符系統詳解【免費下載鏈接】ArchonThe first open-source harness builder for AI coding. Make AI coding deterministic and repeatable.項目地址: https://gitcode.com/GitHub_Trending/archon3/Archon導讀Archon 在命令文件command files與工作流workflow提示詞中通過$VARIABLE形式的占位符在執行時完成文本替換這是把用戶輸入、運行上下文、上游節點輸出與后續 AI 步驟銜接起來的核心機制。本文以官方 Variable Substitution Reference 為骨架結合倉庫源碼梳理全部內置變量、替換發生的時機與位置、bash:/script:節點特有的注入防護與環境變量通道以及 DAG 模式下的節點輸出引用$nodeId.output與 Artifact 指針契約。讀完后你將能準確設計可安全傳遞用戶輸入、跨節點傳遞結構化數據的工作流模板并規避靜默失效與 Shell 注入兩類常見陷阱。變量總覽所有變量都遵守「執行時替換」的同一原則它們在節點真正運行前被解析解析結果取決于當次運行的觸發消息、git 狀態與配置。變量作用域說明$ARGUMENTS所有模式觸發工作流的用戶原始消息$USER_MESSAGE所有模式與$ARGUMENTS等價二者都解析為用戶消息$WORKFLOW_ID所有模式唯一的工作流運行 ID用于追蹤與日志關聯$ARTIFACTS_DIR所有模式本次運行預先創建好的產物目錄節點輸出請寫在這里$BASE_BRANCH所有模式基礎分支名。優先從 git 自動檢測或由配置worktree.baseBranch指定被引用但無法解析時直接拋錯$DOCS_DIR所有模式文檔目錄配置docs.path默認docs/。永不拋錯$CONTEXT所有模式GitHub issue/PR 上下文平臺可用時才有不可用時為空字符串$EXTERNAL_CONTEXT所有模式$CONTEXT的別名$ISSUE_CONTEXT所有模式$CONTEXT的別名$LOOP_USER_INPUT循環 / loop_group 提示詞交互式循環門/workflow approve id text中的用戶反饋。只在恢復后的第一次迭代填充其余位置均為空字符串$LOOP_PREV_OUTPUT循環提示詞上一輪迭代清理后的輸出已剝掉 completion 標簽。第 1 輪為空。是fresh_context: true循環獲知「上一輪做了什么」的關鍵工具$LOOP_PREV.nodeId.output[.field]loop_group 正文提示詞與when:條件上一輪迭代中某個正文節點的輸出。第 1 輪為空。字段訪問遵循下面的嚴格契約真正缺失的先前輸出→在正文when:中它是類型化條件引用而非文本替換$REJECTION_REASON舊式approval.on_reject提示詞來自/workflow reject id reason的評審反饋。其他位置均為空字符串新式門讀取$gate.output.text$nodeId.output僅 DAG某個已完成的上游節點的完整文本輸出未知或被跳過的生產者 →$nodeId.output.field僅 DAGJSON 字段訪問——嚴格模式字段無法解析會使消費節點失敗見下文倉庫完整版參考文檔還額外補充了兩個引擎級變量見 reference/variables.md$STATE_DIR預創建的跨運行狀態目錄~/.archon/workspaces/project/state/按項目而非按運行共享供相互協作的工作流共享記憶如去重賬本、last processed游標。它在倉庫與 worktree 之外worktree 拆除后依然存活也永不進入git status。與$BASE_BRANCH一樣被引用但無法解析時拋錯而非替換為空串。引擎對其不做任何鎖跨運行并發寫需自行按$STATE_DIR/name/命名空間隔離。$ADOPTED_RUN_DIR源碼 executor-shared.ts僅在顯式--adopt run-id采納前序運行時可用用于按引用讀取先前運行的產物目錄未啟用采納時引用會拋錯。變量在哪些位置被替換命令文件.archon/commands/*.md——核心集合$ARGUMENTS/$USER_MESSAGE、$WORKFLOW_ID、$ARTIFACTS_DIR、$BASE_BRANCH、$DOCS_DIR、$CONTEXT家族以及當該命令作為 DAG 節點運行時額外的$nodeId.output[.field]。被loop.command或loop_group正文引用的命令文件與內聯循環提示詞一樣獲得填充好的循環變量普通 DAG 命令節點對循環/拒絕類變量拿到。$REJECTION_REASON只在approval.on_reject提示詞中填充。內聯prompt:字段——DAG 提示詞節點、循環提示詞、loop_group 正文提示詞。bash:腳本——特殊用戶可控變量$ARGUMENTS、$USER_MESSAGE、$LOOP_USER_INPUT、$LOOP_PREV_OUTPUT、$REJECTION_REASON、$CONTEXT不做文本替換Shell 注入防護而是作為環境變量傳入ARGUMENTS、USER_MESSAGE、LOOP_USER_INPUT、LOOP_PREV_OUTPUT、REJECTION_REASON、CONTEXT外加ARTIFACTS_DIR、LOG_DIR、BASE_BRANCH——用$ARGUMENTS按普通 Shell 環境變量讀取即可。$nodeId.output引用會被替換且自動加 Shell 引號超過 32KB 的值會溢出寫入文件并替換為$(cat path)。script:正文——與bash:相同用戶可控變量不做文本替換注入防護見 issue #2115以環境變量形式到達——ARGUMENTS、USER_MESSAGE、LOOP_USER_INPUT、LOOP_PREV_OUTPUT、REJECTION_REASON、CONTEXT外加EXTERNAL_CONTEXT/ISSUE_CONTEXT以及ARTIFACTS_DIR、LOG_DIR、BASE_BRANCH和受管的項目級環境變量——通過process.env.ARGUMENTSbun或os.environ[ARGUMENTS]uv/python讀取。源碼中留在正文里的字面$ARGUMENTS/$USER_MESSAGE/$CONTEXT不再解析并會記錄一條「單版本遷移」警告。$nodeId.output值仍以原始文本替換不加 Shell 引號。這一「引擎變量文本替換 用戶可控變量環境變量傳遞」的雙通道設計在源碼 executor-shared.ts 中可以看到$WORKFLOW_ID、$ARTIFACTS_DIR、$STATE_DIR、$BASE_BRANCH、$DOCS_DIR無條件替換即便shellSafe開啟而$USER_MESSAGE/$ARGUMENTS/$LOOP_USER_INPUT/$REJECTION_REASON/$LOOP_PREV_OUTPUT只在非 shell 分支替換——這正是為了防止把不可信輸入拼進可執行源碼。bash 與 script 節點的安全取值姿勢由于bash:/script:對用戶可控變量走環境變量通道讀取方式如下# bash 節點環境變量即參數正常加引號 echo 用戶消息: $ARGUMENTS mkdir -p $ARTIFACTS_DIR// script 節點runtime: bun const args process.env.ARGUMENTS ?? ; const base process.env.BASE_BRANCH ?? ;# script 節點runtime: uv import os args os.environ.get(ARGUMENTS, )$nodeId.output則按節點類型不同處理bash:中自動 Shell 引號小值內聯單引號32KB 寫入引擎所有的$ARTIFACTS_DIR/.archon/node-output-spills/node[.field].nodeoutput并替換為$(cat path)而script:中原樣嵌入不引號化。因此對 script 節點要把替換值當不可信輸入用語言特性解析如JSON.parse而不是插進 Shell 語法。直接賦值有前提const data $nodeId.output;只有runtime: bun且生產者聲明了output_format時才安全JSON 布爾值與 null 不是合法的 Python 字面量所以runtime: uv的腳本應改用with: { data: $nodeId.output }綁定再從os.environ[INPUTS_DATA]用json.loads解析。對任意文本生產者bash/script 的 stdout 或散文輸出同樣建議走環境變量綁定僅在確認文本含 JSON 時才防御性地解析。不要把$nodeId.output包進String.raw模板字面量——當輸出含反引號AI 生成的 markdown 與output_format載荷中很常見時會靜默破壞。bash 節點雙重引號陷阱bash:的替換自帶引號再套一層雙引號會引入字面單引號導致條件判斷靜默失敗# 錯誤——小值場景下 $emit.output.status 被注入為 ok單引號 # status$emit.output.status 實際變成 statusok引號變成數據 status$emit.output.status [ $status ok ] echo pass # → 靜默失敗$status 是 ok不是 ok # 正確——保持替換不帶引號Archon 的引號就是引號 status$emit.output.status # → statusok → bash 賦值ok [ $status ok ] echo pass # → 通過大輸出32KB的替換形態是$(cat /path)var$(cat ...)在 bash 里正確——但作者無法在編寫時預知大小所以規則是無條件的始終用var$node.output.field絕不用var$node.output.field。數字與布爾字段以裸值注入無引號雙引號對它們「碰巧」有效這讓 bug 變得時有時無。替換順序標準工作流變量$WORKFLOW_ID、$ARGUMENTS、$ARTIFACTS_DIR、$BASE_BRANCH、$DOCS_DIR、$CONTEXT、循環/拒絕類變量節點輸出引用$nodeId.output、$nodeId.output.field、$LOOP_PREV.*——僅 DAG 模式完整版參考文檔進一步細分為三步reference/variables.md工作流變量 → 上下文變量$CONTEXT家族→ 節點輸出引用且loop_group正文中$LOOP_PREV.nodeId.output引用最先解析先于$LOOP_USER_INPUT拼接保證用戶文本不會被二次當作工作流引用處理隨后再執行該節點正常的替換流程。上下文自動追加Context Auto-Append如果提示詞模板中完全沒有出現$CONTEXT/$EXTERNAL_CONTEXT/$ISSUE_CONTEXT但上下文確實存在例如來自 GitHub issue則該上下文會在---分隔符之后自動追加到提示詞末尾。這條規則有兩個目的其一避免命令顯式使用$CONTEXT時上下文被重復發送其二在無 issue 上下文時把三個別名替換為空串避免把字面$CONTEXT文本發給 AI。轉義美元符號在命令文件中用\$產生字面$阻止變量替換。明確不支持$1…$9位置參數盡管舊文檔曾暗示支持工作流引擎不替換位置參數$1…$9——命令文件與提示詞只通過$ARGUMENTS/$USER_MESSAGE接收完整消息不存在按空白拆分成編號槽位的機制直接命令調用與工作流節點皆如此。代碼庫中存在一個遺留的位置替換輔助函數但未接入執行路徑。需要結構化輸入時在提示詞內部解析$ARGUMENTS或用bash:/script:節點處理。節點輸出細節僅 DAG$nodeId.output解析為上游節點的完整文本輸出。若節點使用了output_format:結構化輸出輸出是經校驗的 JSON 字符串化結果無output_format的 bash/script 輸出則是去掉尾部換行的 stdout有output_format時 stdout 必須在同一結果契約下被認證為 JSON見 node-reference.md 的 Result contracts 一節。loop/loop_group 輸出是剝掉完成信號標簽后的最終迭代輸出。帶作者自定approval.decisions的門總是輸出 JSON{decision, text}讀取其字段用$gate.output.decision與$gate.output.text未自定決策的舊式門保持舊行為——只有capture_response: true時才輸出其審批評論否則為。未知或被跳過的生產者解析為空串并記錄警告。字段訪問的嚴格契約no-silent-drop$nodeId.output.field是嚴格的要么解析成功要么讓消費節點失敗生產者聲明了output_format模式中已聲明的字段解析為其值若缺失則解析為聲明為可選未在模式中聲明的字段會使消費者失敗防拼寫錯誤。無模式生產者生產節點未聲明output_format輸出必須是包含該鍵的 JSON 對象——非 JSON 輸出、鍵缺失都會使消費者失敗。生產者被跳過或未決消費者失敗——用when:或寬松的trigger_rule保護引用。取值規則字符串原樣通過數字/布爾字符串化對象/數組 JSON 字符串化。對workflow:子運行結果這些字段規則使用子運行returns:節點的模式——字段名隨值一同傳遞并能在冷恢復后存活調用方不能增刪契約。include:別名在展平后直接使用其選中的生產者。源碼中對應注釋亦印證了「未知輸入名 THROWS而非替換」的嚴格性——拼錯的輸入靜默變空比加載可見的錯誤更糟executor-shared.ts。實戰示例nodes: - id: classify command: classify-issue output_format: type: object properties: type: { type: string, enum: [BUG, FEATURE] } required: [type] - id: fix prompt: | The issue was classified as: $classify.output.type Full classification: $classify.output Users original request: $USER_MESSAGE depends_on: [classify]命令/腳本節點的with:綁定命令文件與命名腳本對內聯文本替換是不透明的——引擎從不改寫其正文。with:在command:/script:節點上按名字把上游值綁定到這些正文已經會讀取的通道命令文件讀$INPUTS.name腳本讀INPUTS_UPPER_SNAKE環境變量。nodes: - id: validate prompt: Run validation and report the verdict. output_format: type: object properties: green: { type: boolean } required: [green] - id: record script: record-verdict # 命名腳本——讀取 process.env.INPUTS_GREEN runtime: bun depends_on: [validate] with: green: $validate.output.green綁定值有三種形態非字符串字面量true、42、[a, b]按自身邏輯類型傳遞恰好是一個完整$node.output/$node.output.field/$INPUTS.name引用的字符串按邏輯值傳遞布爾字段到達時就是布爾對象就是對象環境變量投遞用其規范文本字符串原樣、其余 JSON其他字符串當作文本模板按input:的規則替換先工作流變量再$node.output引用。綁定指令對象{ from, if_skipped }可在生產者被跳過時提供回退值——被跳過且無if_skipped會直接失敗節點綁定永不靜默解析為空串。每個被引用的生產者都必須是depends_on的上游依賴否則加載器拒絕保證綁定永遠不會與生產者競態。Artifact 指針大文件結果的標準通道當機器消費方需要文件結果時在結果中返回一個包含指針的小型 JSON 值。保留形狀{type:archon_artifact,run_id:producing run id,path:review/report.md}run_id必須使用實際的WORKFLOW_ID值而非字面變量名。生產者必須先把自己的文件寫到$ARTIFACTS_DIR之下。允許指針上攜帶兄弟鍵。在持久化結果前引擎會針對生產運行校驗帶標簽的指針自身的 run id、非空相對路徑且不含..段或 NUL 字節、詞法包含、且必須是存在的常規文件。絕對路徑/越界路徑、目錄、缺失文件、其他運行的 id 都會使生產者失敗。校驗規則reference/variables.md規則拒絕的情形自有運行run_id非生產運行自身$WORKFLOW_ID。當前結果只能指向自身運行的產物可尋址運行輸出位置從未記錄或記錄在 Archon home 目錄之外相對路徑絕對路徑、..段或 NUL 字節包含性詞法上解析到運行產物目錄之外真實文件目標缺失或是目錄workflow:父運行與扇出聚合原樣轉發指針而不針對父運行重新校驗。事件與恢復保留 run id 與相對路徑。引擎不會把指針展開為絕對路徑、不會把文件內容讀進提示詞也不提供工作流內解析器——生產運行內部的提示詞交接請繼續使用$ARTIFACTS_DIR/path磁盤上是同一個文件。讀側誰可以看該運行、路徑經符號鏈接跟隨后的 realpath 包含性由讀取方自持授權與校驗責任GET /api/artifacts/run_id/path目前只做詞法包含校驗讀時 realpath 解析尚未實現跟蹤于 #3160。各上下文中的變量可用性變量工作流節點直接命令調用when:條件$ARGUMENTS/$USER_MESSAGE是是兩個別名均可否$WORKFLOW_ID是否否$ARTIFACTS_DIR是否否$STATE_DIR是否否$BASE_BRANCH是否否$DOCS_DIR是否否$CONTEXT/ 別名是否否$LOOP_USER_INPUT是循環節點否否$REJECTION_REASON是僅on_reject否否$LOOP_PREV_OUTPUT是循環節點否否$LOOP_PREV.nodeId.output是loop_group 正文節點否是loop_group 正文節點$nodeId.output是DAG 節點否是此外systemPrompt:與agents.id.prompt/agents.id.description中工作流變量與$nodeId.output引用均可解析這些文本直接進入 provider與prompt:一樣經過兩輪替換三者中任何一處出現懸空的$nodeId.output都是加載錯誤。常見誤區速查$1…$9不可用在提示詞內解析$ARGUMENTS或交給bash:/script:節點處理。bash:中不要對$node.output.field套雙引號替換已自帶引號嵌套引號會讓引號字符變成數據數字/布爾字段會掩蓋此問題使其間歇性出現。script:中不要直接嵌入$nodeId.output到源碼對任意文本生產者優先走with:環境變量綁定再防御性解析bun 下直接賦值僅限生產者聲明了output_format的場景。不要把$nodeId.output包進String.raw模板字面量輸出含反引號時會靜默破壞。$BASE_BRANCH與$STATE_DIR會 fail-fast被引用卻無法解析時直接拋錯而非靜默替換為空串——「響亮的失敗」優于「靜默寫錯位置」。位置參數未接入執行路徑代碼庫中的遺留輔助函數不參與執行不要依賴它。深入閱讀本主題的完整版參考reference/variables.md含$STATE_DIR并發與命名沖突討論、with:綁定三形態、環境讀取的靜態詞法檢查等擴展內容節點類型與結果契約node-reference.md工作流編寫指南DAG、when:、trigger_rule、持久會話等guides/authoring-workflows.md變量替換核心實現executor-shared.tssubstituteWorkflowVariables與buildPromptWithContext含shellSafe雙通道邏輯與 fail-fast 校驗相關測試與校驗邏輯packages/workflows/src/executor-shared.test.ts、packages/workflows/src/dag-executor.ts、packages/workflows/src/validator.ts可用bun test在倉庫內運行驗證行為【免費下載鏈接】ArchonThe first open-source harness builder for AI coding. Make AI coding deterministic and repeatable.項目地址: https://gitcode.com/GitHub_Trending/archon3/Archon創作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考