Metadata-Version: 2.4
Name: watchlight-agent-sdk
Version: 0.5.1
Summary: Watchlight Agent SDK — build governed AI-agent plugins for any framework
Author-email: Watchlight AI <team@watchlight.ai>
License: Apache-2.0
Project-URL: Homepage, https://www.watchlight.ai
Project-URL: Documentation, https://docs.watchlight.ai
Project-URL: Repository, https://github.com/watchlight-ai-beacon/watchlight
Project-URL: Plugin SDK Guide, https://github.com/watchlight-ai-beacon/watchlight/tree/main/plugins
Keywords: watchlight,ai-governance,agent-runtime,ai-agents,agent-sdk,policy-decision-point,cedar-policy
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
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 :: System :: Monitoring
Classifier: Topic :: Security
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.0
Requires-Dist: typing-extensions>=4.5; python_version < "3.12"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Requires-Dist: mypy>=1.8; extra == "dev"
Requires-Dist: cryptography>=42; extra == "dev"
Requires-Dist: requests>=2.32; extra == "dev"
Provides-Extra: otlp
Requires-Dist: opentelemetry-api>=1.20; extra == "otlp"
Requires-Dist: opentelemetry-sdk>=1.20; extra == "otlp"
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.20; extra == "otlp"

# watchlight-agent-sdk

**Build governed AI agents.** The Watchlight Agent SDK lets you put a real,
fail-closed authorization decision in front of every action your agent takes —
and record what happened — with the same code whether you run it on your laptop
or across a production fleet.

```bash
pip install watchlight-agent-sdk
```

Import it as `watchlight_core`.

## What it does

Your agent asks "may I do this?" before it acts; Watchlight answers `Allow` or
`Deny` by evaluating your policies, and the action only runs if it's permitted.
The SDK gives you:

- **Authorization** — `authorize_action(action, resource)` gates every step, fail-closed.
- **Preflight** — a cheap read-only "would this be allowed?" check.
- **Lifecycle** — a `RunHandle` per agent run: submit a plan, authorize steps, complete or terminate.
- **Lineage** — canonical, value-free execution events for audit and debugging.
- **Framework plugins** — ready-made integrations for LangGraph, Google ADK, AWS
  Bedrock, Microsoft Agent Framework, Pydantic AI, and more.

The SDK is **glue**: it shapes a request, hands it to a Watchlight backend, and
projects the answer. Every decision is made by the backend — never in this
package — which is why it's open source (Apache-2.0).

## Two backends, same code

The SDK talks to a **backend** through one small interface, so the exact same
agent and plugin code runs against either:

| | Backend | Runs |
|---|---|---|
| **Developer Edition** | `InProcessClient` | The compiled engine, **in-process** — no server, no network |
| **Enterprise** | `ApdpClient` | The governed control plane — signed lineage, drift detection, fleet-wide governance |

Moving from one to the other is a one-line change, never a rewrite.

## Quickstart — a governed decision, zero infrastructure

Install the in-process engine alongside the SDK:

```bash
pip install watchlight-agent-sdk watchlight-engine
```

```python
import asyncio
from watchlight_core import InProcessClient

# A Cedar policy: the research agent may read, nothing else.
POLICIES = [
    {"name": "reader",
     "code": 'permit(principal == User::"research-agent", action == Action::"read", resource);'},
]

async def main():
    gov = InProcessClient(POLICIES)          # decisions run in-process; lineage → .watchlight/audit.jsonl
    print((await gov.authorize("research-agent", "read", "dataset"))["decision"])    # Allow
    print((await gov.authorize("research-agent", "delete", "dataset"))["decision"])  # Deny

asyncio.run(main())
```

```text
Allow
Deny
```

That `Deny` is the point: the action is refused **before** it runs — by the same
engine that powers the Watchlight platform, with no database and no network.

## Govern a framework agent

Install the plugin for your framework and point it at a backend — your agent code
doesn't change:

```python
from watchlight_langgraph import WatchlightLangGraphPlugin   # or -adk, -bedrock, -pydantic-ai, …
from watchlight_core import InProcessClient

plugin = WatchlightLangGraphPlugin()
plugin.apdp = InProcessClient(POLICIES)      # the one line that differs from production

async with await plugin.start_run("research-agent") as handle:
    if not await handle.authorize_action("read", "dataset"):
        raise PermissionError("denied by policy")
    # ... your agent runs, every action governed ...
```

## Custom agents (any framework)

For an agent not built on a supported framework, the `@watchlight` decorator
governs any function:

```python
from watchlight_core import InProcessClient, watchlight

gov = InProcessClient(POLICIES)

@watchlight(agent_id="custom-research", client=gov)
async def run_research(query: str) -> str:
    ...
```

## Optional: OpenTelemetry export

Install the `[otlp]` extra to export a subset of the lineage stream to your OTel
collector (off by default):

```bash
pip install 'watchlight-agent-sdk[otlp]'
```

## Learn more

- **Documentation:** https://docs.watchlight.ai
- **Developer Edition** (zero-infra quickstart) and **Enterprise** (the governed
  control plane): https://watchlight.ai

## License

Apache-2.0.
