GITHUB_STEP_SUMMARY for Sume jobs: an audit table in the run page
Write the Sume job id, status and artifact URL to GITHUB_STEP_SUMMARY: 1 MiB per step, 20 step summaries shown per job. Public URLs only, no prompts or keys.

A step can append Markdown to $GITHUB_STEP_SUMMARY, and GitHub shows it on the workflow run page. For a Sume job, write one table row with the job id, final status and artifact URL. GitHub allows 1 MiB per step and shows at most 20 step summaries per job, so a table of ids and links is tiny compared with the limit.
What GitHub documents
From GitHub's workflow commands reference:
| Topic | GitHub says |
|---|---|
| Size | 1 MiB per step |
| Shown | A maximum of 20 step summaries per job |
| Format | GitHub flavored Markdown: headings, lists, tables |
| Writing | Append with >> in Bash |
| Secrets | Secrets are masked |
A step that submits, waits and summarizes
The step below starts a Music Router job, polls until the job envelope says terminal, reads the audio artifact from the result, and appends the table. The Music Router charges a fixed $0.125 per generation. request_id in the submit response is the job id. The Idempotency-Key uses run_id, which does not change on a re-run, so a re-run reuses the same job instead of paying twice.
- name: Generate a bed and summarize
env:
SUME_API_KEY: ${{ secrets.SUME_API_KEY }}
run: |
H="Authorization: Bearer $SUME_API_KEY"
job=$(curl -fsS -X POST https://api.sume.com/v1/music-router/generate \
-H "$H" -H "Content-Type: application/json" \
-H "Idempotency-Key: gh-${{ github.run_id }}-bed" \
-d '{"prompt":"Warm lo-fi bed, 84 BPM, C minor. A 30-second track. Instrumental, no vocals."}' \
| jq -r .request_id)
until [ "$(curl -fsS https://api.sume.com/v1/jobs/$job/status -H "$H" | jq -r .terminal)" = true ]; do
sleep 10
done
url=$(curl -fsS https://api.sume.com/v1/jobs/$job/result -H "$H" \
| jq -r '[.result.artifacts[]? | select(.type=="audio")][0].url // "none"')
{
echo "### Sume music job"
echo "| job | audio |"
echo "|---|---|"
echo "| $job | $url |"
} >> "$GITHUB_STEP_SUMMARY"What belongs in the summary
Summaries are readable by anyone who can read the run. Write the job id, the status, the model that ran (job.request.routed_model on a router job) and the artifact URL. Leave out prompts that you consider private. GitHub masks secrets that it knows about, but it cannot know that a brief for an unreleased campaign is sensitive.
The job id is the useful part. GitHub keeps run logs for a limited time, and the id lets you read the job later from the Sume API or dashboard, long after the run page is gone.
Limits
Twenty summaries per job is a cap on steps, not on rows: put all jobs of a matrix leg in one step. A job that fails still needs a summary line, so write the table in a final step with if: always() that reads a small file the earlier steps appended. A loop that polls for ever burns runner minutes: add a step timeout and, if the job is still not terminal, record its id and exit. Never submit the paid request again just because the wait ended.
Sources
Related posts
More in Integrations
- workflow_dispatch music brief: 25 inputs, 65,535 chars vs Sume's 5,000
GitHub dispatch takes 25 inputs and 65,535 characters; Sume's music prompt stops at 5,000 and rejects duration. Guard the length, then call the router.
- Google Sheets =IMAGE() with a Sume URL: PNG, JPEG, never SVG
=IMAGE needs a URL with a protocol and rejects SVG and drive.google.com links. Put a Sume data[0].url from a png or jpeg request in a cell and pick a mode.
- Google Slides createImage with a Sume URL: use PNG or JPEG
CreateImageRequest takes PNG, JPEG or GIF, up to 50 MB and 25 megapixels, from a public URL of 2 KB or less. Ask Sume for output_format png or jpeg, not WebP.
- GPT-6.1 Sol function calling to start a Sume Agent Completion safely
Expose one function that starts an Agent Completion. Let GPT-6.1 Sol fill instruction and input, and keep the spend cap and idempotency key out of its args.
Written by Sume