Skip to content

fix(traceview): make ReferenceId match the reference hierarchy leaf - #1911

Closed
jepadil23 wants to merge 3 commits into
mainfrom
fix/reference-id-hierarchy-leaf
Closed

jepadil23 wants to merge 3 commits into
mainfrom
fix/reference-id-hierarchy-leaf

Conversation

@jepadil23

@jepadil23 jepadil23 commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor
  • Bug: a span's top-level ReferenceId was resolved from a source unrelated to the id the runtime actually stamps, so it disagreed with both the referenceId attribute and the referenceHierarchy on every span.
  • What the runtime does: uipath-agents-python agent.py:135-151 takes one id — agent_definition.id, else UIPATH_PROCESS_UUID — and uses it for both the referenceId attribute and the ("agent", agent_id, …) hierarchy entry. Those two always agreed.
  • What the conversion layer did: _span_utils.py wrote attributes_dict["agentId"] = resolve_project_id() — a project id (uipath.json#id → UIPATH_AGENT_ID → UIPATH_PROJECT_ID → PROJECT_KEY, the same helper telemetry/_track.py uses to report project_id) — then computed reference_id = agentId or referenceId. The or ordering meant the project id always beat the agent id the runtime had stamped.
  • Fix: precedence is now referenceId attribute → hierarchy leaf → agentId.
  • Why referenceId first, not the leaf: the runtime stamps referenceId and pushes that same id onto the hierarchy, so the leaf is a consequence of the reference id, not its source. When a service fails to push its own entry (agent.py:149-150 falls back to parent_ctx on a non-UUID id), the hierarchy is still non-empty and its leaf holds the caller's id — deriving from it would file the span under maestro instead of the agent.
  • Why the leaf at all: it covers producers that push onto the hierarchy without stamping the attribute, e.g. uipath-langchain-python's langgraph entry, which otherwise falls through to the project id and diverges the same way.
  • Blast radius: agentId as a span attribute is untouched; only the top-level ReferenceId changes, and only for spans carrying a referenceId attribute or a hierarchy. Producers that emit neither keep the current behaviour.

Why it went unnoticed

resolve_project_id() returns None in a bare local checkout (no uipath.json#id, no env vars), so reference_id fell through to referenceId and matched. uipath init then backfills uipath.json#id — with str(uuid.uuid4()) when neither UIPATH_PROJECT_ID nor .uipath/.telemetry.json#ProjectKey is present (cli_init.py:436,445). From that point on a random GUID outranks the real agent id on every emitted span.

Behaviour

With uipath.json#id = 1111…, agent.json#id = 2222…, caller 3333…:

span before after
agent run (referenceId + hierarchy) 1111… 2222…
langgraph (hierarchy only, no attr) 1111… 2222…
push failed — leaf is the caller 1111… 2222… (not 3333…)
no hierarchy, no referenceId 1111… 1111… unchanged

Tests

  • Two cases in TestReferenceIdResolution asserted the old precedence and were updated; the class docstring now states the source/consequence relationship and why agentId is last.
  • Added cases for leaf-as-fallback, the unpushed-entry misattribution guard, malformed hierarchy JSON, and a leaf with no referenceId.
  • New TestReferenceIdMatchesHierarchyLeaf pins the invariant end-to-end against a populated project id.
  • uipath-platform suite green; ruff + mypy clean.

Note

agentId as a span attribute still carries a project id (_span_utils.py:471). That is a separate pre-existing naming problem and is deliberately out of scope here — changing what the backend receives for agentId is a bigger call than this fix.

🤖 Generated with Claude Code

ReferenceId and Context.referenceHierarchy were resolved from two
disjoint sources, so they disagreed on every span in any environment
where a project id exists.

Prefer the innermost referenceHierarchy entry, then an explicitly
stamped referenceId attribute, and only then the agentId attribute
(which carries a project id from resolve_project_id()).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 24, 2026 15:21
@github-actions github-actions Bot added test:uipath-langchain Triggers tests in the uipath-langchain-python repository test:uipath-integrations labels Sep 24, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

All reviewed changes align with the intended fix and regression coverage.

Review effort: Lite
Findings: None

What changed in this PR

Fixes span conversion so top-level ReferenceId matches the innermost reference hierarchy entry instead of the project ID.

Changes:

  • Prioritizes the hierarchy leaf, then referenceId, then agentId.
  • Reuses parsed hierarchy data for ID resolution and context.
  • Adds regression tests for precedence and ID mismatches.
File Description
packages/​uipath-platform/​tests/​services/​test_span_utils.py Updates and expands reference ID resolution tests.
packages/​uipath-platform/​tests/​services/​test_reference_context.py Adds hierarchy and ReferenceId consistency tests.
packages/​uipath-platform/​src/​uipath/​platform/​common/​_span_utils.py Implements hierarchy-aware reference ID resolution.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

jepadil23 and others added 2 commits September 24, 2026 08:31
0.2.32 is already published to PyPI, so the release job rejects it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The runtime stamps referenceId and pushes that same id onto the reference
hierarchy, so the leaf is a consequence of the reference id, not its source.

Reading the leaf first misattributes a span whenever a service fails to push
its own entry: the hierarchy is still non-empty and its leaf holds the
*caller's* id, so the span would be filed under the caller.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@jepadil23

Copy link
Copy Markdown
Contributor Author

Superseded. ReferenceId resolution predates the reference hierarchy and works as intended — changing it to satisfy the newer feature is the wrong direction, and it is a wire-visible change to every span. The divergence belongs at the push sites instead, where the hierarchy entry should carry the id ReferenceId already resolves to:

No change to uipath-python is needed.

@jepadil23 jepadil23 closed this Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:uipath-integrations test:uipath-langchain Triggers tests in the uipath-langchain-python repository

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants