Metadata-Version: 2.4
Name: governor-sdk
Version: 0.4.3
Summary: Python SDK for GovernorAI - The execution boundary for autonomous AI
Author: GovernorAI Team
License: Apache-2.0
Project-URL: Homepage, https://github.com/SentinelLayer/GovernorAI
Project-URL: Documentation, https://github.com/SentinelLayer/GovernorAI/tree/main/sdk/python#readme
Project-URL: Repository, https://github.com/SentinelLayer/GovernorAI.git
Project-URL: Issues, https://github.com/SentinelLayer/GovernorAI/issues
Project-URL: Changelog, https://github.com/SentinelLayer/GovernorAI/blob/main/sdk/python/CHANGELOG.md
Keywords: governor,ai,governance,agent,policy,safety
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28.0
Provides-Extra: langchain
Requires-Dist: langchain<2.0.0,>=1.2.0; extra == "langchain"
Requires-Dist: langchain-core<2.0.0,>=1.2.0; extra == "langchain"
Provides-Extra: llamaindex
Requires-Dist: llama-index<0.15.0,>=0.14.0; extra == "llamaindex"
Provides-Extra: crewai
Requires-Dist: crewai<0.12.0,>=0.11.0; python_version < "3.14" and extra == "crewai"
Provides-Extra: langgraph
Requires-Dist: langgraph<2.0.0,>=1.1.0; extra == "langgraph"
Requires-Dist: langchain-core<2.0.0,>=1.2.0; extra == "langgraph"
Provides-Extra: bedrock
Requires-Dist: boto3>=1.28.0; extra == "bedrock"
Provides-Extra: gcp
Requires-Dist: google-auth>=2.20.0; extra == "gcp"
Requires-Dist: google-auth-oauthlib>=1.0.0; extra == "gcp"
Requires-Dist: google-cloud-aiplatform>=1.70.0; extra == "gcp"
Provides-Extra: azure
Requires-Dist: azure-identity>=1.14.0; extra == "azure"
Requires-Dist: azure-ai-projects<3.0.0,>=2.0.0; extra == "azure"
Requires-Dist: azure-ai-agents<2.0.0,>=1.0.0; extra == "azure"
Provides-Extra: databricks
Requires-Dist: databricks-sdk>=0.20.0; extra == "databricks"
Requires-Dist: databricks-agents>=1.0.0; extra == "databricks"
Requires-Dist: mlflow>=2.10.0; extra == "databricks"
Provides-Extra: all
Requires-Dist: langchain<2.0.0,>=1.2.0; extra == "all"
Requires-Dist: langchain-core<2.0.0,>=1.2.0; extra == "all"
Requires-Dist: llama-index<0.15.0,>=0.14.0; extra == "all"
Requires-Dist: crewai<0.12.0,>=0.11.0; python_version < "3.14" and extra == "all"
Requires-Dist: langgraph<2.0.0,>=1.1.0; extra == "all"
Requires-Dist: boto3>=1.28.0; extra == "all"
Requires-Dist: google-auth>=2.20.0; extra == "all"
Requires-Dist: google-auth-oauthlib>=1.0.0; extra == "all"
Requires-Dist: google-cloud-aiplatform>=1.70.0; extra == "all"
Requires-Dist: azure-identity>=1.14.0; extra == "all"
Requires-Dist: azure-ai-projects<3.0.0,>=2.0.0; extra == "all"
Requires-Dist: azure-ai-agents<2.0.0,>=1.0.0; extra == "all"
Requires-Dist: databricks-sdk>=0.20.0; extra == "all"
Requires-Dist: databricks-agents>=1.0.0; extra == "all"
Requires-Dist: mlflow>=2.10.0; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=7.4.0; extra == "dev"
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: pytest-mock>=3.12.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: black>=23.0.0; extra == "dev"
Requires-Dist: mypy>=1.7.0; extra == "dev"
Requires-Dist: types-requests>=2.31.0; extra == "dev"
Dynamic: license-file

# governor-sdk

