Skip to content

feat(governance): OpenAI Agents adapter#358

Open
aditik0303 wants to merge 9 commits into
mainfrom
feat/governance-openai-agents
Open

feat(governance): OpenAI Agents adapter#358
aditik0303 wants to merge 9 commits into
mainfrom
feat/governance-openai-agents

Conversation

@aditik0303

@aditik0303 aditik0303 commented Jun 24, 2026

Copy link
Copy Markdown

Summary

Adds an OpenAI Agents SDK governance adapter to uipath-openai-agents. It lets UiPath governance evaluate what an OpenAI Agent does at the model and tool level, and block disallowed actions, without the agent author writing governance code. This package contains only the OpenAI-Agents-specific bridge.

What it does

  • Detects an OpenAI agents.Agent (can_handle claims only real Agent instances) and installs governance on each agent in the tree by setting its native hooks attribute (an agents.AgentHooks), chaining any pre-existing hooks.

  • Maps each hook on the agent lifecycle to a governance check:

    OpenAI Agents hook Governance hook
    on_llm_start BEFORE_MODEL
    on_llm_end AFTER_MODEL
    on_tool_start TOOL_CALL
    on_tool_end AFTER_TOOL
  • Enforces by letting a GovernanceBlockException (raised on a DENY decision) propagate, stopping the model call or tool. Any other error inside a governance hook is logged and swallowed, so a governance failure cannot break an otherwise-healthy agent run.

  • Discovered through the uipath.governance.adapters entry point, so no explicit import is needed to register it.

What it does not do

  • Does not fire agent-level boundaries (BEFORE_AGENT / AFTER_AGENT); those are owned by the governance host.
  • Does not depend on platform, auth, transport, or runtime internals — only on the shared governance contracts in uipath-core.

aditik0303 and others added 2 commits June 22, 2026 23:09
Installs governance on each agent's AgentHooks (on_llm_start/end -> BEFORE/AFTER_MODEL, on_tool_start/end -> TOOL_CALL/AFTER_TOOL), chaining any existing hooks and walking the handoffs graph.

Self-registers via the uipath.governance.adapters entry point; unit-tested and verified firing through the framework's real execution path. BEFORE/AFTER_AGENT remain owned by the uipath-runtime wrapper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…, framework-only can_handle)

Mirror radu's LangChain-adapter review across the OpenAI Agents adapter:
- __init__: drop the import-time register_governance_adapter() side-effect; registration happens only via the uipath.governance.adapters entry-point discovery path.
- can_handle: claim only a real agents.Agent; remove the broad duck-typed (name/hooks/tools) fallback.
- docstring/comments: refer to the generic 'governance host', not uipath-runtime internals.
- tests: can_handle uses a real Agent; a duck-typed look-alike is now rejected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 24, 2026 12:37

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 an OpenAI Agents governance adapter to uipath-openai-agents, wired via entry-point discovery, along with a dedicated test suite to validate hook extraction, chaining, and enforcement behavior.

Changes:

  • Introduces OpenAIAgentsAdapter + GovernanceAgentHooks to govern OpenAI Agents SDK runs via AgentHooks callbacks.
  • Adds governance adapter registration via uipath.governance.adapters entry point (no import-time registry mutation).
  • Adds unit tests covering can_handle, attach/detach semantics, hook payload extraction, delegation, and exception handling.

Reviewed changes

