feat: allow guardrail evaluation to carry attachment references - #1895
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
One or more issues must be addressed before approval.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Extends uipath-platform guardrail evaluation to send file attachment references to the backend.
Changes:
- Adds and exports
GuardrailAttachment. - Serializes attachments and applies an extended timeout.
- Adds tests and bumps the package version.
File summaries
| File | Description |
|---|---|
| packages/uipath-platform/tests/services/test_guardrails_service.py | Updated as part of this pull request. |
| packages/uipath-platform/src/uipath/platform/guardrails/guardrails.py | Updated as part of this pull request. |
| packages/uipath-platform/src/uipath/platform/guardrails/_guardrails_service.py | Updated as part of this pull request. |
| packages/uipath-platform/src/uipath/platform/guardrails/init.py | Updated as part of this pull request. |
| packages/uipath-platform/pyproject.toml | Updated as part of this pull request. |
Review details
- Files reviewed: 5/5 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
@Traced records a function's arguments on the OpenTelemetry span by default, so every GuardrailAttachment.url — a short-lived SAS credential — was landing in input.value. Flagged by Copilot on #1895. An input_processor now replaces attachments[*].url with "<redacted>" and leaves everything else (payload, guardrail, attachment identity) intact; that is tighter than hide_input=True, which would drop the useful part of the span too. Also adds the two tests Copilot noted were missing: that an attachment-bearing evaluation forwards the 60s timeout, and that the default path does not. uipath-platform: 35 tests pass (+4); ruff, ruff format, mypy clean. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Traced records a function's arguments on the OpenTelemetry span by default, so every GuardrailAttachment.url — a short-lived SAS credential — was landing in input.value. Flagged by Copilot on #1895. An input_processor now replaces attachments[*].url with "<redacted>" and leaves everything else (payload, guardrail, attachment identity) intact; that is tighter than hide_input=True, which would drop the useful part of the span too. Also adds the two tests Copilot noted were missing: that an attachment-bearing evaluation forwards the 60s timeout, and that the default path does not. uipath-platform: 35 tests pass (+4); ruff, ruff format, mypy clean. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
e831652 to
7145cf9
Compare
ba99f49 to
e475e89
Compare
🚨 Heads up:
|
Adds an optional `attachments` keyword to GuardrailsService.evaluate_guardrail and a GuardrailAttachment model (id, fileName, mimeType, url), so a caller can tell the guardrails backend which files a guardrail should inspect instead of the backend seeing only attachment metadata embedded in the payload string. Also forwards a 60s timeout when attachments are present. The default client timeout is 30s and RequestSpec.timeout was constructed but never passed, so a validate call that waits on server-side file fetching would have timed out. An attachment url is a short-lived SAS credential, and @Traced records a function's arguments on the span by default, so an input_processor redacts attachments[*].url and leaves the rest of the span intact. Backward compatible: without `attachments` — or with an empty list — the request body is byte-identical to today, so an older backend is unaffected. The parameter is keyword-only and defaults to None, so existing callers are untouched. Bumps uipath-platform to 0.2.31. SDK_REFERENCE.md records the new parameter, which makes uipath a co-changed package, so it bumps to 2.14.21 and raises its floor to uipath-platform>=0.2.31. uipath-platform: 35 tests pass (+8); ruff, ruff format and mypy clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Guardrail attachments are now referenced by their Orchestrator attachment id alone: GuardrailAttachment drops the `url` field the runtime used to resolve to a signed URL before sending it to the guardrails backend. Two problems with that: Orchestrator's signed URL shape is environment-dependent (a platform-proxied alpha.uipath.com URL on alpha, not *.blob.core.windows.net), so a host allow-list downstream silently dropped every attachment; and a caller-supplied URL meant the backend never verified the caller was entitled to the file it fetched. The backend now resolves each id through its own Orchestrator client, so Orchestrator's own access control applies. evaluate_guardrail sends the optional x-uipath-folderkey header (already defined as HEADER_FOLDER_KEY) alongside attachments when the SDK is configured with a folder key, so the backend can resolve folder-scoped attachments. The now-pointless URL-redaction input_processor on @Traced is removed along with the field it protected. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
main released 2.14.21 while this branch was carrying the same number, so check-version-availability rejected the PR. The package still has to move because SDK_REFERENCE.md changed and its uipath-platform floor is now 0.2.31. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2aeff72 to
f7d65ad
Compare
|
| Passed to [`GuardrailsService.evaluate_guardrail`][uipath.platform.guardrails.GuardrailsService.evaluate_guardrail] | ||
| so the guardrails backend can read the file's contents rather than only its metadata. | ||
|
|
||
| Only the Orchestrator attachment id crosses the wire: helix resolves it through |
There was a problem hiding this comment.
Don't refer the helix project name in the SDK docs please
There was a problem hiding this comment.
Addressed in #1903 — project name dropped and the surrounding comments trimmed.
| execution_source = self._execution_context.execution_source | ||
| if execution_source: | ||
| source_headers[HEADER_GUARDRAILS_SOURCE] = execution_source | ||
| # When attachments are present, tell helix which folder the run executed in |
There was a problem hiding this comment.
Same here. Drop the helix terminology. In fact, do we need this comment at all? Let's reduce the comments' verbosity and keep only what's really needed and useful.
There was a problem hiding this comment.
Addressed in #1903 — project name dropped and the surrounding comments trimmed.



What
Adds an optional
attachmentskeyword toGuardrailsService.evaluate_guardrailand aGuardrailAttachmentmodel (id,fileName,mimeType) so a caller can tell the guardrails backend which Orchestrator attachments a guardrail should inspect. When attachments are present the call also carries the run's folder key inx-uipath-folderkey(from the SDK config) so the backend can resolve them folder-scoped, and uses a 60 s timeout because the backend fetches and decodes each file inside the request.Backward compatible: without
attachmentsthe request body is byte-identical to today. Bumpsuipath-platformto 0.2.31 anduipathto 2.14.22 (itsSDK_REFERENCE.mdrecords the new parameter and its platform floor moves to 0.2.31).v2 — references instead of urls (commit
db3cd201)The first version carried a resolved SAS
urlper attachment and redacted it from the@tracedspan. The backend now resolves attachment ids itself through Orchestrator (see UiPath/Agents#6256), so theurlfield and the redaction processor are gone and the model is justid/fileName/mimeType. New: the folder-key header. 36 tests pass; ruff, ruff format and mypy clean.Review fixes
e831652c— SAS urls no longer reach the trace span.@tracedrecords a function's arguments on the OpenTelemetry span by default, so everyGuardrailAttachment.url(a short-lived SAS credential) was landing ininput.value. Aninput_processornow redactsattachments[*].urland leaves the rest of the span intact — tighter thanhide_input=True. Thanks Copilot.49b50329— lockfiles relocked after the version bump (uv lock --checkin CI).Notes for reviewers
attachments, or with an empty list, the request body is byte-identical to today.RequestSpec.timeoutwas constructed but never forwarded, so this passes 60 s explicitly when attachments are present.Test plan
packages/uipath-platform— 35 tests pass (+8 over baseline).ruff check,ruff format --check,mypy src testsclean.Pairs with UiPath/Agents#6256.
🤖 Generated with Claude Code