**Python SDK for [GovernorAI](https://governorai.ai) — the execution boundary for autonomous AI.**

[![PyPI version](https://img.shields.io/pypi/v/governor-sdk.svg)](https://pypi.org/project/governor-sdk/)
[![Python versions](https://img.shields.io/pypi/pyversions/governor-sdk.svg)](https://pypi.org/project/governor-sdk/)
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

Autonomous AI agents can think anywhere — but with GovernorAI they can only *act* through a policy enforcement gateway. This SDK is how your Python agents talk to it: a `@governed` decorator, a universal `govern()` wrapper that auto-detects the framework, and native adapters for the major agent runtimes.

---

## Install

```bash
pip install governor-sdk
```

Optional framework adapters:

```bash
pip install "governor-sdk[langchain]"     # LangChain + langchain-core
pip install "governor-sdk[langgraph]"     # LangGraph tool nodes
pip install "governor-sdk[llamaindex]"    # LlamaIndex query engines
pip install "governor-sdk[crewai]"        # CrewAI crews and tasks
pip install "governor-sdk[bedrock]"       # AWS Bedrock + boto3
pip install "governor-sdk[gcp]"           # GCP Vertex AI + google-cloud-aiplatform
pip install "governor-sdk[azure]"         # Azure AI Foundry + azure-ai-agents
pip install "governor-sdk[databricks]"    # Databricks + databricks-agents + mlflow
pip install "governor-sdk[all]"           # all of the above
```

---

## Quickstart

```python
import os
from governor import GovernorAIClient, GovernorAIDenied

client = GovernorAIClient(
    base_url=os.environ["GOVERNOR_URL"],
    api_key=os.environ["GOVERNOR_API_KEY"],
)

try:
    result = client.execute(
        tool="erp.process_payment",
        args={"amount": 50_000, "vendor": "ACME"},
        agent_id="finance-agent-v1",
    )
    print("Allowed:", result)
except GovernorAIDenied as e:
    print("Denied by policy:", e)
```

Or wrap any agent in one line:

```python
from governor import govern

governed = govern(your_langchain_executor)
result = governed.invoke({"input": "process payment for ACME"})
```

`govern()` auto-detects LangChain, LangGraph, LlamaIndex, and CrewAI agents and applies the right adapter.

---

## Features

- **Sync and async clients** — `GovernorAIClient` and `AsyncGovernorAIClient`
- **One-line governance** — `govern(agent)` for any supported framework
- **`@governed` decorator** — wrap any function so it routes through a policy check before executing
- **Typed decisions** — allow / deny / needs-approval surface as `GovernorAIDenied` and `GovernorAIApprovalRequired` exceptions
- **Fail-closed by default** — if the gateway is unreachable, calls deny rather than silently proceeding
- **Framework adapters** — LangChain, LangGraph, LlamaIndex, CrewAI, AWS Bedrock, Google Cloud ADK / Vertex AI, Azure AI Foundry, Databricks Mosaic AI, AutoGPT
- **Session and step tracking** — every tool call carries `agent_id` and `session_id` so the gateway can enforce per-session step limits and cost caps
- **OpenTelemetry-friendly** — `trace_id` propagation built in
- **Mypy-strict** — type hints throughout

---

## Configuration

The client auto-configures from environment variables when explicit values aren't passed:

| Variable | Description |
|---|---|
| `GOVERNOR_URL` | Gateway URL (default: `http://localhost:8080`) |
| `GOVERNOR_API_KEY` | API key for authentication |
| `GOVERNOR_ORG_ID` | Organization ID (sent as `X-Org-ID` header) |

```python
# All three of these are equivalent if env vars are set:
client = GovernorAIClient()
client = GovernorAIClient(base_url=os.environ["GOVERNOR_URL"])
client = GovernorAIClient(base_url="...", api_key="...")
```

---

## Patterns

### 1. Decorate any function

```python
from governor import governed_fn

@governed_fn("crm.create_case", agent_id="support-agent")
def create_case(customer_id: str) -> dict:
    return {"case_id": "CASE-001", "customer_id": customer_id}

# Governance check happens before the function body runs.
# Raises GovernorAIDenied if the policy denies.
create_case(customer_id="123")
```

### 2. LangChain callback handler

```python
from langchain.agents import AgentExecutor
from governor import GovernorAIClient
from governor.integrations.langchain import GovernorAICallbackHandler

client = GovernorAIClient()
callback = GovernorAICallbackHandler(client, agent_id="research-agent")
executor = AgentExecutor(agent=agent, tools=tools, callbacks=[callback])
```

### 3. LangGraph tool node

```python
from governor.helpers import govern_langgraph

tool_node = govern_langgraph([search_web, write_file], agent_id="ops-agent")
graph.add_node("tools", tool_node)
```

### 4. CrewAI crew

```python
from governor import GovernorAIClient
from governor.integrations.crewai import GovernorAICrew

crew = GovernorAICrew(
    crew=your_crew,
    governor_client=GovernorAIClient(),
    crew_id="research-crew-v2",
)
```

### 5. AWS Bedrock agent

```python
import boto3
from governor import GovernorAIClient
from governor.integrations.bedrock import GovernorAIBedrockAgent

agent = GovernorAIBedrockAgent(
    bedrock_client=boto3.client("bedrock-agent-runtime"),
    governor_client=GovernorAIClient(),
    agent_id="bedrock-agent-v1",
)
response = agent.invoke_agent(
    agentId="...",
    agentAliasId="...",
    sessionId="session-123",
    inputText="Process a payment",
)
```

See [`examples/quickstart.py`](examples/quickstart.py) for the full set of integration patterns.

---

## Decision model

Every call returns one of three outcomes:

| Outcome | Python surface |
|---|---|
| **Allow** | Returns the gateway response dict containing the tool result |
| **Deny** | Raises `GovernorAIDenied` with policy reason |
| **Needs approval** | Raises `GovernorAIApprovalRequired` with approval URL — the agent can either block, poll, or hand off to a human |

```python
from governor import (
    GovernorAIClient,
    GovernorAIDenied,
    GovernorAIApprovalRequired,
    GovernorAIError,
)

try:
    result = client.execute(tool="...", args={...}, agent_id="...")
except GovernorAIDenied as e:
    log.warning("Denied: %s", e)
except GovernorAIApprovalRequired as e:
    notify_human(e.approval_url)
except GovernorAIError as e:
    # gateway unreachable, auth failed, etc — fail closed
    log.error("Gateway error: %s", e)
```

---

## CLI

The SDK installs a small CLI for quick checks:

```bash
governorai --help
governorai check tool=erp.process_payment agent_id=finance-agent
```

---

## Development

```bash
git clone https://github.com/SentinelLayer/GovernorAI
cd GovernorAI/sdk/python
pip install -e ".[all,dev]"
pytest
ruff check governor
mypy governor
```

---

## End-to-end testing

The default `pytest` run only exercises unit tests. To verify the SDK against a real gateway, opt into the integration suite under `tests/integration/`.

Start a gateway locally:

```bash
docker-compose up -d gateway control-plane postgres redis
```

Create an API key (via the control-plane UI at `http://localhost:3000` or by POSTing to `/api/v1/auth/apikeys`) and seed the smoke-test policy into the `smoke` namespace:

```bash
curl -X POST "$GOVERNOR_URL/api/v1/policies/opa" \
  -H "Authorization: Bearer $GOVERNOR_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<EOF
{"namespace": "smoke",
 "rego": $(jq -Rs . < tests/integration/policies/smoke_test.rego)}
EOF
```

Then run the suite:

```bash
export GOVERNOR_INTEGRATION=1
export GOVERNOR_URL=http://localhost:8080
export GOVERNOR_API_KEY=gov_xxx
pytest tests/integration/ -v
```

Or use the wrapper script, which validates the gateway is up and runs pytest for you:

```bash
./examples/smoke_test.sh
```

The integration suite exercises four invariants:

- **Allow** — `smoke.echo` is permitted; response shape is well-formed.
- **Deny** — `smoke.export_pii` is denied; the SDK raises `GovernorAIDenied` with a non-empty reason.
- **Approval-required** — `smoke.process_payment` requires approval; the SDK raises `GovernorAIApprovalRequired`.
- **Fail-closed** — a closed gateway port raises `GovernorAIError` instead of silently allowing. This is the SDK's most important safety invariant.

Integration tests are auto-skipped when `GOVERNOR_INTEGRATION` is unset, so the default `pytest` invocation stays fast and CI-friendly.

---

## Compatibility

- Python 3.9, 3.10, 3.11, 3.12
- Works with LangChain ≥1.2, LangGraph ≥1.1, LlamaIndex ≥0.14, CrewAI ≥0.11

---

## Links

- **PyPI**: https://pypi.org/project/governor-sdk/
- **Source**: https://github.com/SentinelLayer/GovernorAI/tree/main/sdk/python
- **Issues**: https://github.com/SentinelLayer/GovernorAI/issues
- **GovernorAI platform**: https://governorai.ai

---

## License

Apache License 2.0. See [LICENSE](LICENSE).
