Skip to content
Open
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
2 changes: 1 addition & 1 deletion packages/uipath-platform/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "uipath-platform"
version = "0.1.17"
version = "0.1.18"
description = "HTTP client library for programmatic access to UiPath Platform"
readme = { file = "README.md", content-type = "text/markdown" }
requires-python = ">=3.11"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@
)

from ._guardrails_service import GuardrailsService
from .decorators import (
BlockAction,
CustomValidator,
GuardrailAction,
GuardrailBlockException,
GuardrailExecutionStage,
GuardrailTargetAdapter,
GuardrailValidatorBase,
LogAction,
LoggingSeverityLevel,
PIIDetectionEntity,
PIIDetectionEntityType,
PIIValidator,
PromptInjectionValidator,
RuleFunction,
guardrail,
register_guardrail_adapter,
)
from .guardrails import (
BuiltInValidatorGuardrail,
EnumListParameterValue,
Expand All @@ -22,7 +40,9 @@
)

__all__ = [
# Service
"GuardrailsService",
# Guardrail models
"BuiltInValidatorGuardrail",
"GuardrailType",
"GuardrailValidationResultType",
Expand All @@ -33,4 +53,21 @@
"GuardrailValidationResult",
"EnumListParameterValue",
"MapEnumParameterValue",
# Decorator framework
"guardrail",
"GuardrailValidatorBase",
"PIIValidator",
"PromptInjectionValidator",
"CustomValidator",
"RuleFunction",
"PIIDetectionEntity",
"PIIDetectionEntityType",
"GuardrailExecutionStage",
"GuardrailAction",
"LogAction",
"BlockAction",
"LoggingSeverityLevel",
"GuardrailBlockException",
"GuardrailTargetAdapter",
"register_guardrail_adapter",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""Guardrail decorator framework for UiPath Platform.

Provides the ``@guardrail`` decorator, built-in validators, actions, and an
adapter registry that framework integrations (e.g. *uipath-langchain*) use to
teach the decorator how to wrap their specific object types.

Quick start::

from uipath.platform.guardrails.decorators import (
guardrail,
PIIValidator,
LogAction,
BlockAction,
PIIDetectionEntity,
PIIDetectionEntityType,
GuardrailExecutionStage,
)

pii = PIIValidator(entities=[PIIDetectionEntity(PIIDetectionEntityType.EMAIL)])

# Applied to a factory function (LangChain adapter must be imported first):
@guardrail(validator=pii, action=LogAction(), name="LLM PII")
def create_llm():
...
"""

from ._actions import BlockAction, LogAction, LoggingSeverityLevel
from ._enums import GuardrailExecutionStage, PIIDetectionEntityType
from ._exceptions import GuardrailBlockException
from ._guardrail import guardrail
from ._models import GuardrailAction, PIIDetectionEntity
from ._registry import GuardrailTargetAdapter, register_guardrail_adapter
from .validators import (
CustomValidator,
GuardrailValidatorBase,
PIIValidator,
PromptInjectionValidator,
RuleFunction,
)

__all__ = [
# Decorator
"guardrail",
# Validators
"GuardrailValidatorBase",
"PIIValidator",
"PromptInjectionValidator",
"CustomValidator",
"RuleFunction",
# Models & enums
"PIIDetectionEntity",
"PIIDetectionEntityType",
"GuardrailExecutionStage",
"GuardrailAction",
# Actions
"LogAction",
"BlockAction",
"LoggingSeverityLevel",
# Exception
"GuardrailBlockException",
# Adapter registry
"GuardrailTargetAdapter",
"register_guardrail_adapter",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""Built-in GuardrailAction implementations."""

import logging
from dataclasses import dataclass
from enum import Enum
from typing import Any, Optional

from uipath.core.guardrails import (
GuardrailValidationResult,
GuardrailValidationResultType,
)

from ._exceptions import GuardrailBlockException
from ._models import GuardrailAction


class LoggingSeverityLevel(int, Enum):
"""Logging severity level for :class:`LogAction`."""

ERROR = logging.ERROR
INFO = logging.INFO
WARNING = logging.WARNING
DEBUG = logging.DEBUG


@dataclass
class LogAction(GuardrailAction):
"""Log guardrail violations without stopping execution.

Args:
severity_level: Python logging level. Defaults to ``WARNING``.
message: Custom log message. If omitted, the validation reason is used.
"""

severity_level: LoggingSeverityLevel = LoggingSeverityLevel.WARNING
message: Optional[str] = None

def handle_validation_result(
self,
result: GuardrailValidationResult,
data: str | dict[str, Any],
guardrail_name: str,
) -> str | dict[str, Any] | None:
"""Log the violation and return ``None`` (no data modification)."""
if result.result == GuardrailValidationResultType.VALIDATION_FAILED:
msg = self.message or f"Failed: {result.reason}"
logging.getLogger(__name__).log(
self.severity_level,
"[GUARDRAIL] [%s] %s",
guardrail_name,
msg,
)
return None


@dataclass
class BlockAction(GuardrailAction):
"""Block execution by raising :class:`GuardrailBlockException`.

Framework adapters catch ``GuardrailBlockException`` at the wrapper boundary
and convert it to their own runtime error type.

Args:
title: Exception title. Defaults to a message derived from the guardrail name.
detail: Exception detail. Defaults to the validation reason.
"""

title: Optional[str] = None
detail: Optional[str] = None

def handle_validation_result(
self,
result: GuardrailValidationResult,
data: str | dict[str, Any],
guardrail_name: str,
) -> str | dict[str, Any] | None:
"""Raise :class:`GuardrailBlockException` when validation fails."""
if result.result == GuardrailValidationResultType.VALIDATION_FAILED:
title = self.title or f"Guardrail [{guardrail_name}] blocked execution"
detail = self.detail or result.reason or "Guardrail validation failed"
raise GuardrailBlockException(title=title, detail=detail)
return None
Loading
Loading