Skip to content

feat: support ByoValidator (BYOG) on the decorator path [AL-512] - #1014

Merged
apetraru-uipath merged 1 commit into
mainfrom
feat/byog-decorator
Jul 31, 2026
Merged

feat: support ByoValidator (BYOG) on the decorator path [AL-512]#1014
apetraru-uipath merged 1 commit into
mainfrom
feat/byog-decorator

Conversation

@apetraru-uipath

@apetraru-uipath apetraru-uipath commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

What changed?

Decorator-flavor Bring Your Own Guardrail (BYOG) support — the counterpart to UiPathByoGuardrailMiddleware shipped in #1013.

ByoValidator re-export

  • Exported from uipath_langchain.guardrails and the .guardrails.decorators shim as a plain import. uipath-platform is floored at >=0.2.14 — the release that ships ByoValidator (feat: add ByoValidator for Bring Your Own Guardrail (BYOG) [AL-512] uipath-python#1833, now merged and published) — so the guarded getattr(..., None) fallback this PR previously carried is gone, along with the sample's ImportError guard and the conditional test skips.
  • No new adapter machinery — @guardrail(validator=ByoValidator("…", connection_id="…"), action=…) works through the existing LangChainGuardrailAdapter, with scope inferred from the decorated target (tool → TOOL, LLM factory → LLM, agent factory → AGENT).

Adapter hardening

  • The LLM/agent wrappers previously swallowed evaluator exceptions with a bare 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)

  • Both parity mock agents (tests/cli/mocks/parity_agent_{middleware,decorator}.py) gain the same "Agent BYOG Detection" guardrail — AGENT scope, PRE, BlockAction; wired through UiPathByoGuardrailMiddleware on one side and ByoValidator + @guardrail on the other, with identical placeholder validator name / connection id.
  • New scenario 12, test_byog_agent_block in tests/cli/test_guardrails_in_langgraph.py, runs for both flavors and asserts two parity dimensions: the identical AgentRuntimeError block contract on a failing verdict, and — the BYOG-specific part — that both flavors deliver the same byo wire 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

  • The two BYOG samples are merged into samples/joke-agent-bring-your-own-guardrail: a single agent guarded twice from the same BYOG configuration — UiPathByoGuardrailMiddleware logs on AGENT scope (PRE_AND_POST, LogAction) while ByoValidator + @guardrail on a create_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 (parameters naming, no static stage restriction, error semantics) are spelled out.
  • Discovery uses uip agent guardrails list --byo, whose entries carry ByoValidatorName (→ validator_name), ByoConnectionId (→ connection_id) and the full connector-defined Parameters schema. Updated in both BYOG doc sections, the sample README and the sample's code comments.
  • 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.
  • All identifiers are placeholders (my-harmful-content-guardrail, my-byog-guardrail-connection, public uipath-azure-contentsafety-guardrails connector key); the Azure Content Safety parameter example ships commented out to keep the sample vendor-neutral.

Leftovers cleaned up from the #1013 review

  • Tenant-specific values removed from tests. The earlier placeholder sweep covered docs and samples but missed the test suites: tests/guardrails/test_byo_validator.py and tests/guardrails/middlewares/test_byo.py still 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 on main, so this PR touches it.
  • Scopes/stages claim and the uip agent guardrails list discovery command were corrected here in the previous round, matching what landed in feat: add UiPathByoGuardrailMiddleware (BYOG) [AL-512] #1013.
  • Docs deduplication after feat: add UiPathByoGuardrailMiddleware (BYOG) [AL-512] #1013 merged: two ### 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