Copilot reviewed 4 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/uipath-openai-agents/uv.lock Adds uipath-core to the locked dependency set for governance contracts/protocols.
packages/uipath-openai-agents/tests/governance/test_adapter.py New unit tests for adapter behavior, hook extraction, chaining, and enforcement semantics.
packages/uipath-openai-agents/tests/governance/init.py Establishes the governance tests package.
packages/uipath-openai-agents/src/uipath_openai_agents/governance/adapter.py Implements the OpenAI Agents governance adapter and hook plumbing.
packages/uipath-openai-agents/src/uipath_openai_agents/governance/init.py Provides explicit, idempotent adapter registration function for entry-point discovery.
packages/uipath-openai-agents/pyproject.toml Adds uipath-core dependency and registers the governance adapter entry point.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/uipath-openai-agents/src/uipath_openai_agents/governance/adapter.py Outdated
Comment thread packages/uipath-openai-agents/src/uipath_openai_agents/governance/adapter.py Outdated
Comment thread packages/uipath-openai-agents/src/uipath_openai_agents/governance/adapter.py Outdated
Comment thread packages/uipath-openai-agents/tests/governance/test_adapter.py Outdated
aditik0303 and others added 7 commits June 24, 2026 18:22
- Module docstring: registers via the uipath.governance.adapters entry point, not at import time.
- Text-cap comment: refer to the governance host, not the uipath-runtime wrapper constant.
- _iter_agents docstring: drop the stale 'duck-typed so Agent need not be importable' claim (the module imports agents.Agent).
- Test docstring: note can_handle uses a real agents.Agent; only payload shapes are faked.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
These files were swept into the branch by a broad add; they are unrelated to the governance adapter. Reverting/removing them so the PR contains only governance changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
An earlier cleanup commit compared against a stale local main and wrongly removed SETUP.MD and reverted the LlamaIndex docs change. Both files come from main (PRs #352/#356), not this branch. Restore them to the main version so this PR is governance-only with no spurious deletions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nale

AFTER_TOOL reads the tool name directly from the SDK-provided tool at
both on_tool_start and on_tool_end, so no start→end correlation is
needed (addresses the #899-style tool-identity review note). Also record
that the run-item/response text extraction is duck-typed intentionally,
since the SDK shapes are not stable public models.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Core PR #1761 dropped BaseAdapter + AdapterRegistry from uipath-core
(only EvaluatorProtocol remains), so the entry-point/adapter model no
longer compiles against current core. Migrate to the factory-evaluator
pattern used by the LangChain adapter (#899):

- governance/adapter.py: replace the BaseAdapter subclass (name/
  can_handle/attach/detach) with a module-level install_governance();
  keep GovernanceAgentHooks + the handoff-graph walk + chaining.
- runtime/factory.py: new_runtime reads `evaluator` from kwargs and
  calls install_governance on the resolved agent.
- governance/__init__.py: drop register_governance_adapter + the
  registry import; expose install_governance. No import-time side effects.
- pyproject.toml: remove the uipath.governance.adapters entry point.
- tests: drop can_handle/attach/detach tests; cover install_governance
  + factory wiring (evaluator present installs, absent skips).

ruff + mypy clean; 24 governance tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…onsistency

The module is no longer an adapter (no BaseAdapter). Name the file after
its native seam — agent hooks — matching how the LangChain integration
(#899) uses callbacks.py. Renames adapter.py->hooks.py and
test_adapter.py->test_hooks.py; updates imports + docstrings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…raph walk

Review findings (Viswa) for PR #358:

- Drop the per-hooks uuid trace_id: minting one at install time was
  identical across every call and diverged across handoff nodes. Trace
  correlation is owned by the layer below (OTel span / HTTP resolve),
  matching the LangChain adapter. Requires uipath-core >= 0.5.20, which
  removed trace_id from EvaluatorProtocol — bumped in the lock.
- Count llm/tool calls only after governance passes: a DENY raised
  before the bump, inflating the counter on blocked calls.
- Walk the handoff graph by isinstance(node, Agent) instead of
  duck-typing hasattr(node, "hooks") — the SDK type-checks the slot, so
  non-Agent objects could slip through.
- Log (not silently drop) when the graph walk hits the node cap.
- Report the live executing agent's name rather than the install-time
  entrypoint name, so attribution is correct after a handoff.
- Treat an item as a function call only when explicitly typed
  function_call or it carries arguments (no bare-name misclassification).
- Cap _stringify output so an oversized tool result / arg blob can't
  hand a multi-megabyte string to the evaluator.
- Trailing newline (W292).

Tests: FakeAgent now subclasses agents.Agent (graph walk isinstance-checks
Agent); added live-agent-name and no-inflation-on-block coverage; made the
caplog assertions propagation-independent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Jul 1, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
83.6% Coverage on New Code (required ≥ 90%)

See analysis details on SonarQube Cloud

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.

2 participants