Summary
In the agent job of the Autotriage workflow, the trace that plengauer/opentelemetry-github/actions/instrument/job (job-level instrumentation) establishes for the job is not the trace that ends up used by the agentic workflow's own built-in observability (GITHUB_AW_OTEL_TRACE_ID / GITHUB_AW_OTEL_PARENT_SPAN_ID, consumed by the "Execute GitHub Copilot CLI" step). The job ends up with two disconnected root traces instead of one continuous trace.
Job log: https://github.com/plengauer/Thoth/actions/runs/30767171258/job/91547886181 (run 30767171258, job 91547886181, workflow Autotriage)
Evidence from the log (all times 2026-08-02, UTC)
-
21:08:41.766 — instrument/job establishes the job's trace and logs it:
##[notice]Trace ID: 896c8b337f1f4384ffeeda32a25895a2, Span ID: 310e31cbf9a51834, Trace Deep Link: ...
From here on, every step's env: block shows TRACEPARENT: 00-896c8b337f1f4384ffeeda32a25895a2-310e31cbf9a51834-03 (confirmed through step 24, "Audit pre-agent workspace", at 21:12:58).
-
21:08:41.839 — the very next step, "Setup Scripts" (github/gh-aw-actions/setup@34802437a...), is invoked with:
with:
destination: /home/runner/work/_temp/gh-aw/actions
job-name: agent
trace-id: 88bab49c6b45aa6d94f70a47ec31309f
parent-span-id: 908aa33a2bbf75dc
— a different trace/span than step 1, even though this same step's own env: block still shows TRACEPARENT: 00-896c8b...-310e31c...-03.
-
21:10:15.998 – 21:10:16.020 — "Setup Scripts"'s own internal logic ([otlp]-prefixed logs) processes those inputs:
[otlp] INPUT_TRACE_ID=88bab49c6b45aa6d94f70a47ec31309f (will reuse activation trace)
[otlp] INPUT_PARENT_SPAN_ID=908aa33a2bbf75dc (will parent setup span)
[otlp] GH_AW_OTLP_ENDPOINTS not set, skipping setup span
[otlp] resolved trace-id=88bab49c6b45aa6d94f70a47ec31309f
[otlp] trace-id=88bab49c6b45aa6d94f70a47ec31309f written to GITHUB_OUTPUT
[otlp] span-id=29a10ff7983cd05d written to GITHUB_OUTPUT
[otlp] parent-span-id=908aa33a2bbf75dc written to GITHUB_OUTPUT
[otlp] GITHUB_AW_OTEL_TRACE_ID written to GITHUB_ENV
[otlp] GITHUB_AW_OTEL_PARENT_SPAN_ID written to GITHUB_ENV
→ GITHUB_AW_OTEL_TRACE_ID=88bab49c6b45aa6d94f70a47ec31309f, GITHUB_AW_OTEL_PARENT_SPAN_ID=29a10ff7983cd05d.
-
21:13:04.818 — step 25, "Execute GitHub Copilot CLI" (the actual agent invocation, and what the built-in observability of the agentic workflow instruments), shows:
TRACEPARENT: 00-88bab49c6b45aa6d94f70a47ec31309f-29a10ff7983cd05d-01
i.e. the trace from step 3, not the job trace from step 1. Every other step in the job (before and after step 25) keeps using 896c8b....
Net result: two disconnected root traces for one job — 896c8b337f1f4384ffeeda32a25895a2 for ordinary job-level instrumentation, 88bab49c6b45aa6d94f70a47ec31309f for the agent's own execution/observability — rather than a single trace covering the whole job.
Where 88bab49c.../908aa33a... comes from
.github/workflows/autotriage.lock.yml (compiled output — autotriage.md, the hand-authored source, has no OTel/tracing config at all, so this wiring comes from gh aw compile) wires the agent job's Setup Scripts step to the upstream activation job's own setup outputs:
# autotriage.lock.yml, agent job (lines 424, 434-444)
- uses: plengauer/opentelemetry-github/actions/instrument/job@2169fb0fa9a8260fde99a2a185bbf99a5d63546e # v5.59.0
...
- name: Setup Scripts
id: setup
uses: github/gh-aw-actions/setup@34802437a0cba2fd1352d1f1bb02c18a78b56b31 # v0.83.0
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
and, only for the agent-execution step (line 882):
env:
...
TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }}
So 88bab49c.../908aa33a... is what the activation job's own Setup Scripts step produced (job 91547839105, https://github.com/plengauer/Thoth/actions/runs/30767171258/job/91547839105 — that job's gh-aw-actions/setup call also gets no explicit trace-id/parent-span-id, so it self-generates one). It has no relationship to the agent job's own job-level trace (896c8b...) that instrument/job established a fraction of a second earlier, in the same job.
The same pattern (trace-id/parent-span-id sourced from needs.activation.outputs.*, same TRACEPARENT override on the agent-execution step) also appears in the detection job of this workflow (lock file lines ~1062-1077, ~1495), and the same output block shows up in autofix.lock.yml, autoapprove.lock.yml, and monitor_changelog.lock.yml. I have not checked those jobs' own logs, so I can't confirm they show the identical divergence — flagging it only as a plausible wider scope based on the compiled YAML looking the same.
What I could find of "the custom instrumentation"
Looking in plengauer/opentelemetry-github (the job-level instrumentation) for something that would make it accept or reuse an inherited trace-id/parent-span-id instead of always minting a fresh one:
actions/instrument/job/action.yml declares no trace-id / parent-span-id / similar input at all — only github_token, cache, secrets_to_redact, self_monitoring, self_monitoring_anonymize, debug, and the internal __job_status / __job_matrix / __job_id.
- The one gh-aw-aware piece of custom logic I found is in
actions/instrument/job/decorate_action.sh, line 229:
if [ "$exit_code" = 0 ] && ( [ "${GITHUB_ACTION_REPOSITORY:-}" = github/gh-aw ] || [ "${GITHUB_ACTION_REPOSITORY:-}" = github/gh-aw-actions ] ) && [ "${GITHUB_STEP:-$GITHUB_ACTION}" = setup ] && [ -d "${INPUT_DESTINATION:-}" ]; then
find "${INPUT_DESTINATION}" -name "*.sh" 2>/dev/null | while IFS= read -r script_file; do
sed -i 's~#!/bin/sh~#!/bin/sh\n. otel.sh~g' "$script_file" 2>/dev/null || true
sed -i 's~#!/bin/bash~#!/bin/bash\n. otel.sh~g' "$script_file" 2>/dev/null || true
done || true
[ -n "${OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT:-}" ] || echo OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=span_and_event >> "$GITHUB_ENV"
echo "::debug::Instrumented agentic workflows"
fi
This fires specifically when decorating the gh-aw Setup Scripts step — confirmed for this run, since OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT: span_and_event shows up in every step's env: from "Setup Scripts" onward. But it only (a) sources otel.sh into the *.sh scripts gh-aw copies into place, so later ordinary bash steps get shell-level instrumentation, and (b) sets the GenAI content-capture env var. It doesn't touch trace-id/parent-span-id at all, so this isn't a "reuse the trace" mechanism.
- The actual
[otlp] INPUT_TRACE_ID=... (will reuse activation trace) logic lives in github/gh-aw's and github/gh-aw-actions' own actions/setup/js/action_setup_otlp.cjs (upstream, third-party — not plengauer/opentelemetry-github). It just faithfully reuses whatever trace-id/parent-span-id it's handed; in this run that happens to be the activation job's self-generated trace rather than the current job's own trace.
I wasn't able to locate a piece of code in plengauer/opentelemetry-github that fakes/forwards a trace-id/parent-span-id so that a job's own instrument/job trace gets picked up by that same job's gh-aw-actions/setup call. If such a mechanism is supposed to exist, I couldn't find where — flagging that as a gap rather than guessing.
Possibly unrelated
In the same window where instrument/job establishes the trace, its "Start Observation" step also logs:
21:08:41.7277327Z jq: error (at <stdin>:0): null (null) has no keys
Not clear if it's connected to the above; noting it since it's in the same phase of execution.
Not attempting to root-cause or fix this here — just documenting what the log and compiled workflow show.
Summary
In the
agentjob of theAutotriageworkflow, the trace thatplengauer/opentelemetry-github/actions/instrument/job(job-level instrumentation) establishes for the job is not the trace that ends up used by the agentic workflow's own built-in observability (GITHUB_AW_OTEL_TRACE_ID/GITHUB_AW_OTEL_PARENT_SPAN_ID, consumed by the "Execute GitHub Copilot CLI" step). The job ends up with two disconnected root traces instead of one continuous trace.Job log: https://github.com/plengauer/Thoth/actions/runs/30767171258/job/91547886181 (run
30767171258, job91547886181, workflowAutotriage)Evidence from the log (all times
2026-08-02, UTC)21:08:41.766 —
instrument/jobestablishes the job's trace and logs it:From here on, every step's
env:block showsTRACEPARENT: 00-896c8b337f1f4384ffeeda32a25895a2-310e31cbf9a51834-03(confirmed through step 24, "Audit pre-agent workspace", at 21:12:58).21:08:41.839 — the very next step, "Setup Scripts" (
github/gh-aw-actions/setup@34802437a...), is invoked with:— a different trace/span than step 1, even though this same step's own
env:block still showsTRACEPARENT: 00-896c8b...-310e31c...-03.21:10:15.998 – 21:10:16.020 — "Setup Scripts"'s own internal logic (
[otlp]-prefixed logs) processes those inputs:→
GITHUB_AW_OTEL_TRACE_ID=88bab49c6b45aa6d94f70a47ec31309f,GITHUB_AW_OTEL_PARENT_SPAN_ID=29a10ff7983cd05d.21:13:04.818 — step 25, "Execute GitHub Copilot CLI" (the actual agent invocation, and what the built-in observability of the agentic workflow instruments), shows:
i.e. the trace from step 3, not the job trace from step 1. Every other step in the job (before and after step 25) keeps using
896c8b....Net result: two disconnected root traces for one job —
896c8b337f1f4384ffeeda32a25895a2for ordinary job-level instrumentation,88bab49c6b45aa6d94f70a47ec31309ffor the agent's own execution/observability — rather than a single trace covering the whole job.Where
88bab49c.../908aa33a...comes from.github/workflows/autotriage.lock.yml(compiled output —autotriage.md, the hand-authored source, has no OTel/tracing config at all, so this wiring comes fromgh aw compile) wires theagentjob'sSetup Scriptsstep to the upstreamactivationjob's own setup outputs:and, only for the agent-execution step (line 882):
So
88bab49c.../908aa33a...is what the activation job's ownSetup Scriptsstep produced (job91547839105, https://github.com/plengauer/Thoth/actions/runs/30767171258/job/91547839105 — that job'sgh-aw-actions/setupcall also gets no explicittrace-id/parent-span-id, so it self-generates one). It has no relationship to theagentjob's own job-level trace (896c8b...) thatinstrument/jobestablished a fraction of a second earlier, in the same job.The same pattern (trace-id/parent-span-id sourced from
needs.activation.outputs.*, sameTRACEPARENToverride on the agent-execution step) also appears in thedetectionjob of this workflow (lock file lines ~1062-1077, ~1495), and the same output block shows up inautofix.lock.yml,autoapprove.lock.yml, andmonitor_changelog.lock.yml. I have not checked those jobs' own logs, so I can't confirm they show the identical divergence — flagging it only as a plausible wider scope based on the compiled YAML looking the same.What I could find of "the custom instrumentation"
Looking in
plengauer/opentelemetry-github(the job-level instrumentation) for something that would make it accept or reuse an inherited trace-id/parent-span-id instead of always minting a fresh one:actions/instrument/job/action.ymldeclares notrace-id/parent-span-id/ similar input at all — onlygithub_token,cache,secrets_to_redact,self_monitoring,self_monitoring_anonymize,debug, and the internal__job_status/__job_matrix/__job_id.actions/instrument/job/decorate_action.sh, line 229:Setup Scriptsstep — confirmed for this run, sinceOTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT: span_and_eventshows up in every step'senv:from "Setup Scripts" onward. But it only (a) sourcesotel.shinto the*.shscripts gh-aw copies into place, so later ordinary bash steps get shell-level instrumentation, and (b) sets the GenAI content-capture env var. It doesn't touchtrace-id/parent-span-idat all, so this isn't a "reuse the trace" mechanism.[otlp] INPUT_TRACE_ID=... (will reuse activation trace)logic lives ingithub/gh-aw's andgithub/gh-aw-actions' ownactions/setup/js/action_setup_otlp.cjs(upstream, third-party — notplengauer/opentelemetry-github). It just faithfully reuses whatevertrace-id/parent-span-idit's handed; in this run that happens to be theactivationjob's self-generated trace rather than the current job's own trace.I wasn't able to locate a piece of code in
plengauer/opentelemetry-githubthat fakes/forwards atrace-id/parent-span-idso that a job's owninstrument/jobtrace gets picked up by that same job'sgh-aw-actions/setupcall. If such a mechanism is supposed to exist, I couldn't find where — flagging that as a gap rather than guessing.Possibly unrelated
In the same window where
instrument/jobestablishes the trace, its "Start Observation" step also logs:Not clear if it's connected to the above; noting it since it's in the same phase of execution.
Not attempting to root-cause or fix this here — just documenting what the log and compiled workflow show.