How has this been tested?

  • tests/guardrails/test_byo_validator.py10 tests, all running, no skips: adapter evaluator-error logging across all four LLM/agent PRE/POST wrappers (message names the guardrail, traceback attached), and ByoValidator through @guardrail on a tool, a plain function, and reused across two targets — asserting the byo guardrail with byoValidatorName/byoConnectionId reaches evaluate_guardrail. Previously 3 of these skipped on CI behind skipif ByoValidator is None; with the floor at uipath-platform>=0.2.14 they now execute against the published package.
  • Parity suite, scenario 12test_byog_agent_block runs for BOTH flavors: each parity mock agent gains an "Agent BYOG Detection" guardrail (AGENT scope, PRE, BlockAction; middleware via UiPathByoGuardrailMiddleware, decorator via ByoValidator), and the test asserts they deliver the same byo wire 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 identical AgentRuntimeError block contract. All 12 parity scenarios × 2 flavors green.
  • Full suite green; ruff check, ruff format --check, mypy clean; uv lock --check clean.
  • Verified the re-export resolves without the guard: ByoValidator imports from both entry points, is present in both __all__s, and builds a guardrail with validator_type="byo" carrying the expected byoValidatorName/byoConnectionId.
  • All three python fences across both BYOG doc sections compile-checked; the merged sample's graph.py parses and its JSON manifests validate.
  • Live E2E on alpha (AdminStudioTest) against a real BYOG harmful-content configuration, running the merged sample (local uipath-langchain + published uipath-platform 0.2.14):
    • benign topic → both flavors evaluate in one run (agent PRE, LLM PRE per model call, agent POST — all 200) → joke returned ✅
    • harmful topic → [GUARDRAIL] [BYOG Harmful Content] Failed logged by the agent-scope middleware, then Guardrail [BYOG LLM Harmful Content] blocked executionAgentRuntimeError before chat/completions ✅ (vendor verdict: Harmful content detected: Violence (severity 4))

Behaviour note for reviewers: @guardrail on a factory function evaluates the factory's own (empty) arguments once at import time — so a run shows one guardrail call before START in addition to the runtime evaluations. This is pre-existing platform behaviour for any factory-decorated guardrail (it also affects the existing joke-agent-decorator sample), not something introduced here, and is deliberately left as is. LLM-scope guardrails evaluate once per model call (twice in a two-turn ReAct run).

Are there any breaking changes?

  • Under Feature Flag
  • None
  • DB migrations
  • API removals

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-platform floor moves 0.2.12 → 0.2.14 (within the existing <0.3.0 range), which is required for ByoValidator to exist.

🤖 Generated with Claude Code

apetraru-uipath added a commit that referenced this pull request Jul 29, 2026
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>
Copilot AI review requested due to automatic review settings July 29, 2026 12:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ByoValidator from uipath_langchain.guardrails and uipath_langchain.guardrails.decorators (falls back to None on older uipath versions).
  • 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.

Comment on lines +11 to +12
> For the middleware flavor of the same setup, see the `joke-agent-byog` sample
> (`UiPathByoGuardrailMiddleware`).
@apetraru-uipath
apetraru-uipath force-pushed the feat/byog-decorator branch 2 times, most recently from f0ca636 to 3d321ba Compare July 29, 2026 16:08
guardrail,
)

# Bring Your Own Guardrail (BYOG) validator. Available when the installed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To remove this comment once the TODO is solved

UiPathUserPromptAttacksMiddleware,
)

# Bring Your Own Guardrail (BYOG) validator. Available when the installed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Comment thread docs/guardrails.md Outdated
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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

apetraru-uipath added a commit that referenced this pull request Jul 30, 2026
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>
@apetraru-uipath
apetraru-uipath force-pushed the feat/byog-decorator branch 2 times, most recently from 3e49e7e to f4024bf Compare July 30, 2026 11:29
apetraru-uipath added a commit that referenced this pull request Jul 30, 2026
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>
@apetraru-uipath
apetraru-uipath force-pushed the feat/byog-decorator branch 4 times, most recently from 1e1be52 to cfbbc23 Compare July 30, 2026 15:07
Comment thread docs/guardrails.md Outdated
```

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need for the connection details to end up in bindings, for byog.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@sonarqubecloud

Copy link
Copy Markdown

@apetraru-uipath
apetraru-uipath merged commit bd62104 into main Jul 31, 2026
45 checks passed
@apetraru-uipath
apetraru-uipath deleted the feat/byog-decorator branch July 31, 2026 10:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants