Skip to content

feat: add uipath headers llm calls#663

Merged
cotovanu-cristian merged 5 commits intomainfrom
feat/headers-llm-calls
Mar 5, 2026
Merged

feat: add uipath headers llm calls#663
cotovanu-cristian merged 5 commits intomainfrom
feat/headers-llm-calls

Conversation

@cotovanu-cristian
Copy link
Copy Markdown
Collaborator

@cotovanu-cristian cotovanu-cristian commented Mar 4, 2026

Uniform UiPath headers and service URL override support for chat models

Summary

  • Centralize all UiPath HTTP headers into a single build_uipath_headers() function in a new chat/http_client/ package, replacing per-model header construction
  • Add context headers (x-uipath-jobkey, x-uipath-folderkey, x-uipath-traceid) read directly from environment variables across all LLM chat models (OpenAI, Vertex, Bedrock) and the RequestMixin
  • Couple chat models into the platform's service URL override system via resolve_gateway_url(), enabling UIPATH_SERVICE_URL_AGENTHUB=http://localhost:PORT to redirect LLM gateway traffic for local development
  • Inject routing headers (X-UiPath-Internal-TenantId, X-UiPath-Internal-AccountId) automatically when a service URL override is active, since the platform routing layer is bypassed
  • Consolidate HTTP-related modules by moving header_capture.py and retryers/ under chat/http_client/

Changes


┌─────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  │            Area             │                                                                                            What changed                                                                                            │
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ chat/http_client/headers.py │ New shared build_uipath_headers(token, *, agenthub_config, byo_connection_id, inject_routing) — builds Authorization, context headers, process key (percent-encoded), and optional routing headers │
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ chat/http_client/url.py     │ New resolve_gateway_url(endpoint) -> (url, is_override) — checks UIPATH_SERVICE_URL_<SERVICE> override, falls back to UIPATH_URL                                                                   │
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ chat/openai.py              │ _build_base_url() → _resolve_url(), _build_headers() uses shared function with inject_routing                                                                                                      │
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ chat/vertex.py              │ _build_base_url() → _resolve_url(), _build_headers() uses shared function with inject_routing                                                                                                      │
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ chat/bedrock.py             │ _build_base_url() → _resolve_url(), _modify_request() uses shared function with inject_routing                                                                                                     │
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ _utils/_request_mixin.py    │ url property uses resolve_gateway_url(), auth_headers passes inject_routing flag; removed hardcoded X-UiPath-JobKey/X-UiPath-ProcessKey from default_headers                                       │
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ chat/http_client/           │ Moved header_capture.py and retryers/ here from chat/                                                                                                                                              │
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ Tests                       │ 3 new test files (27 tests) covering headers, encoding, and URL resolution                                                                                                                         │
  └─────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

@cotovanu-cristian cotovanu-cristian changed the title Feat/headers llm calls feat: add uipath headers llm calls Mar 4, 2026
@cotovanu-cristian cotovanu-cristian marked this pull request as ready for review March 4, 2026 13:52
Comment thread src/uipath_langchain/chat/http_client/url.py
if process_key := os.getenv("UIPATH_PROCESS_KEY"):
headers["X-UiPath-ProcessKey"] = quote(process_key, safe="")
if job_key := os.getenv("UIPATH_JOB_KEY"):
headers["x-uipath-jobkey"] = job_key
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.

The old code used X-UiPath-JobKey, not sure if casing matters or not.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

yep, let s be consistent with casing

Copy link
Copy Markdown
Collaborator Author

@cotovanu-cristian cotovanu-cristian Mar 5, 2026

Choose a reason for hiding this comment

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

fair points; I get:

  1. consistency in the same file
  2. consistency for all uipath headers used

For point 2 I lower cased them as per the source of truth for headers in uipath-python: https://github.com/UiPath/uipath-python/blob/1869a9625e9da3957bf0a379325341b904150494/packages/uipath/src/uipath/_utils/constants.py#L24-L30

I will actually export them from the uipath-platform-python package and reuse them here as the source of truth and this would address both points you;ve raised.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

as for the casing, according to the http RFC and mozilla docs the HTTP headers would be case insensitive such that I'll keep them lowercase:

  1. https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers
  2. https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

self.access_token,
agenthub_config=self.agenthub_config,
byo_connection_id=self.byo_connection_id,
inject_routing=self._is_override,
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.

if auth_headers() is called before url(), self._is_override will be False, right now the ordering is correct but might be problematic in the future.

if tenant_id := os.getenv("UIPATH_TENANT_ID"):
headers["X-UiPath-Internal-TenantId"] = tenant_id
if organization_id := os.getenv("UIPATH_ORGANIZATION_ID"):
headers["X-UiPath-Internal-AccountId"] = organization_id
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.

Are X-UiPath-Internal-AccountId and X-UiPath-Internal-TenantId new headers? Who needs them? Is it APIM? Then why not always having them when calling an UiPath URL?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

these would get called only for the local dev flow as per the conditions to inject_routing

cotovanu-cristian and others added 4 commits March 5, 2026 14:32
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move all shared HTTP concerns (headers, header capture, retryers) into
a new chat/http_client subpackage. Introduce build_uipath_headers() as
the single entry point for building UiPath LLM Gateway headers across
OpenAI, Vertex, and Bedrock providers. Context headers (job_key,
folder_key, trace_id) now read directly from env vars like process_key.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add resolve_gateway_url() to integrate all chat models with the
platform's per-service URL override system (UIPATH_SERVICE_URL_<SERVICE>
env vars). When an override is active, routing headers
(X-UiPath-Internal-TenantId/AccountId) are injected automatically since
the platform routing layer is bypassed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@cotovanu-cristian cotovanu-cristian merged commit 2126bba into main Mar 5, 2026
39 checks passed
@cotovanu-cristian cotovanu-cristian deleted the feat/headers-llm-calls branch March 5, 2026 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants