Skip to content

fix(governance): mark the governance run span for export - #168

Closed
JoshParkSJ wants to merge 1 commit into
mainfrom
fix/governance-root-span-orphans-agent-run
Closed

fix(governance): mark the governance run span for export#168
JoshParkSJ wants to merge 1 commit into
mainfrom
fix/governance-root-span-orphans-agent-run

Conversation

@JoshParkSJ

@JoshParkSJ JoshParkSJ commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Problem

Conversational agent run spans stopped showing up under the CAS Exchange span — on prod rings 1-5 and staging. (Slack thread)

In the sample production trace, the agent run span points at a parent id that isn't in the trace at all:

span id parent
Exchange 380056a28af21b0d Conversation
Conversational agent run 52f13179f466cf8f 8eb59fa2b10766c8 — not present

So it's a dropped parent, not a mis-parented child.

Cause

_governance_root_span opens a uipath.governance.run span around every execute / stream, which sits between the host's span and the agent's own run span.

Hosts filter spans on export. The Agents LLMOps exporter keeps only spans carrying uipath.custom_instrumentation and drops the rest without re-parenting their children. This span didn't carry the marker, so it never reached the backend — while the agent run span still referenced it. The agent run span and its whole subtree detached from the host's trace.

Same reason the BEFORE_AGENT guardrail rule spans (guardrail-harmful-content, -prompt-injection, -pii) surface at the trace root: they fire before the agent run span exists, so their parent was the dropped span too. The rule spans that fire during the model hooks are parented on the agent run span and look correct.

Note this is not the Governance evaluation span from LLM Gateway — that one is correctly nested under LLM call. Two similarly-named spans; the thread chased the wrong one for a bit.

Fix

Add the marker so the span survives export and the chain stays whole: Exchangeuipath.governance.run → agent run.

Also sets type / span_type / uipath.source, matching what the per-rule governance spans in TracesAuditSink already set, so it renders as a governance span rather than an unknown span type.

This makes uipath.governance.run visible in customer-facing traces as a new level between Exchange and the agent run. That's the intended trade — flagging it explicitly since it changes what customers see. The alternative was skipping the span entirely when a host span already exists (the host's span supplies the trace_id that is the wrapper's only purpose there), which fixes the tree with no UI change but gives up the span. Happy to switch if you'd rather it stay internal.

Follow-up worth doing separately

The export filter in uipath-agents-python should re-parent survivors to their nearest surviving ancestor. Any future filtered span will orphan its children exactly this way.

Tests

Two added to tests/test_governance_runtime.py:

  • the span carries the export marker and the type attributes, keeps its existing agent_name / runtime_id, and stays a child of the host's span
  • stream marks the span the same way execute does

Full suite passes (434).

🤖 Generated with Claude Code

@JoshParkSJ
JoshParkSJ force-pushed the fix/governance-root-span-orphans-agent-run branch 2 times, most recently from 0671b94 to b6d0623 Compare September 10, 2026 14:42
@JoshParkSJ JoshParkSJ changed the title fix(governance): don't wrap the agent run in a span when the host has one fix(governance): mark the governance run span for export Sep 10, 2026
The governance runtime opens a `uipath.governance.run` span around
every agent invocation, between the host's span and the agent's own
run span. Hosts filter spans on export — the Agents LLMOps exporter
keeps only spans carrying `uipath.custom_instrumentation` and drops
the rest without re-parenting their children. This span didn't carry
the marker, so it was dropped while the agent run span still
referenced it, leaving the agent run span pointing at a parent id
that never reached the backend.

Observed in production: conversational agent run spans stopped
appearing under the CAS Exchange span across prod rings 1-5 and
staging, and the BEFORE_AGENT guardrail rule spans surfaced at the
trace root for the same reason.

Add the marker, plus the `type` / `span_type` / `uipath.source`
attributes the per-rule governance spans already set, so the span
renders as governance rather than an unknown span type.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@JoshParkSJ

Copy link
Copy Markdown
Contributor Author

Alternative approach in #169 — skips the span entirely when the host already has one, instead of marking it for export. Same bug, different trade: #169 leaves customer traces unchanged but gives up the span; this one keeps the span but adds a level between Exchange and the agent run. Pick one, close the other.

@sonarqubecloud

Copy link
Copy Markdown

@JoshParkSJ

Copy link
Copy Markdown
Contributor Author

Closing in favor of #169@viswa-uipath approved that approach. The governance run span stays internal rather than appearing in customer-facing traces.

@JoshParkSJ JoshParkSJ closed this Sep 10, 2026
@JoshParkSJ
JoshParkSJ deleted the fix/governance-root-span-orphans-agent-run branch September 10, 2026 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant