Summary
generateInterpolationAndTemplateStep skips emitting the "Interpolate variables and render templates" step when a workflow has no expressions, no {{#if pattern, no GitHub tool and no inline sub-agents — but the compiler always emits the {{#runtime-import <workflow>.md}} macro for the workflow body.
interpolate_prompt.cjs is the only consumer of that macro. When the step is skipped, the macro reaches the agent verbatim and the entire workflow body is never delivered. The agent receives only the <system> preamble and a literal {{#runtime-import ...}} line.
Compilation reports 0 error(s), 0 warning(s) and validate_prompt_placeholders.sh reports ✅ Placeholder validation complete, so nothing surfaces the failure.
Root cause
pkg/workflow/template.go:
hasExpressions := len(expressionMappings) > 0
hasTemplatePattern := strings.Contains(data.MarkdownContent, "{{#if ")
hasGitHubContext := hasGitHubTool(data.ParsedTools)
hasInlineSubAgents := inlineSubAgentPattern.MatchString(data.MarkdownContent)
hasTemplates := hasTemplatePattern || hasGitHubContext || hasInlineSubAgents
if !hasExpressions && !hasTemplates {
templateLog.Print("No interpolation or template rendering needed, skipping step generation")
return
}
The condition never checks for the presence of {{#runtime-import}} macros, even though unified_prompt_step.go documents the dependency explicitly:
// Runtime-import macros are plain text lines processed by the
// interpolate-prompt step; they can live in the same heredoc block
// as surrounding content.
Reproduction
Minimal frontmatter that triggers it — the key is github: false (no GitHub tool ⇒ hasGitHubContext == false) plus a body containing no {{#if and no ${{ }}:
engine:
id: claude
tools:
edit:
github: false
safe-outputs:
create-pull-request:
Compile, then inspect the generated lock:
$ grep -c interpolate_prompt .github/workflows/<name>.lock.yml
0
$ grep -c runtime-import .github/workflows/<name>.lock.yml
1
At runtime, the activation job's "Print prompt" step shows the unresolved macro:
</system>
{{#runtime-import .github/workflows/<name>.md}}
The activation artifact declares three prompt files but only produces one — the two written by interpolate_prompt.cjs are missing:
/tmp/gh-aw/aw-prompts/prompt.txt ← present (still the template)
/tmp/gh-aw/aw-prompts/prompt-template.txt ← never created
/tmp/gh-aw/aw-prompts/prompt-import-tree.json ← never created
if-no-files-found: ignore on the upload keeps this silent.
Observed impact
Across four production runs the agent received no instructions at all. Its first action was consistently an attempt to locate its own prompt.
Sometimes the agent doesn't find it so it ends abruptly.
Expected behaviour
Emit the interpolation step whenever the prompt contains runtime-import macros. Something like:
hasRuntimeImports := strings.Contains(data.MarkdownContent, "{{#runtime-import")
hasTemplates := hasTemplatePattern || hasGitHubContext || hasInlineSubAgents || hasRuntimeImports
Note the compiler emits the body's self-import independently of MarkdownContent, so checking the generated prompt chunks rather than the markdown source may be more robust.
A secondary guard would help regardless: validate_prompt_placeholders.sh currently passes a prompt containing an unresolved {{#runtime-import}}. Failing there would turn a silent no-op into a clear build error.
Workaround
Adding any {{#if ...}} block to the workflow body forces hasTemplatePattern to true and restores the step.
Environment
gh aw v0.83.4
- engine:
claude (@anthropic-ai/claude-code@2.1.214)
- self-hosted Linux x64 runner,
awf v0.27.37
- trigger:
repository_dispatch
Summary
generateInterpolationAndTemplateStepskips emitting the "Interpolate variables and render templates" step when a workflow has no expressions, no{{#ifpattern, no GitHub tool and no inline sub-agents — but the compiler always emits the{{#runtime-import <workflow>.md}}macro for the workflow body.interpolate_prompt.cjsis the only consumer of that macro. When the step is skipped, the macro reaches the agent verbatim and the entire workflow body is never delivered. The agent receives only the<system>preamble and a literal{{#runtime-import ...}}line.Compilation reports
0 error(s), 0 warning(s)andvalidate_prompt_placeholders.shreports✅ Placeholder validation complete, so nothing surfaces the failure.Root cause
pkg/workflow/template.go:The condition never checks for the presence of
{{#runtime-import}}macros, even thoughunified_prompt_step.godocuments the dependency explicitly:Reproduction
Minimal frontmatter that triggers it — the key is
github: false(no GitHub tool ⇒hasGitHubContext == false) plus a body containing no{{#ifand no${{ }}:Compile, then inspect the generated lock:
At runtime, the activation job's "Print prompt" step shows the unresolved macro:
The
activationartifact declares three prompt files but only produces one — the two written byinterpolate_prompt.cjsare missing:if-no-files-found: ignoreon the upload keeps this silent.Observed impact
Across four production runs the agent received no instructions at all. Its first action was consistently an attempt to locate its own prompt.
Sometimes the agent doesn't find it so it ends abruptly.
Expected behaviour
Emit the interpolation step whenever the prompt contains runtime-import macros. Something like:
Note the compiler emits the body's self-import independently of
MarkdownContent, so checking the generated prompt chunks rather than the markdown source may be more robust.A secondary guard would help regardless:
validate_prompt_placeholders.shcurrently passes a prompt containing an unresolved{{#runtime-import}}. Failing there would turn a silent no-op into a clear build error.Workaround
Adding any
{{#if ...}}block to the workflow body forceshasTemplatePatternto true and restores the step.Environment
gh awv0.83.4claude(@anthropic-ai/claude-code@2.1.214)awfv0.27.37repository_dispatch