@@ -350,6 +350,109 @@ def capture_request(request):
350350 assert request_payload ["byoValidatorName" ] == "my_databricks_pii"
351351 assert result .result == GuardrailValidationResultType .PASSED
352352
353+ def test_evaluate_guardrail_byog_forwards_byo_connection_id (
354+ self ,
355+ httpx_mock : HTTPXMock ,
356+ service : GuardrailsService ,
357+ base_url : str ,
358+ org : str ,
359+ tenant : str ,
360+ ) -> None :
361+ """A BYOG guardrail forwards byoConnectionId so the backend can narrow
362+ configuration resolution to the specific connection."""
363+ captured_request = None
364+
365+ def capture_request (request ):
366+ nonlocal captured_request
367+ captured_request = request
368+ return httpx .Response (
369+ status_code = 200 ,
370+ json = {"result" : "PASSED" , "details" : "Validation passed" },
371+ )
372+
373+ httpx_mock .add_callback (
374+ method = "POST" ,
375+ url = f"{ base_url } { org } { tenant } /agentsruntime_/api/execution/guardrails/validate" ,
376+ callback = capture_request ,
377+ )
378+
379+ byog_guardrail = BuiltInValidatorGuardrail (
380+ id = "byog-id" ,
381+ name = "Databricks PII (BYOG)" ,
382+ enabled_for_evals = True ,
383+ selector = GuardrailSelector (scopes = [GuardrailScope .LLM ]),
384+ guardrail_type = "builtInValidator" ,
385+ validator_type = "byo" ,
386+ byo_validator_name = "my_databricks_pii" ,
387+ byo_connection_id = "byog-conn-1" ,
388+ validator_parameters = [],
389+ )
390+
391+ service .evaluate_guardrail ("some input" , byog_guardrail )
392+
393+ assert captured_request is not None
394+ request_payload = json .loads (captured_request .content )
395+ assert request_payload ["byoValidatorName" ] == "my_databricks_pii"
396+ assert request_payload ["byoConnectionId" ] == "byog-conn-1"
397+
398+ def test_evaluate_guardrail_byog_omits_connection_id_when_absent (
399+ self ,
400+ httpx_mock : HTTPXMock ,
401+ service : GuardrailsService ,
402+ base_url : str ,
403+ org : str ,
404+ tenant : str ,
405+ ) -> None :
406+ """byoConnectionId is only forwarded when present; a BYOG guardrail without
407+ one resolves by validator name alone."""
408+ captured_request = None
409+
410+ def capture_request (request ):
411+ nonlocal captured_request
412+ captured_request = request
413+ return httpx .Response (
414+ status_code = 200 ,
415+ json = {"result" : "PASSED" , "details" : "Validation passed" },
416+ )
417+
418+ httpx_mock .add_callback (
419+ method = "POST" ,
420+ url = f"{ base_url } { org } { tenant } /agentsruntime_/api/execution/guardrails/validate" ,
421+ callback = capture_request ,
422+ )
423+
424+ byog_guardrail = BuiltInValidatorGuardrail (
425+ id = "byog-id" ,
426+ name = "Databricks PII (BYOG)" ,
427+ enabled_for_evals = True ,
428+ selector = GuardrailSelector (scopes = [GuardrailScope .LLM ]),
429+ guardrail_type = "builtInValidator" ,
430+ validator_type = "byo" ,
431+ byo_validator_name = "my_databricks_pii" ,
432+ validator_parameters = [],
433+ )
434+
435+ service .evaluate_guardrail ("some input" , byog_guardrail )
436+
437+ assert captured_request is not None
438+ request_payload = json .loads (captured_request .content )
439+ assert "byoConnectionId" not in request_payload
440+
441+ def test_evaluate_guardrail_byo_connection_id_from_alias (self ) -> None :
442+ """byoConnectionId parses into the typed field via its camelCase alias."""
443+ guardrail = BuiltInValidatorGuardrail .model_validate (
444+ {
445+ "$guardrailType" : "builtInValidator" ,
446+ "id" : "byog-id" ,
447+ "name" : "BYOG" ,
448+ "validatorType" : "byo" ,
449+ "byoValidatorName" : "my_databricks_pii" ,
450+ "byoConnectionId" : "byog-conn-1" ,
451+ "validatorParameters" : [],
452+ }
453+ )
454+ assert guardrail .byo_connection_id == "byog-conn-1"
455+
353456 def test_evaluate_guardrail_byo_without_name_raises (
354457 self ,
355458 service : GuardrailsService ,
@@ -426,6 +529,49 @@ def capture_request(request):
426529 request_payload = json .loads (captured_request .content )
427530 assert "byoValidatorName" not in request_payload
428531
532+ def test_evaluate_guardrail_non_byo_type_does_not_forward_connection_id (
533+ self ,
534+ httpx_mock : HTTPXMock ,
535+ service : GuardrailsService ,
536+ base_url : str ,
537+ org : str ,
538+ tenant : str ,
539+ ) -> None :
540+ """byoConnectionId is only forwarded for the "byo" sentinel, never leaked
541+ into a non-BYOG validator payload even if the field happens to be set."""
542+ captured_request = None
543+
544+ def capture_request (request ):
545+ nonlocal captured_request
546+ captured_request = request
547+ return httpx .Response (
548+ status_code = 200 ,
549+ json = {"result" : "PASSED" , "details" : "Validation passed" },
550+ )
551+
552+ httpx_mock .add_callback (
553+ method = "POST" ,
554+ url = f"{ base_url } { org } { tenant } /agentsruntime_/api/execution/guardrails/validate" ,
555+ callback = capture_request ,
556+ )
557+
558+ guardrail = BuiltInValidatorGuardrail (
559+ id = "test-id" ,
560+ name = "PII detection guardrail" ,
561+ enabled_for_evals = True ,
562+ selector = GuardrailSelector (scopes = [GuardrailScope .LLM ]),
563+ guardrail_type = "builtInValidator" ,
564+ validator_type = "pii_detection" ,
565+ byo_connection_id = "stray-conn" ,
566+ validator_parameters = [],
567+ )
568+
569+ service .evaluate_guardrail ("some input" , guardrail )
570+
571+ assert captured_request is not None
572+ request_payload = json .loads (captured_request .content )
573+ assert "byoConnectionId" not in request_payload
574+
429575 def test_evaluate_guardrail_ootb_omits_byo_validator_name (
430576 self ,
431577 httpx_mock : HTTPXMock ,
0 commit comments