|
10 | 10 | ) |
11 | 11 |
|
12 | 12 | from uipath.platform import UiPathApiConfig, UiPathExecutionContext |
| 13 | +from uipath.platform.common import ExecutionSourceContext |
13 | 14 | from uipath.platform.guardrails import ( |
14 | 15 | BuiltInValidatorGuardrail, |
15 | 16 | EnumListParameterValue, |
@@ -356,6 +357,103 @@ def capture_request(request): |
356 | 357 | # header merging works even when no active span exists) |
357 | 358 | assert "content-type" in headers |
358 | 359 |
|
| 360 | + def test_evaluate_guardrail_sends_source_and_job_key_headers( |
| 361 | + self, |
| 362 | + httpx_mock: HTTPXMock, |
| 363 | + service: GuardrailsService, |
| 364 | + base_url: str, |
| 365 | + org: str, |
| 366 | + tenant: str, |
| 367 | + monkeypatch: pytest.MonkeyPatch, |
| 368 | + ) -> None: |
| 369 | + """Outgoing request includes execution source and job key headers.""" |
| 370 | + monkeypatch.setenv("UIPATH_JOB_KEY", "job-123") |
| 371 | + |
| 372 | + captured_request = None |
| 373 | + |
| 374 | + def capture_request(request): |
| 375 | + nonlocal captured_request |
| 376 | + captured_request = request |
| 377 | + return httpx.Response( |
| 378 | + status_code=200, |
| 379 | + json={"result": "PASSED", "details": "OK"}, |
| 380 | + ) |
| 381 | + |
| 382 | + httpx_mock.add_callback( |
| 383 | + method="POST", |
| 384 | + url=f"{base_url}{org}{tenant}/agentsruntime_/api/execution/guardrails/validate", |
| 385 | + callback=capture_request, |
| 386 | + ) |
| 387 | + |
| 388 | + pii_guardrail = BuiltInValidatorGuardrail( |
| 389 | + id="test-id", |
| 390 | + name="PII guardrail", |
| 391 | + description="Test", |
| 392 | + enabled_for_evals=True, |
| 393 | + selector=GuardrailSelector( |
| 394 | + scopes=[GuardrailScope.TOOL], match_names=["tool1"] |
| 395 | + ), |
| 396 | + guardrail_type="builtInValidator", |
| 397 | + validator_type="pii_detection", |
| 398 | + validator_parameters=[], |
| 399 | + ) |
| 400 | + |
| 401 | + with ExecutionSourceContext("runtime"): |
| 402 | + service.evaluate_guardrail("test input", pii_guardrail) |
| 403 | + |
| 404 | + assert captured_request is not None |
| 405 | + headers = dict(captured_request.headers) |
| 406 | + assert headers.get("x-uipath-guardrails-source") == "runtime" |
| 407 | + assert headers.get("x-uipath-jobkey") == "job-123" |
| 408 | + |
| 409 | + def test_evaluate_guardrail_omits_source_and_job_key_when_unset( |
| 410 | + self, |
| 411 | + httpx_mock: HTTPXMock, |
| 412 | + service: GuardrailsService, |
| 413 | + base_url: str, |
| 414 | + org: str, |
| 415 | + tenant: str, |
| 416 | + monkeypatch: pytest.MonkeyPatch, |
| 417 | + ) -> None: |
| 418 | + """Source/job key headers are absent when unset.""" |
| 419 | + monkeypatch.delenv("UIPATH_JOB_KEY", raising=False) |
| 420 | + |
| 421 | + captured_request = None |
| 422 | + |
| 423 | + def capture_request(request): |
| 424 | + nonlocal captured_request |
| 425 | + captured_request = request |
| 426 | + return httpx.Response( |
| 427 | + status_code=200, |
| 428 | + json={"result": "PASSED", "details": "OK"}, |
| 429 | + ) |
| 430 | + |
| 431 | + httpx_mock.add_callback( |
| 432 | + method="POST", |
| 433 | + url=f"{base_url}{org}{tenant}/agentsruntime_/api/execution/guardrails/validate", |
| 434 | + callback=capture_request, |
| 435 | + ) |
| 436 | + |
| 437 | + pii_guardrail = BuiltInValidatorGuardrail( |
| 438 | + id="test-id", |
| 439 | + name="PII guardrail", |
| 440 | + description="Test", |
| 441 | + enabled_for_evals=True, |
| 442 | + selector=GuardrailSelector( |
| 443 | + scopes=[GuardrailScope.TOOL], match_names=["tool1"] |
| 444 | + ), |
| 445 | + guardrail_type="builtInValidator", |
| 446 | + validator_type="pii_detection", |
| 447 | + validator_parameters=[], |
| 448 | + ) |
| 449 | + |
| 450 | + service.evaluate_guardrail("test input", pii_guardrail) |
| 451 | + |
| 452 | + assert captured_request is not None |
| 453 | + headers = dict(captured_request.headers) |
| 454 | + assert "x-uipath-guardrails-source" not in headers |
| 455 | + assert "x-uipath-jobkey" not in headers |
| 456 | + |
359 | 457 | def test_evaluate_guardrail_extracts_span_id_from_traceparent( |
360 | 458 | self, |
361 | 459 | httpx_mock: HTTPXMock, |
|
0 commit comments