Skip to content

Commit e8ce7af

Browse files
feat: add custom guardrails implementation [AL-197]
1 parent 861e2db commit e8ce7af

File tree

4 files changed

+1247
-5
lines changed

4 files changed

+1247
-5
lines changed

src/uipath/_services/guardrails_service.py

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,27 @@
66
from .._execution_context import ExecutionContext
77
from .._folder_context import FolderContext
88
from .._utils import Endpoint, RequestSpec, header_folder
9-
from ..models.guardrails import BuiltInValidatorGuardrail, Guardrail
9+
from ..agent.guardrails._evaluators import (
10+
evaluate_boolean_rule,
11+
evaluate_number_rule,
12+
evaluate_universal_rule,
13+
evaluate_word_rule,
14+
)
15+
from ..models.guardrails import (
16+
BooleanRule,
17+
BuiltInValidatorGuardrail,
18+
CustomGuardrail,
19+
Guardrail,
20+
NumberRule,
21+
UniversalRule,
22+
WordRule,
23+
)
1024
from ..tracing import traced
1125
from ._base_service import BaseService
1226

1327

14-
class BuiltInGuardrailValidationResult(BaseModel):
15-
"""Result from built-in guardrail validation."""
28+
class GuardrailValidationResult(BaseModel):
29+
"""Result from guardrail validation."""
1630

1731
model_config = ConfigDict(populate_by_name=True)
1832

@@ -42,7 +56,7 @@ def evaluate_guardrail(
4256
*,
4357
folder_key: Optional[str] = None,
4458
folder_path: Optional[str] = None,
45-
) -> BuiltInGuardrailValidationResult:
59+
) -> GuardrailValidationResult:
4660
"""Call the API to validate input_data with the given guardrail.
4761
4862
Only supports built-in guardrails for now.
@@ -69,8 +83,53 @@ def evaluate_guardrail(
6983
json=spec.json,
7084
headers=spec.headers,
7185
)
72-
return BuiltInGuardrailValidationResult.model_validate(response.json())
86+
return GuardrailValidationResult.model_validate(response.json())
7387
else:
7488
raise NotImplementedError(
7589
"Custom guardrail validation is not yet supported by the API."
7690
)
91+
92+
@traced("evaluate_pre_custom_guardrails", run_type="uipath")
93+
def evaluate_pre_custom_guardrails(
94+
self,
95+
input_data: Dict[str, Any],
96+
guardrail: CustomGuardrail,
97+
) -> GuardrailValidationResult:
98+
"""Evaluate custom guardrail rules against input data (pre-execution)."""
99+
return self.evaluate_post_custom_guardrails(
100+
input_data=input_data,
101+
output_data={},
102+
guardrail=guardrail,
103+
)
104+
105+
@traced("evaluate_post_custom_guardrails", run_type="uipath")
106+
def evaluate_post_custom_guardrails(
107+
self,
108+
input_data: Dict[str, Any],
109+
output_data: Dict[str, Any],
110+
guardrail: CustomGuardrail,
111+
) -> GuardrailValidationResult:
112+
"""Evaluate custom guardrail rules against input and output data."""
113+
for rule in guardrail.rules:
114+
if isinstance(rule, WordRule):
115+
passed, reason = evaluate_word_rule(rule, input_data, output_data)
116+
elif isinstance(rule, NumberRule):
117+
passed, reason = evaluate_number_rule(rule, input_data, output_data)
118+
elif isinstance(rule, BooleanRule):
119+
passed, reason = evaluate_boolean_rule(rule, input_data, output_data)
120+
elif isinstance(rule, UniversalRule):
121+
passed, reason = evaluate_universal_rule(rule, output_data)
122+
else:
123+
return GuardrailValidationResult(
124+
validation_passed=False,
125+
reason=f"Unknown rule type: {type(rule)}",
126+
)
127+
128+
if not passed:
129+
return GuardrailValidationResult(
130+
validation_passed=False, reason=reason or "Rule validation failed"
131+
)
132+
133+
return GuardrailValidationResult(
134+
validation_passed=True, reason="All custom guardrail rules passed"
135+
)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
"""UiPath Guardrails utilities module.
2+
3+
This module provides utilities for evaluating guardrail rules.
4+
"""

0 commit comments

Comments
 (0)