Metadata-Version: 2.4
Name: watchlight-langgraph
Version: 0.4.0
Summary: Governed LangGraph agents with Watchlight — authorize every agent action, fail-closed, with zero infrastructure.
Author-email: Watchlight AI <team@watchlight.ai>
License: Apache-2.0
Project-URL: Homepage, https://watchlight.ai
Project-URL: Documentation, https://docs.watchlight.ai/de
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.27
Requires-Dist: langgraph>=0.2
Requires-Dist: watchlight-agent-sdk>=0.5.1
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"

# watchlight-langgraph

Governed LangGraph agents with Watchlight — authorize every agent action, fail-closed, with zero infrastructure.

```bash
pip install watchlight-langgraph
```

> **Independent third-party plugin.** This is an independent integration built by Watchlight AI. It is **not affiliated with, endorsed by, or sponsored by** LangChain. `LangGraph` and related names are trademarks of LangChain, used here nominatively only to describe compatibility.

## What it does

`watchlight-langgraph` puts a Watchlight authorization decision in front of every action your LangGraph agent takes — tool calls, plan steps, and sub-agent spawns — so each one is allowed, modified, or denied *before* it runs. It's open-source glue: a thin, framework-specific layer that threads Watchlight's governance primitives into your graph topology. The actual policy decisions run on Watchlight's compiled engine, either in-process for local development or against the governed control plane in production.

## Quickstart

Point the plugin at a backend and wrap your run. Your agent code doesn't change — only the backend does.

For local development, the zero-infrastructure **Developer Edition** runs the compiled engine in-process (requires the `watchlight-engine` package):

```bash
pip install watchlight-langgraph watchlight-engine
```

```python
from watchlight_langgraph import WatchlightLangGraphPlugin
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);'},
]

plugin = WatchlightLangGraphPlugin()
plugin.apdp = InProcessClient(POLICIES)   # decisions run in-process, no server, no network

async def run_agent(question: str):
    async with await plugin.start_run(agent_slug="research-agent") as handle:
        # Validate a multi-step plan ahead of execution (Allow / Modify / Deny).
        result = await handle.submit_plan(["read dataset", "summarize"])
        if result.is_deny():
            raise PermissionError(f"Plan denied: {result.violations}")

        # Gate each action authoritatively. Returns True on Allow, False on Deny.
        if not await handle.authorize_action("read", "dataset"):
            raise PermissionError("Denied by policy")

        # ... your LangGraph agent runs, every action governed ...
```

`authorize_action` fails closed: a denial — or an unreachable backend — returns `False`, so the action never runs.

## Two backends, same code

|  | 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 local to production is a one-line change:

```python
from watchlight_core import ApdpClient

plugin = WatchlightLangGraphPlugin()
plugin.apdp = ApdpClient("https://apdp.your-company.example", api_key="...")
```

## Links

- Documentation: https://docs.watchlight.ai/de
- Website: https://watchlight.ai

## License

Apache-2.0
