ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Archon 变量替换完全指南:Workflow 与命令中的占位符系统详解

Archon 变量替换完全指南:Workflow 与命令中的占位符系统详解 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),仅供参考
返回列表