🤖 AI Assisted bug report
Summary
When a gh-aw compiled workflow is invoked as a reusable workflow (workflow_call) instead of workflow_dispatch, ${{ inputs.* }} expressions in the .md prompt body are not resolved. The agent sees the literal text ${{ inputs.errors }} instead of the actual value.
Reproduction
- Create an agentic workflow (
.md) with both workflow_call and workflow_dispatch triggers, and ${{ inputs.some_input }} in the prompt body
- Compile with
gh aw compile
- Call it from another workflow using
uses: + with: (reusable workflow pattern)
- The agent receives the literal
${{ inputs.some_input }} text — the value is never substituted
Dispatching the same workflow via workflow_dispatch works correctly.
Root Cause
In actions/setup/js/runtime_import.cjs, the evaluateExpression() function resolves expressions differently depending on their prefix:
needs.* and steps.* (line ~275): Converted to GH_AW_* env var names and looked up in process.env. This works because the compiler sets these env vars in the lock file's "Create prompt" step.
inputs.*: Does NOT get the env var lookup. Falls through to the GitHub context path (line ~306): inputs: context.payload?.inputs || {}. For workflow_dispatch, context.payload.inputs is populated by GitHub Actions. For workflow_call, it is not — the inputs are delivered differently.
The compiler already generates the correct env vars (e.g., GH_AW_INPUTS_ERRORS: ${{ inputs.errors }}), and GitHub Actions resolves them in YAML for both trigger types. The values are available in process.env — the runtime just never reads them for inputs.* expressions.
Suggested Fix
Add inputs.* to the env var lookup condition at line ~275 of runtime_import.cjs:
// Before:
if (trimmed.startsWith("needs.") || trimmed.startsWith("steps.")) {
// After:
if (trimmed.startsWith("needs.") || trimmed.startsWith("steps.") || trimmed.startsWith("inputs.")) {
This makes inputs.errors resolve to process.env.GH_AW_INPUTS_ERRORS — the same pattern that already works for needs.* and steps.*.
Why It Was Not Caught
The existing workflow_call smoke test (smoke-workflow-call.md) declares no inputs and uses no ${{ inputs.* }} expressions in its prompt body, so this code path was never exercised.
Context
We discovered this while converting the a workflow from workflow_dispatch (fire-and-forget) to workflow_call (reusable workflow) so two workflows would appear as nodes in a single GitHub Actions run graph.
🤖 AI Assisted bug report
Summary
When a gh-aw compiled workflow is invoked as a reusable workflow (
workflow_call) instead ofworkflow_dispatch,${{ inputs.* }}expressions in the.mdprompt body are not resolved. The agent sees the literal text${{ inputs.errors }}instead of the actual value.Reproduction
.md) with bothworkflow_callandworkflow_dispatchtriggers, and${{ inputs.some_input }}in the prompt bodygh aw compileuses:+with:(reusable workflow pattern)${{ inputs.some_input }}text — the value is never substitutedDispatching the same workflow via
workflow_dispatchworks correctly.Root Cause
In
actions/setup/js/runtime_import.cjs, theevaluateExpression()function resolves expressions differently depending on their prefix:needs.*andsteps.*(line ~275): Converted toGH_AW_*env var names and looked up inprocess.env. This works because the compiler sets these env vars in the lock file's "Create prompt" step.inputs.*: Does NOT get the env var lookup. Falls through to the GitHub context path (line ~306):inputs: context.payload?.inputs || {}. Forworkflow_dispatch,context.payload.inputsis populated by GitHub Actions. Forworkflow_call, it is not — the inputs are delivered differently.The compiler already generates the correct env vars (e.g.,
GH_AW_INPUTS_ERRORS: ${{ inputs.errors }}), and GitHub Actions resolves them in YAML for both trigger types. The values are available inprocess.env— the runtime just never reads them forinputs.*expressions.Suggested Fix
Add
inputs.*to the env var lookup condition at line ~275 ofruntime_import.cjs:This makes
inputs.errorsresolve toprocess.env.GH_AW_INPUTS_ERRORS— the same pattern that already works forneeds.*andsteps.*.Why It Was Not Caught
The existing
workflow_callsmoke test (smoke-workflow-call.md) declares no inputs and uses no${{ inputs.* }}expressions in its prompt body, so this code path was never exercised.Context
We discovered this while converting the a workflow from
workflow_dispatch(fire-and-forget) toworkflow_call(reusable workflow) so two workflows would appear as nodes in a single GitHub Actions run graph.