Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
GuardrailAttachment,
)

#: Timeout for a validate call carrying attachments. The backend fetches and decodes each
#: file inside the request, which the default 30s client timeout does not allow for.
_ATTACHMENT_VALIDATE_TIMEOUT_SECONDS = 60.0


Expand Down Expand Up @@ -119,10 +117,7 @@ def evaluate_guardrail(
Args:
input_data: The text or structured data to validate. Dictionaries will be converted to a string before validation.
guardrail: A guardrail instance used for validation.
attachments: Files attached to the run that the guardrail may inspect, so a
validator can evaluate a file's contents rather than only its metadata.
Which validators can use them, and which file types are readable, is
decided server-side. Omitted from the request body when empty.
attachments: Files attached to the run that the guardrail may inspect.

Returns:
GuardrailValidationResult: The outcome of the guardrail evaluation.
Expand Down Expand Up @@ -158,9 +153,6 @@ def evaluate_guardrail(
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
# so it can resolve each attachment id through Orchestrator's folder-scoped
# API. Only sent alongside attachments: it is meaningless otherwise.
folder_headers: dict[str, str] = {}
if attachments and UiPathConfig.folder_key:
folder_headers[HEADER_FOLDER_KEY] = UiPathConfig.folder_key
Expand All @@ -171,9 +163,6 @@ def evaluate_guardrail(
**header_job_key(),
**folder_headers,
}
# The default client timeout is 30s (common/_http_config.py). A validate call
# carrying attachments waits for the backend to fetch and decode each one, so give
# it more room. RequestSpec.timeout exists but is never forwarded, so pass it here.
request_kwargs: dict[str, Any] = {
"json": spec.json,
"headers": request_headers,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,21 +99,10 @@ class BuiltInValidatorGuardrail(BaseGuardrail):
class GuardrailAttachment(BaseModel):
"""A reference to a file attached to the run that a guardrail may inspect.

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
its own Orchestrator client (folder-scoped when the run's folder key is sent
alongside), so Orchestrator's access control is what decides whether the file can
be read — the runtime never resolves or forwards a signed URL itself.

Attributes:
id: The Orchestrator attachment id, as a string UUID. Used by the backend to
resolve the file through Orchestrator, as an extraction cache key, and for
trace correlation.
file_name: Original file name, shown to a judge model so it can name the
offending file.
mime_type: Original mime type. The backend decides what it can inspect.
id: The Orchestrator attachment id, as a string UUID.
file_name: Original file name.
mime_type: Original mime type.
"""

id: str
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1008,8 +1008,7 @@ def test_attachment_round_trips_the_wire_shape(self) -> None:


class TestGuardrailAttachmentFolderHeader:
"""evaluate_guardrail tells helix which folder the run executed in so it can
resolve each attachment id through Orchestrator's folder-scoped API."""
"""evaluate_guardrail sends the folder key alongside attachments."""

def test_folder_header_sent_when_folder_key_configured(
self,
Expand Down
Loading