feat(governance): GovernanceRuntime wrapper + runtime registry wiring#126
Open
aditik0303 wants to merge 3 commits into
Open
feat(governance): GovernanceRuntime wrapper + runtime registry wiring#126aditik0303 wants to merge 3 commits into
aditik0303 wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a governance integration layer at the runtime boundary by wiring a feature-flag–gated wrapper into the runtime factory registry, so newly created runtimes can be transparently wrapped with GovernanceRuntime when governance is enabled.
Changes:
- Add
apply_governance_wrapper(lazy-import, FF-gated) and re-export it fromuipath.runtime. - Wrap
UiPathRuntimeFactoryRegistry.get()results by default viaUiPathWrappedRuntimeFactory, with anapply_wrappers=Falseescape hatch. - Add a new governance runtime wrapper implementation (
uipath.runtime.governance.wrapper) plus extensive tests and docs for wrapper behavior.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_wrapper.py | Adds boundary tests for apply_governance_wrapper (FF gate, lazy import, fail-open behavior). |
| tests/test_wrapper_internals.py | Adds unit tests for GovernanceRuntime helper internals and module entry points (governance_wrapper, wrap_agent). |
| tests/test_registry.py | Updates registry tests for new apply_wrappers behavior and adds wrapper-specific coverage. |
| tests/test_dispose_isolation.py | Adds isolation tests ensuring GovernanceRuntime.dispose() runs all cleanup steps and only propagates delegate disposal errors. |
| src/uipath/runtime/wrapper.py | Introduces the FF-gated, lazy-import runtime wrapper entry point (apply_governance_wrapper). |
| src/uipath/runtime/registry.py | Adds UiPathWrappedRuntimeFactory and apply_wrappers plumbing to auto-apply governance on runtime creation. |
| src/uipath/runtime/governance/wrapper.py | Adds the GovernanceRuntime implementation (adapter wrapping, evaluator lifecycle, input/output extraction, dispose behavior). |
| src/uipath/runtime/init.py | Re-exports governance wrapper API (GOVERNANCE_FEATURE_FLAG, apply_governance_wrapper). |
| docs/runtime-wrapper-extension.md | Documents the governance integration point, flag semantics, and recommended testing approach. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+339
to
+353
| # Bind the model-name ContextVar so adapters running in this | ||
| # runtime's context see the right value under concurrent | ||
| # agents. The token is stashed so dispose() can reset the | ||
| # var — without that, the value leaks into sibling tasks | ||
| # that inherit this context and outlive the runtime. | ||
| model_name = self._extract_model_name(delegate, context) | ||
| self._model_name = model_name | ||
| self._model_name_token = _current_model_name.set(model_name) | ||
|
|
||
| # Record agent-type before the policy prefetch fires so the | ||
| # fetch can ask the server for the matching container key | ||
| # (conversational vs autonomous). | ||
| set_agent_conversational( | ||
| self._extract_is_conversational(delegate, context) | ||
| ) |
| # full chat history (e.g. ``{"messages": [...]}``). Pass | ||
| # ``latest_only=True`` so governance evaluates the most | ||
| # recent user message and not the entire transcript. | ||
| agent_input = _extract_governable_text(input, latest_only=True) |
Comment on lines
+405
to
+420
| # Try nested delegate chain (unwrap wrappers) | ||
| if not model_name: | ||
| inner = getattr(delegate, "_delegate", None) or getattr( | ||
| delegate, "delegate", None | ||
| ) | ||
| while inner and not model_name: | ||
| agent_def = getattr(inner, "_agent_definition", None) | ||
| if agent_def: | ||
| settings = getattr(agent_def, "settings", None) | ||
| if settings: | ||
| model_name = getattr(settings, "model", None) or "" | ||
| break | ||
| inner = getattr(inner, "_delegate", None) or getattr( | ||
| inner, "delegate", None | ||
| ) | ||
|
|
Comment on lines
+216
to
+222
| # Last-resort: walk public attributes on opaque objects (e.g. a | ||
| # framework-specific result class without model_dump/dict). | ||
| public = { | ||
| name: getattr(value, name) | ||
| for name in dir(value) | ||
| if not name.startswith("_") and not callable(getattr(value, name, None)) | ||
| } |
Comment on lines
+327
to
+336
| if not is_governance_enabled(): | ||
| self._init_failed = True | ||
| self._evaluator_ready = True # don't try to materialise later | ||
| logger.info( | ||
| "GovernanceRuntime initialized as no-op: governance feature " | ||
| "flag is OFF (agent='%s', runtime_id='%s')", | ||
| self._agent_name, | ||
| runtime_id, | ||
| ) | ||
| return |
aeb0d94 to
0664ff6
Compare
f1a607b to
ff14f22
Compare
0664ff6 to
58c7baf
Compare
ff14f22 to
2fb2248
Compare
58c7baf to
20fe69c
Compare
2fb2248 to
1a9ce83
Compare
20fe69c to
d1d42d6
Compare
1a9ce83 to
da816b2
Compare
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… FF gate (no-op when OFF, single dispose token); latest_only only for conversational agents; depth-cap model-name delegate walk; guard getattr in text extractor; doc is_governance_enabled name Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ts._helpers Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
d1d42d6 to
61e9ff7
Compare
da816b2 to
10b949f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked PR 7/7 — part of splitting
feat/governance-coreinto reviewable slices. Base:feat/governance-delegation-guard. One logical slice (branch is cumulative so CI is green). Merge in order #1 → #7 and delete each branch on merge so the next PR auto-retargets ontofeat/agentic-governance.feat/governance-corekept untouched as backup.