Skip to content

feat(eval): honor UIPATH_AGENT_ID, UIPATH_CLOUD_USER_ID, UIPATH_PROJECT_FILES_SOURCE env vars [AE-1396]#1608

Merged
Chibionos merged 9 commits intomainfrom
fix/eval-honor-agent-id-env-vars
May 2, 2026
Merged

feat(eval): honor UIPATH_AGENT_ID, UIPATH_CLOUD_USER_ID, UIPATH_PROJECT_FILES_SOURCE env vars [AE-1396]#1608
Chibionos merged 9 commits intomainfrom
fix/eval-honor-agent-id-env-vars

Conversation

@Chibionos
Copy link
Copy Markdown
Contributor

@Chibionos Chibionos commented May 1, 2026

What

The SDK now distinguishes the logical agent the user authored from the file-source project the worker fetches files from. Previously these were collapsed onto UIPATH_PROJECT_ID, which works for cloud projects but is wrong for local-workspace eval runs (where prepareForCustomDebug creates a separate cloud debug project).

Three behaviors change:

  1. Eval API callbacks route by AgentId, not file-source project. The URL /api/execution/agents/{id}/evalRun and the agentId payload field now use the logical agent ID.
  2. Telemetry tags AgentId with the logical agent, not the file-source project — dashboards group by what the user authored.
  3. CloudUserId prefers the explicit env var over the JWT sub claim, so service-account-spawned workers tag the real triggering user.

File fetching (UiPathConfig.project_id, used by StudioClient / ResourceOverwritesContext in cli_eval.py and cli_debug.py) stays on the file-source project — that's where the worker's package files actually live.

Env var contract

Env var Meaning Notes
UIPATH_PROJECT_ID Cloud project the worker fetches package files from. Equals the agent ID for cloud projects; for local-workspace runs it is the debug project's GUID. UiPathConfig.project_id; StudioClient / ResourceOverwritesContext use it for file fetching.
UIPATH_AGENT_ID Logical agent the user authored. UiPathConfig.agent_id (falls back to project_id). Used for eval API URL routing in StudioWebProgressReporter and telemetry AgentId tagging.
UIPATH_CLOUD_USER_ID Real user who triggered the run. Eval + CLI telemetry prefer this over the JWT sub claim.
UIPATH_PROJECT_FILES_SOURCE Local or Cloud discriminator the UI filters by. Sent on every eval-run / eval-set-run POST/PUT payload and the resume GET as a query parameter, so rows match the UI's ?projectFilesSource=1 filter.

How env vars flow

sequenceDiagram
    autonumber
    actor U as User
    participant FE as Studio Web (FE)
    participant API as Agents Backend
    participant ORC as Orchestrator
    participant HDN as hdens worker (Python runtime)
    participant SDK as uipath-python SDK

    U->>FE: Start eval run
    FE->>API: POST /startMultipleEvaluators<br/>?debugProjectId={debugId}
    Note over API: Builds env vars:<br/>UIPATH_PROJECT_ID = debugProjectId ?? agentId<br/>UIPATH_AGENT_ID = real agentId<br/>UIPATH_CLOUD_USER_ID = session.UserId<br/>UIPATH_PROJECT_FILES_SOURCE = Local/Cloud
    API->>ORC: ServerlessStartJobDto envVars newline-joined
    ORC->>HDN: Dispatch job
    Note over HDN: PythonCodedJobExecutor<br/>EnsureEnvironmentVariablesParsed()<br/>(no allowlist - every UIPATH_* flows through)
    HDN->>HDN: os.environ.update(env_vars)<br/>(via cli_server.py for pooled mode)
    HDN->>SDK: Invoke uipath eval

    rect rgb(240, 248, 255)
        Note over SDK: API callbacks use UIPATH_AGENT_ID
        SDK->>API: POST /api/execution/agents/{UIPATH_AGENT_ID}/evalSetRun<br/>{ projectFilesSource: 1, ... }
        SDK->>API: POST /api/execution/agents/{UIPATH_AGENT_ID}/evalRun<br/>{ projectFilesSource: 1, ... }
        SDK->>API: GET /api/execution/agents/.../evalRuns<br/>?projectFilesSource=1
    end

    rect rgb(245, 245, 245)
        Note over SDK: File fetching uses UIPATH_PROJECT_ID (file source)
        SDK->>API: StudioClient(UIPATH_PROJECT_ID)<br/>(ResourceOverwritesContext)
    end

    rect rgb(248, 240, 255)
        Note over SDK: Telemetry tagged with both
        SDK->>SDK: properties[AgentId] = UIPATH_AGENT_ID<br/>properties[ProjectId] = UIPATH_PROJECT_ID<br/>properties[CloudUserId] = UIPATH_CLOUD_USER_ID
    end
Loading

For cloud runs, UIPATH_AGENT_ID and UIPATH_PROJECT_ID are equal — the diagram collapses to today's behaviour. For local-workspace runs they differ and the SDK keeps them straight.

Why this matters

  • Codex adversarial review flagged "the route now lies" — eval-run callbacks were hitting /agents/{debug-project}/evalRun even though the row should be attributed to the logical agent. Authz, telemetry dimensions, cache keys, and any future code consuming the route param would all see the debug project as if it were the agent.
  • Pooled cli_server.py cross-contamination is mitigated by the existing os.environ.clear() + update(baseline) + update(env_vars) pattern — every job request gets a fresh env. The new variables follow the same pipeline.
  • Backwards compatibility is preserved at every layer: missing env vars fall back to the legacy single-id behaviour. A worker running this SDK against an old backend (without UIPATH_AGENT_ID) falls back to UIPATH_PROJECT_ID and behaves identically to today.

Files touched

packages/uipath-platform/src/uipath/platform/common/constants.py        +5
packages/uipath-platform/src/uipath/platform/common/_config.py          +25
packages/uipath/src/uipath/_cli/_evals/_progress_reporter.py            +5/-3
packages/uipath/src/uipath/_cli/_evals/_telemetry.py                    +6/-7
packages/uipath/src/uipath/_cli/_telemetry.py                           +6/-7
packages/uipath/pyproject.toml                                          version + dep pin
packages/uipath-platform/pyproject.toml                                 version
packages/uipath-platform/tests/common/test_config_env_vars.py           +60 (new)
packages/uipath/tests/cli/eval/test_progress_reporter.py                +81 (new tests)

Tests

  • 10 test_config_env_vars.py — fallback chain for each property
  • 3 TestAgentIdRouting in test_progress_reporter.py — URL routing, payload field, fallback to project_id
1826 passed, 6 warnings in 12.65s

Ship sequence

  1. hdens #7038 — restores eval args after the #6929 regression. ✅ Merged 2026-05-01. Required for evals to run at all.
  2. This PR — SDK reads new env vars (gracefully degrades when unset).
  3. Agents #5160 — backend emits the env vars. After this, local-workspace telemetry tags the right user + agent.

Jira

🤖 Generated with Claude Code

Local-workspace eval runs distinguish two project IDs that the SDK had
been collapsing into one: the *file-source project* (cloud project the
worker fetches package files from) and the *logical agent* (the agent
the user authored). For cloud projects the two are equal; for local
workspaces they differ — file source is the per-run debug project's
GUID, agent is the user's local agent UUID.

When the worker runs under a service-account context (serverless),
its JWT carries the service account's `sub` claim, not the real
triggering user. Telemetry tagged from the JWT therefore attributes
runs to the wrong identity.

This change introduces three env vars the backend can set so the SDK
tags telemetry with the right identities:

- UIPATH_FILE_SOURCE_PROJECT_ID — preferred over UIPATH_PROJECT_ID for
  file-source semantics; falls back to UIPATH_PROJECT_ID so existing
  cloud deployments are unaffected.
- UIPATH_AGENT_ID — the logical agent. Telemetry "AgentId" is now
  tagged with this when set, falling back to the file-source project
  for cloud runs.
- UIPATH_CLOUD_USER_ID — the real user. Eval and CLI telemetry prefer
  this over the JWT sub claim, falling back to the JWT for older
  backends.

The route URL the SDK uses for eval-run callbacks is unchanged
(stays on file-source project) — backend-side ownership inheritance
in CreateEvalRunAsync handles the AgentId/CloudUserId attribution
end-to-end. This SDK change is the telemetry/observability half.

10 new tests in packages/uipath-platform/tests/common/ cover the
fallback chain for each property. Existing CLI telemetry tests
unchanged and still pass.

Refs: AE-1396, PC-4407
@github-actions github-actions Bot added test:uipath-langchain Triggers tests in the uipath-langchain-python repository test:uipath-integrations labels May 1, 2026
1. Pin uipath-platform>=0.1.43 in uipath/pyproject.toml. The new
   UiPathConfig.agent_id / cloud_user_id properties only exist after the
   0.1.43 bump; the old >=0.1.42 constraint allowed a skewed install
   where uipath==2.10.61 calls AttributeError-raising properties.

