Optional: work through this deep-dive if you want to understand how data flows between steps, then return to Step 16.
GitHub Actions runs each step in its own shell process. That means a plain export MY_VAR=value in one step is invisible to the next step — the environment is thrown away when the step exits. $GITHUB_OUTPUT is the official mechanism for persisting data across steps.
# ❌ This looks reasonable but DOES NOT WORK
- name: Set a value
run: export RESULT="hello"
- name: Use the value
run: echo "$RESULT" # prints nothing — RESULT is goneEach step is a separate child process. Environment variables set with export only survive for the duration of that step.
Append a key=value pair to the file path stored in the $GITHUB_OUTPUT environment variable:
# ✅ Write a single-line value
echo "status=healthy" >> $GITHUB_OUTPUTTo read it back in a later step, reference ${{ steps.<id>.outputs.status }} — but first you need to give the writing step an id.
A step id is how you refer to its outputs elsewhere in the workflow. Add id: at the same level as name: and run::
- name: Check health
id: health_check
run: |
echo "status=healthy" >> $GITHUB_OUTPUTNow any later step (or the AI prompt) can reference:
${{ steps.health_check.outputs.status }}
A single echo "key=value" won't work for multi-line content because the newlines would break the key=value format. Use a heredoc delimiter instead:
# ✅ Write a multi-line value
echo "commit_log<<EOF" >> $GITHUB_OUTPUT
echo "$COMMIT_LOG" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUTThe three lines together tell GitHub Actions:
commit_log<<EOF— start a multi-line value namedcommit_log, usingEOFas the end marker.$COMMIT_LOG— the actual content (can span many lines).EOF— close the block.
You can use any unique string as the delimiter — EOF is just a convention.
Once your data is in $GITHUB_OUTPUT, you reference it directly inside the workflow Markdown body — which is the AI prompt in gh-aw. There is no separate step to invoke the AI; the body text is sent to the model after all step outputs have been resolved.
Frontmatter (data-preparation step):
steps:
- name: Fetch recent commits
id: recent
run: |
echo "commit_log<<EOF" >> $GITHUB_OUTPUT
git log --oneline -10 >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUTWorkflow body (the prompt):
Here are the recent commits:
${{ steps.recent.outputs.commit_log }}
Write a one-paragraph summary of this activity.The ${{ ... }} expression is resolved by GitHub Actions before the body is sent to the model, so the AI receives the fully expanded text.
- You can explain why
exportdoes not pass values between steps - You can write a single-line value to
$GITHUB_OUTPUT - You know how to give a step an
idand reference its outputs - You can use the
<<EOFheredoc syntax for multi-line values - You can reference step outputs inside an AI prompt
Return to Connect a Live Data Source to Your Workflow.