feat: support ByoValidator (BYOG) on the decorator path [AL-512] - #1014
Conversation
Add Bring Your Own Guardrail (BYOG) support so coded agents can run customer-managed validators (a cloud content-safety subscription, a vendor validation service, or a custom Integration Service connector) configured under Admin -> AI Trust Layer -> Guardrails Configurations. - UiPathByoGuardrailMiddleware references the admin configuration by validator name + IS connection id and builds a builtInValidator guardrail with validator_type="byo" (byoValidatorName/byoConnectionId), reusing the shared BuiltInGuardrailMiddlewareMixin hook wiring unchanged. - validator_parameters is an optional passthrough of raw ValidatorParameter values; scopes/stages are developer-supplied, since BYO validator capabilities are connector-defined and unknowable statically. - Extract BUILT_IN_VALIDATOR_GUARDRAIL_TYPE (Literal-typed, in middlewares/_base.py) and use it across all built-in middlewares in place of the repeated "builtInValidator" string. - Docs: "Bring Your Own Guardrail (BYOG)" section in docs/guardrails.md plus a "Tuning a BYOG validator" subsection for validator_parameters. - Sample: samples/joke-agent-bring-your-own-guardrail, guarding AGENT (PRE+POST) and TOOL (PRE) scopes, with bindings.json declaring the IS connection for per-environment rebinding. All identifiers are placeholders, following the bring-your-own-model convention; the Azure Content Safety parameter example ships commented out to keep the sample vendor-neutral. - Bump version to 0.14.17 and sync uv.lock. Verified live on alpha against a real BYOG harmful-content configuration: benign input passes, harmful input blocks at before_agent with the vendor verdict, and per-category severity thresholds are honoured (omitted blocks any non-zero severity, 4 lets severity-2 through while blocking 4, 6 lets both through). The decorator flavor ships separately (uipath-python ByoValidator + #1014). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds decorator-path Bring Your Own Guardrail (BYOG) support by re-exporting ByoValidator when available in the installed uipath SDK, hardens the LangChain adapter to log evaluator failures (still fail-open), and documents/illustrates usage with tests and a new sample.
Changes:
- Guarded re-export of
ByoValidatorfromuipath_langchain.guardrailsanduipath_langchain.guardrails.decorators(falls back toNoneon olderuipathversions). - Adapter hardening: LLM/agent guardrail evaluation exceptions are now logged at WARNING with traceback instead of being silently swallowed.
- Adds docs, sample project, and unit tests for BYOG decorator usage and the new warning logs.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/guardrails/test_byo_validator.py | Adds tests for adapter exception logging and conditional BYOG decorator wiring when ByoValidator exists. |
| src/uipath_langchain/guardrails/decorators/init.py | Adds guarded ByoValidator re-export via getattr(...) and includes it in __all__. |
| src/uipath_langchain/guardrails/_langchain_adapter.py | Logs WARNING with traceback on evaluator exceptions in LLM/agent PRE/POST application helpers. |
| src/uipath_langchain/guardrails/init.py | Adds guarded ByoValidator re-export and exposes it publicly via __all__. |
| samples/README.md | Adds the new BYOG decorator sample to the samples index. |
| samples/joke-agent-byog-decorator/uipath.json | Adds sample project UiPath packaging/runtime configuration. |
| samples/joke-agent-byog-decorator/README.md | Documents how to configure and run the BYOG decorator sample. |
| samples/joke-agent-byog-decorator/pyproject.toml | Adds the sample’s Python project metadata and dependencies. |
| samples/joke-agent-byog-decorator/langgraph.json | Declares the LangGraph entrypoint for the sample. |
| samples/joke-agent-byog-decorator/graph.py | Implements the sample agent guarded with ByoValidator using @guardrail. |
| samples/joke-agent-byog-decorator/bindings.json | Declares the Integration Service connection binding used by the BYOG config. |
| docs/guardrails.md | Adds a BYOG section under decorator-based guardrails and links the new sample. |
| > For the middleware flavor of the same setup, see the `joke-agent-byog` sample | ||
| > (`UiPathByoGuardrailMiddleware`). |
f0ca636 to
3d321ba
Compare
| guardrail, | ||
| ) | ||
|
|
||
| # Bring Your Own Guardrail (BYOG) validator. Available when the installed |
There was a problem hiding this comment.
To remove this comment once the TODO is solved
| UiPathUserPromptAttacksMiddleware, | ||
| ) | ||
|
|
||
| # Bring Your Own Guardrail (BYOG) validator. Available when the installed |
| Notes: | ||
|
|
||
| - **Always pass `connection_id`.** Validator names are unique per connection only; without the id the server picks the first configuration matching the name. | ||
| - **Stages must match the connector.** BYO validator capabilities are connector-defined, so `ByoValidator` applies no static stage restriction; an unsupported scope/stage surfaces as a `PROVIDER_ERROR` at runtime. |
There was a problem hiding this comment.
We don't have stage constraints in the connector. We left full flexibility - the connector allows all stages(by not enforcing them in any way) and the guardrail user is in charge to select the stage.
Add Bring Your Own Guardrail (BYOG) support so coded agents can run customer-managed validators (a cloud content-safety subscription, a vendor validation service, or a custom Integration Service connector) configured under Admin -> AI Trust Layer -> Guardrails Configurations. - UiPathByoGuardrailMiddleware references the admin configuration by validator name + IS connection id and builds a builtInValidator guardrail with validator_type="byo" (byoValidatorName/byoConnectionId), reusing the shared BuiltInGuardrailMiddlewareMixin hook wiring unchanged. - validator_parameters is an optional passthrough of raw ValidatorParameter values. Scopes and stages are developer-supplied: BYOG validators are not scope- or stage-restricted, so all three scopes and both stages are available exactly as for the built-in validators. - Extract BUILT_IN_VALIDATOR_GUARDRAIL_TYPE (Literal-typed, in middlewares/_base.py) and use it across all built-in middlewares in place of the repeated "builtInValidator" string. - Docs: "Bring Your Own Guardrail (BYOG)" section in docs/guardrails.md plus a "Tuning a BYOG validator" subsection for validator_parameters. - Sample: samples/joke-agent-bring-your-own-guardrail, guarding AGENT (PRE+POST) and TOOL (PRE) scopes, with bindings.json declaring the IS connection for per-environment rebinding. All identifiers are placeholders, following the bring-your-own-model convention; the Azure Content Safety parameter example ships commented out to keep the sample vendor-neutral. - Discovery: docs and sample point at `uip agent guardrails list` for the validator name, connection id and the connector-defined `Parameters` schema, rather than the raw agents_/api/designer/byog-guardrails endpoint. - Bump version to 0.14.19 and sync uv.lock. Verified live on alpha against a real BYOG harmful-content configuration: benign input passes, harmful input blocks at before_agent with the vendor verdict, and per-category severity thresholds are honoured (omitted blocks any non-zero severity, 4 lets severity-2 through while blocking 4, 6 lets both through). The decorator flavor ships separately (uipath-python ByoValidator + #1014). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
3e49e7e to
f4024bf
Compare
Add Bring Your Own Guardrail (BYOG) support so coded agents can run customer-managed validators (a cloud content-safety subscription, a vendor validation service, or a custom Integration Service connector) configured under Admin -> AI Trust Layer -> Guardrails Configurations. - UiPathByoGuardrailMiddleware references the admin configuration by validator name + IS connection id and builds a builtInValidator guardrail with validator_type="byo" (byoValidatorName/byoConnectionId), reusing the shared BuiltInGuardrailMiddlewareMixin hook wiring unchanged. - validator_parameters is an optional passthrough of raw ValidatorParameter values. Scopes and stages are developer-supplied: BYOG validators are not scope- or stage-restricted, so all three scopes and both stages are available exactly as for the built-in validators. - Extract BUILT_IN_VALIDATOR_GUARDRAIL_TYPE (Literal-typed, in middlewares/_base.py) and use it across all built-in middlewares in place of the repeated "builtInValidator" string. - Docs: "Bring Your Own Guardrail (BYOG)" section in docs/guardrails.md plus a "Tuning a BYOG validator" subsection for validator_parameters. - Sample: samples/joke-agent-bring-your-own-guardrail, guarding AGENT (PRE+POST) and TOOL (PRE) scopes, with bindings.json declaring the IS connection for per-environment rebinding. All identifiers are placeholders, following the bring-your-own-model convention; the Azure Content Safety parameter example ships commented out to keep the sample vendor-neutral. - Discovery: docs and sample point at `uip agent guardrails list` for the validator name, connection id and the connector-defined `Parameters` schema, rather than the raw agents_/api/designer/byog-guardrails endpoint. - Bump version to 0.14.18 and sync uv.lock (0.14.17 was taken by #1012 and is published on PyPI). Verified live on alpha against a real BYOG harmful-content configuration: benign input passes, harmful input blocks at before_agent with the vendor verdict, and per-category severity thresholds are honoured (omitted blocks any non-zero severity, 4 lets severity-2 through while blocking 4, 6 lets both through). The decorator flavor ships separately (uipath-python ByoValidator + #1014, which follows at 0.14.19). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1e1be52 to
cfbbc23
Compare
| ``` | ||
|
|
||
| Your BYOG configurations are listed alongside the built-in validators — so the same validator type can appear more than once, once for the UiPath-managed validator and once per BYOG configuration. Copy the validator name and connection id from your configuration's entry. | ||
| Each entry carries `ByoValidatorName` (→ `validator_name`), `ByoConnectionId` (→ `connection_id`), and `ByoConnectorKey` (the connector key, useful for a `bindings.json` connection binding), alongside its `AllowedScopes` / `GuardrailStages` and the full `Parameters` schema. |
There was a problem hiding this comment.
There is no need for the connection details to end up in bindings, for byog.
There was a problem hiding this comment.
Done in eb878f6 — the sample no longer ships a bindings.json (its only resource was the BYOG connection binding), and the docs/README no longer point ByoConnectorKey at a connection binding. Both now state the connection is resolved server-side from the BYOG configuration, with the agent sending only the validator name + connection id.
Decorator-flavor Bring Your Own Guardrail support, the counterpart to the UiPathByoGuardrailMiddleware shipped in #1013. - Re-export ByoValidator from uipath_langchain.guardrails and the .guardrails.decorators shim. `uipath-platform` is floored at >=0.2.14, the release that ships ByoValidator (UiPath/uipath-python#1833), so this is a plain import rather than a guarded getattr. - Adapter hardening: the LLM/agent wrappers previously swallowed evaluator exceptions silently; they now log a WARNING with the guardrail name and traceback (still fail-open), via a shared _EVALUATION_FAILED_MSG constant. This makes BYOG misconfiguration (PROVIDER_ERROR, removed/disabled config, BYOG not enabled) visible. - Tests: adapter error-logging tests plus ByoValidator-through-@guardrail tests (tool / plain function / validator reuse), all running against the published uipath-platform - no conditional skips. - Parity suite: new scenario 12 (test_byog_agent_block) runs for BOTH flavors and asserts they deliver the same byo wire contract to the service (validator_type="byo", byoValidatorName, byoConnectionId) and block identically on a failing verdict; both parity mock agents gain an "Agent BYOG Detection" guardrail (AGENT scope, PRE, BlockAction). - Sample: merge both flavors into samples/joke-agent-bring-your-own-guardrail as ONE agent guarded twice from the same BYOG configuration -- the middleware logs on AGENT scope (PRE_AND_POST, LogAction) while the decorator blocks on LLM scope (PRE, BlockAction on a create_llm factory), so a harmful topic is first logged and then blocked before the model is invoked. The separate joke-agent-byog-decorator sample is removed. - No solution binding for the BYOG connection (review feedback): the connection is resolved server-side from the BYOG configuration, so the sample ships no bindings.json and the docs no longer point ByoConnectorKey at a connection binding. - Docs: BYOG section under the decorator pattern in docs/guardrails.md, cross-referencing the middleware section for the shared prerequisite and discovery steps. Discovery uses `uip agent guardrails list --byo`, whose entries carry ByoValidatorName / ByoConnectionId and the connector-defined Parameters schema. - Replace the leftover tenant-specific validator name and connection GUID with the placeholder values used elsewhere, in this PR's tests and in tests/guardrails/middlewares/test_byo.py from #1013. - Bump to 0.14.20 (0.14.19 was taken by #1008 and is published on PyPI). Verified live on alpha against a real BYOG harmful-content configuration: benign topic evaluates on both flavors (agent PRE, LLM PRE per model call, agent POST) and returns a joke; harmful topic is logged by the agent-scope guardrail, then blocked by the LLM-scope guardrail before chat/completions, with the vendor verdict "Harmful content detected: Violence (severity 4)". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
cfbbc23 to
eb878f6
Compare
|



What changed?
Decorator-flavor Bring Your Own Guardrail (BYOG) support — the counterpart to
UiPathByoGuardrailMiddlewareshipped in #1013.ByoValidatorre-exportuipath_langchain.guardrailsand the.guardrails.decoratorsshim as a plain import.uipath-platformis floored at>=0.2.14— the release that shipsByoValidator(feat: add ByoValidator for Bring Your Own Guardrail (BYOG) [AL-512] uipath-python#1833, now merged and published) — so the guardedgetattr(..., None)fallback this PR previously carried is gone, along with the sample'sImportErrorguard and the conditional test skips.@guardrail(validator=ByoValidator("…", connection_id="…"), action=…)works through the existingLangChainGuardrailAdapter, with scope inferred from the decorated target (tool → TOOL, LLM factory → LLM, agent factory → AGENT).Adapter hardening
except Exception: return(4 sites in_langchain_adapter.py). They now log a WARNING with the guardrail name and traceback while staying fail-open, so a misconfigured BYOG configuration (PROVIDER_ERROR, removed/disabled config, BYOG not enabled) is visible instead of silent.Parity suite: BYOG scenario (middleware vs decorator)
tests/cli/mocks/parity_agent_{middleware,decorator}.py) gain the same "Agent BYOG Detection" guardrail — AGENT scope, PRE,BlockAction; wired throughUiPathByoGuardrailMiddlewareon one side andByoValidator+@guardrailon the other, with identical placeholder validator name / connection id.test_byog_agent_blockintests/cli/test_guardrails_in_langgraph.py, runs for both flavors and asserts two parity dimensions: the identicalAgentRuntimeErrorblock contract on a failing verdict, and — the BYOG-specific part — that both flavors deliver the samebyowire contract to the guardrails service (validator_type="byo",byoValidatorName,byoConnectionId). The guardrail objects are captured outside the mock so a mismatch fails the test rather than being swallowed by a fail-open path.Docs & sample: ONE sample, both flavors in one agent
samples/joke-agent-bring-your-own-guardrail: a single agent guarded twice from the same BYOG configuration —UiPathByoGuardrailMiddlewarelogs on AGENT scope (PRE_AND_POST,LogAction) whileByoValidator+@guardrailon acreate_llm()factory blocks on LLM scope (PRE,BlockAction). On a harmful topic you see both actions in sequence: the agent guardrail logs the violation, then the LLM guardrail aborts the run before the model is invoked.samples/joke-agent-byog-decorator/is removed.docs/guardrails.md: BYOG section under the decorator pattern. The admin prerequisite and discovery steps are cross-referenced to the middleware BYOG section rather than repeated verbatim — only the decorator-specific notes (parametersnaming, no static stage restriction, error semantics) are spelled out.uip agent guardrails list --byo, whose entries carryByoValidatorName(→validator_name),ByoConnectionId(→connection_id) and the full connector-definedParametersschema. Updated in both BYOG doc sections, the sample README and the sample's code comments.bindings.jsonand the docs no longer pointByoConnectorKeyat a connection binding.my-harmful-content-guardrail,my-byog-guardrail-connection, publicuipath-azure-contentsafety-guardrailsconnector key); the Azure Content Safety parameter example ships commented out to keep the sample vendor-neutral.Leftovers cleaned up from the #1013 review
tests/guardrails/test_byo_validator.pyandtests/guardrails/middlewares/test_byo.pystill hard-coded a real validator name and connection GUID. Both now use the same placeholders as the samples. The second file came from feat: add UiPathByoGuardrailMiddleware (BYOG) [AL-512] #1013 and is already onmain, so this PR touches it.uip agent guardrails listdiscovery command were corrected here in the previous round, matching what landed in feat: add UiPathByoGuardrailMiddleware (BYOG) [AL-512] #1013.### Bring Your Own Guardrail (BYOG)sections now exist in one document, so the identical admin-prerequisite and discovery paragraphs were collapsed into a cross-reference.Release
uv.locksynced (0.14.19 was taken by feat(tools): add internal HTTP request tool #1008 and is published on PyPI). The lock also movesuipath-platform0.2.12 → 0.2.14 for the raised floor.How has this been tested?
tests/guardrails/test_byo_validator.py— 10 tests, all running, no skips: adapter evaluator-error logging across all four LLM/agent PRE/POST wrappers (message names the guardrail, traceback attached), andByoValidatorthrough@guardrailon a tool, a plain function, and reused across two targets — asserting thebyoguardrail withbyoValidatorName/byoConnectionIdreachesevaluate_guardrail. Previously 3 of these skipped on CI behindskipif ByoValidator is None; with the floor atuipath-platform>=0.2.14they now execute against the published package.test_byog_agent_blockruns for BOTH flavors: each parity mock agent gains an "Agent BYOG Detection" guardrail (AGENT scope, PRE,BlockAction; middleware viaUiPathByoGuardrailMiddleware, decorator viaByoValidator), and the test asserts they deliver the samebyowire contract to the service (validator_type="byo",byoValidatorName,byoConnectionId— captured outside the mock so fail-open paths can't swallow a mismatch) and raise the identicalAgentRuntimeErrorblock contract. All 12 parity scenarios × 2 flavors green.ruff check,ruff format --check,mypyclean;uv lock --checkclean.ByoValidatorimports from both entry points, is present in both__all__s, and builds a guardrail withvalidator_type="byo"carrying the expectedbyoValidatorName/byoConnectionId.pythonfences across both BYOG doc sections compile-checked; the merged sample'sgraph.pyparses and its JSON manifests validate.AdminStudioTest) against a real BYOG harmful-content configuration, running the merged sample (localuipath-langchain+ publisheduipath-platform 0.2.14):[GUARDRAIL] [BYOG Harmful Content] Failedlogged by the agent-scope middleware, thenGuardrail [BYOG LLM Harmful Content] blocked execution→AgentRuntimeErrorbeforechat/completions✅ (vendor verdict: Harmful content detected: Violence (severity 4))Are there any breaking changes?
Additive: one re-export plus docs, sample and test coverage. Two things a reviewer should note as deliberate: the adapter now emits a WARNING on paths that previously failed silently, and the
uipath-platformfloor moves 0.2.12 → 0.2.14 (within the existing<0.3.0range), which is required forByoValidatorto exist.🤖 Generated with Claude Code