2. Restrict the CLI telemetry AgentId override to the explicit
   UIPATH_AGENT_ID env var instead of UiPathConfig.agent_id (which
   falls back to project_id). Prevents silent regression of non-eval
   CLI contexts that set UIPATH_PROJECT_ID — those continue to tag
   AgentId from PROJECT_KEY as before.

Refs: AE-1396
Copy link
Copy Markdown
Contributor

@AAgnihotry AAgnihotry left a comment

Choose a reason for hiding this comment

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

where are we passing these values to the eval runs and evalset runs

Chibionos added 3 commits May 1, 2026 12:39
The SDK's StudioWebProgressReporter was using UIPATH_PROJECT_ID for
both the API URL (/api/execution/agents/{id}/evalRun) and the file
fetch context. For local-workspace runs those are different IDs:
file source is the cloud debug project's GUID, agent is the user's
logical agent.

Honoring the AgentId in API calls so the route URL reflects the real
logical agent. File fetching (UiPathConfig.project_id, used by
StudioClient/ResourceOverwritesContext in cli_eval.py) keeps using
the file-source project, since that is where the worker's package
files live.

Changes:
- StudioWebProgressReporter now exposes self._agent_id (UIPATH_AGENT_ID
  with fallback to self._project_id). Every API URL construction and
  the agentId payload field now use _agent_id.
- self._project_id is preserved for the file-source semantic (env-var
  fallback for AgentId resolution); no remaining read sites in the
  reporter, but kept as the explicit "if file source ever needs
  callbacks" hook.

Tests added in TestAgentIdRouting (test_progress_reporter.py):
- _agent_id used in URL when both UIPATH_AGENT_ID and UIPATH_PROJECT_ID set
- agentId payload field carries _agent_id, not file source
- Falls back to project_id (file source) when UIPATH_AGENT_ID unset

1826 reporter tests pass (3 new).

Refs: AE-1396
… UI filter

projectFilesSource is the Local/Cloud discriminator the UI filters by
(`?projectFilesSource=1` for local-workspace runs), not a project ID.
Until now the SDK didn't send it on the eval-run / eval-set-run
callbacks, so the backend created every worker-spawned row defaulting
to Cloud and the UI's local-runs filter never matched them.

Reads UIPATH_PROJECT_FILES_SOURCE (string Local/Cloud) once at reporter
construction and maps it to the backend's enum integer (Local=1,
Cloud=0). Adds it to:

  POST   eval set run                  payload
  POST   eval run                       payload
  PUT    eval run (legacy)              payload
  PUT    eval run (coded)               payload
  PUT    eval set run                   payload
  GET    eval runs (resume lookup)      query parameter

When the env var is unset (cloud-project case or older backend that
doesn't emit it) the field is omitted from payloads/params, preserving
existing behaviour.

14 new tests in TestProjectFilesSourcePropagation covering the
parametrized env-var resolution (Local/Cloud/numeric/garbage), each of
the six request shapes carries the right value, and absence-omits-field.

1840 reporter tests pass.

Refs: AE-1396
UIPATH_PROJECT_ID already carries the file-source semantic (cloud
project the worker fetches files from). UIPATH_FILE_SOURCE_PROJECT_ID
was an alias that added a third name for the same value without
adding meaning.

UiPathConfig.project_id now reads UIPATH_PROJECT_ID directly — no
fallback chain. UiPathConfig.agent_id still falls back to project_id
when UIPATH_AGENT_ID is unset (cloud-project case where the two are
equal).

Updated config tests; existing reporter/CLI telemetry behaviour
unchanged.

Refs: AE-1396
@mjnovice mjnovice requested a review from AAgnihotry May 1, 2026 23:31
@Chibionos Chibionos changed the title feat(eval): honor UIPATH_AGENT_ID, UIPATH_CLOUD_USER_ID, UIPATH_FILE_SOURCE_PROJECT_ID env vars [AE-1396] feat(eval): honor UIPATH_AGENT_ID, UIPATH_CLOUD_USER_ID, UIPATH_PROJECT_FILES_SOURCE env vars [AE-1396] May 1, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 2, 2026

🚨 Heads up: uipath-langchain cross-tests are FAILING 🚨

Your changes may break the uipath-langchain-python integration.

⚠️ These checks are NOT enforced by branch protection rules. Please review the failures before merging.

🔍 Inspect the failed run →

@Chibionos Chibionos merged commit af3602e into main May 2, 2026
242 of 245 checks passed
@Chibionos Chibionos deleted the fix/eval-honor-agent-id-env-vars branch May 2, 2026 00:12
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.

3 participants