Metadata-Version: 2.4
Name: gaas-openai-agents
Version: 0.1.0
Summary: OpenAI Agents SDK integration for GaaS (Governance as a Service)
Project-URL: Homepage, https://gaas.is
Project-URL: Documentation, https://gaas.to/sdks.html
Project-URL: Repository, https://github.com/H2OmAI/gaas
Project-URL: Changelog, https://github.com/H2OmAI/gaas/blob/main/CHANGELOG.md
Author-email: H2Om <sdk@gaas.is>
License-Expression: Apache-2.0
Keywords: agents,ai,gaas,governance,openai,openai-agents
Classifier: Development Status :: 3 - Alpha
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: gaas-sdk>=0.2.7
Requires-Dist: httpx>=0.27.0
Provides-Extra: all
Requires-Dist: openai-agents>=0.17; extra == 'all'
Provides-Extra: dev
Requires-Dist: openai-agents<0.18,>=0.17; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
Requires-Dist: pytest>=8.3.0; extra == 'dev'
Provides-Extra: openai-agents
Requires-Dist: openai-agents>=0.17; extra == 'openai-agents'
Description-Content-Type: text/markdown

# gaas-openai-agents

GaaS (Governance as a Service) integration for the [OpenAI Agents SDK](https://github.com/openai/openai-agents-python).

Every function tool call is governed **before it executes**: the adapter submits a
governance intent to GaaS, and only an APPROVE (or an approved escalation) lets the
tool run. A BLOCK verdict raises `GovernanceBlockedError` **out of `Runner.run()`** —
the run halts; the error is never converted into text the model can route around.

```bash
pip install gaas-openai-agents[openai-agents]
```

## Quickstart

```python
from agents import Agent, Runner, function_tool
from gaas_openai_agents import govern_tools, GaaSGovernanceConfig

@function_tool
def send_email(to: str, subject: str, body: str) -> str:
    """Send an email."""
    ...

config = GaaSGovernanceConfig(api_key="gsk_...", agent_id="my-agent")
agent = Agent(
    name="assistant",
    instructions="You are a helpful assistant.",
    tools=govern_tools([send_email], config=config),
)

result = await Runner.run(agent, "Email the Q3 report to finance@acme.com")
```

## Verdict flow

```
tool call → GaaS intent → ┌─────────┐
                          │ APPROVE │ → tool executes
                          │ BLOCK   │ → GovernanceBlockedError raised out of Runner.run()
                          │ ESCALATE│ → raises by default; hold-and-poll optional (below)
                          └─────────┘
```

Only governance blocks halt the run. Errors *inside* your tool function keep the
framework's default behaviour (formatted for the model; the run continues).

## Configuration

```python
from gaas_openai_agents import GaaSGovernanceConfig

config = GaaSGovernanceConfig(
    api_url="https://api.gaas.is",    # GaaS API endpoint
    api_key="gsk_...",                # Your API key
    agent_id="my-agent",              # Agent identifier (appears in audit trail)
    block_on_escalate=True,           # Raise GovernanceBlockedError on ESCALATE
    timeout_seconds=5.0,              # Governance check timeout (fail open on timeout)
    sensitivity="INTERNAL",           # Default sensitivity level for tool inputs
    raise_on_governance_error=False,  # Fail open if GaaS API is unreachable
    extra_regulatory_domains=["HIPAA"],   # Additional domains for all intents
    extra_data_categories=["PHI"],        # Additional data categories for all intents
    hold_on_escalate=False,           # Wait for the human decision on ESCALATE
    escalation_poll_seconds=5.0,      # Poll interval while holding
    escalation_max_wait_seconds=600.0,  # Give up (treat as timeout) after this
)
```

### Hold-and-Poll on ESCALATE

With `hold_on_escalate=True`, an ESCALATE verdict no longer raises immediately.
The tool call holds while GaaS routes the escalation to a human reviewer, polling
the escalation status until it is decided:

- **approve / modify** — the tool executes.
- **deny** — raises `GovernanceBlockedError` with verdict `ESCALATE_DENY`.
- **timeout** — raises `GovernanceBlockedError` with verdict `ESCALATE_TIMEOUT`.

`hold_on_escalate` takes precedence over `block_on_escalate`. Transient polling
errors are retried until the deadline.

## Handling blocked runs

```python
from gaas_openai_agents import GovernanceBlockedError

try:
    result = await Runner.run(agent, "wire $250k to the new vendor")
except GovernanceBlockedError as err:
    print(err.verdict)                  # BLOCK / ESCALATE / ESCALATE_DENY / ESCALATE_TIMEOUT
    print(err.decision_id)              # audit reference
    print(err.blocking_policies)        # policy IDs that triggered the block
    print(err.governance_proof_token)   # GPT token ID for the legal audit trail
```

`GovernanceBlockedError` subclasses `agents.exceptions.AgentsException`, so the
openai-agents runner propagates it unchanged.

## Notes

- Only `FunctionTool` instances (e.g. from `@function_tool`) can be governed.
  Hosted tools (web search, code interpreter) execute on OpenAI's side and are
  out of client-side governance reach.
- Tool metadata (name, description, JSON schema, guardrails, approval config)
  is preserved by wrapping.
- Fail-open by default: if the GaaS API is unreachable the tool proceeds. Set
  `raise_on_governance_error=True` to fail closed.

## Links

- Docs: https://gaas.to/sdks.html
- GaaS: https://gaas.is
