Archon Workflows Variable Substitution Syntax: Complete Reference Guide
Archon employs a dollar-sign prefix convention where command-level substitutions like $1 through $9 and $ARGUMENTS are processed first, followed by workflow-level placeholders including $WORKFLOW_ID, $USER_MESSAGE, and $ARTIFACTS_DIR to inject runtime context into prompts.
The coleam00/Archon repository implements a two-layer variable substitution system that processes placeholders beginning with $ in both command texts and workflow prompts. This architecture separates lightweight command argument replacement from runtime-specific context injection, enabling dynamic workflow execution. Mastering the variable substitution syntax in Archon workflows allows developers to build responsive automation that adapts to user inputs, Git context, and execution environment variables.
Command-Level Substitution Syntax
Archon processes command-level variables through the substituteVariables function defined in packages/workflows/src/utils/variable-substitution.ts. This layer handles positional arguments supplied directly to command nodes before workflow-level context is applied.
Supported Placeholders
The command substitution engine recognizes three distinct placeholder types:
$1through$9– Positional arguments mapped to indices in the arguments array, where$1corresponds to the first element.$ARGUMENTS– A special variable that expands to all arguments joined as a single space-delimited string.\$– An escaped dollar sign that produces a literal$character in the output.
Implementation Details
The substituteVariables(text, args) function iterates through the provided arguments array, replacing each indexed placeholder with its corresponding value. After processing positional arguments, it substitutes the $ARGUMENTS token and finally un-escapes any \$ sequences to preserve literal dollar signs.
import { substituteVariables } from '@/workflows/utils/variable-substitution';
const cmd = 'git checkout $1 && echo "Branch is $1" && echo "All args: $ARGUMENTS" && echo "Literal dollar: \\$"';
const args = ['feature/login', '--force', '--no-verify'];
const result = substituteVariables(cmd, args);
// Output: git checkout feature/login && echo "Branch is feature/login" && echo "All args: feature/login --force --no-verify" && echo "Literal dollar: $"
Workflow-Level Substitution Syntax
After command processing, Archon applies workflow-level substitutions through the substituteWorkflowVariables function in packages/workflows/src/executor-shared.ts (lines 55-64). This routine injects runtime context that only exists during workflow execution.
Runtime Context Variables
The workflow substitution layer supports placeholders for execution metadata and environment configuration:
$WORKFLOW_ID– The UUID of the current workflow run.$USER_MESSAGE– The original trigger message from the user that initiated the workflow.$ARTIFACTS_DIR– Absolute path to the per-run artifacts directory.$DOCS_DIR– Path to the documentation folder (defaults todocs/or uses the.archon/config.yamloverride).$BASE_BRANCH– The base Git branch, auto-detected or explicitly configured.$CONTEXT,$EXTERNAL_CONTEXT,$ISSUE_CONTEXT– GitHub issue and pull request data when available.$ARGUMENTS– All command arguments joined as a string, accessible within prompt contexts.
Error Handling for Missing Values
If the $BASE_BRANCH placeholder appears in a prompt but the system cannot resolve a branch name, substituteWorkflowVariables throws an explicit error to prevent un-expanded tokens from reaching the AI model. This validation ensures workflow integrity before prompt submission.
import { substituteWorkflowVariables } from '@/workflows/executor-shared';
const prompt = `
Run ID: $WORKFLOW_ID
User said: $USER_MESSAGE
Artifacts can be found at: $ARTIFACTS_DIR
Docs live in: $DOCS_DIR
`;
const { prompt: expanded } = substituteWorkflowVariables(
prompt,
'c3f9e2a1-7b4d-4a5e-9f3c-2c7f9e1b6a5d', // workflowId
'/review add auth', // userMessage
'/tmp/archon/artifacts/123', // artifactsDir
'main', // baseBranch
'documentation/' // docsDir
);
Interactive Loop and Approval Variables
Archon provides specialized placeholders for interactive workflow nodes that handle user feedback and rejection states.
Loop User Input and Rejection Reasons
$LOOP_USER_INPUT– Contains feedback supplied to an interactive loop node, populated only during the first iteration of a resumed loop.$REJECTION_REASON– Stores reviewer comments when an approval node is rejected, enabling conditional logic based on rejection context.
const loopPrompt = `
You are reviewing the changes. User feedback: $LOOP_USER_INPUT
If the reviewer rejected, show reason: $REJECTION_REASON
`;
const { prompt } = substituteWorkflowVariables(
loopPrompt,
'run-42', '', '', '', '', '',
undefined,
'I think the variable naming is unclear.', // loopUserInput
'Too many nested loops.' // rejectionReason
);
Key Source Files
The variable substitution mechanism spans several critical files in the Archon codebase:
packages/workflows/src/utils/variable-substitution.ts– ImplementssubstituteVariables()for command-level$1…$9and$ARGUMENTSprocessing.packages/workflows/src/executor-shared.ts– ContainssubstituteWorkflowVariables()that expands runtime placeholders like$WORKFLOW_IDand$ARTIFACTS_DIRusing sequentialString.replaceoperations.packages/workflows/src/executor.ts– Orchestrates the end-to-end substitution flow during node execution.packages/workflows/src/schemas/workflow.ts– Defines the YAML schema where users declare variable references within workflow nodes.
Summary
- Archon uses a two-layer substitution system: command-level for arguments (
$1–$9,$ARGUMENTS) and workflow-level for runtime context ($WORKFLOW_ID,$USER_MESSAGE, etc.). - All placeholders follow the dollar-sign prefix convention (
$VARIABLE), with\$used to escape literal dollar signs in command texts. - The
substituteVariables()function invariable-substitution.tshandles positional argument replacement, whilesubstituteWorkflowVariables()inexecutor-shared.tsmanages execution-specific data. - Error handling prevents unresolved variables like
$BASE_BRANCHfrom reaching AI prompts by throwing exceptions when required context is missing. - Interactive workflows access special variables including
$LOOP_USER_INPUTand$REJECTION_REASONto process user feedback and approval states.
Frequently Asked Questions
What is the difference between $ARGUMENTS at the command level versus the workflow level?
While both use the same syntax, command-level $ARGUMENTS is processed by substituteVariables() in variable-substitution.ts for bash commands and executable nodes, whereas workflow-level $ARGUMENTS is expanded by substituteWorkflowVariables() in executor-shared.ts for inclusion in AI prompts. Both produce the same space-joined string of all input arguments, but they operate at different stages of the execution pipeline.
How do I include a literal dollar sign in my workflow commands?
Use the backslash escape sequence \$ in your command text. The substituteVariables() function converts \$ to a literal $ after processing all other placeholders, ensuring special characters are preserved without triggering substitution.
What happens if I reference an undefined variable like $BASE_BRANCH in my workflow?
If $BASE_BRANCH cannot be resolved because the Git context is missing or not configured in .archon/config.yaml, the substituteWorkflowVariables() function throws an error before sending the prompt to the AI model. This strict validation prevents malformed prompts containing unexpanded tokens.
When is $LOOP_USER_INPUT available during workflow execution?
$LOOP_USER_INPUT is only populated during the first iteration of a resumed loop in interactive workflow nodes. When a workflow pauses for user feedback and resumes, this variable captures the initial input provided by the user, allowing subsequent iterations to reference the original feedback context.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →