Metadata-Version: 2.4
Name: langchain-preloop
Version: 0.1.0
Summary: LangChain integration for Preloop — the open-source AI agent control plane (MCP firewall, model gateway, human approvals, budgets, and a tamper-evident audit ledger).
Project-URL: Homepage, https://preloop.ai
Project-URL: Repository, https://github.com/preloop/preloop
Project-URL: Documentation, https://preloop.ai/docs
Project-URL: Bug Tracker, https://github.com/preloop/preloop/issues
Author: Preloop
License: Apache-2.0
License-File: LICENSE
Keywords: agent control plane,ai gateway,approvals,governance,human-in-the-loop,langchain,langgraph,mcp,preloop
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Security
Requires-Python: >=3.11
Requires-Dist: httpx>=0.27
Requires-Dist: langchain-core>=0.3
Requires-Dist: langchain-mcp-adapters>=0.1
Requires-Dist: pydantic>=2
Provides-Extra: mcp
Requires-Dist: mcp>=1.0; extra == 'mcp'
Provides-Extra: test
Requires-Dist: langchain-tests>=0.3; extra == 'test'
Requires-Dist: pytest-asyncio>=0.23; extra == 'test'
Requires-Dist: pytest-socket; extra == 'test'
Requires-Dist: pytest>=8; extra == 'test'
Description-Content-Type: text/markdown

# langchain-preloop

LangChain / LangGraph integration for [**Preloop**](https://preloop.ai) — the
open-source AI agent **control plane**. Preloop sits between your agent and its
tools and gives you, in one Apache-2.0, self-hostable layer:

- **MCP firewall** — every tool call is matched against CEL policy and can be
  allowed, denied, or **paused for a human**.
- **Human-in-the-loop approvals** — out-of-band approve/deny from Slack,
  webhook, email, or mobile, with the agent's reasoning, the tool, and the
  arguments shown to the approver.
- **Model gateway** — a unified gateway to OpenAI/Anthropic and 100+ models.
- **Budgets & rate limits** — per-key/user/team cost tracking and caps.
- **Tamper-evident audit ledger** — a hash-chained, append-only record of who
  approved what, when, why, and under which policy version — exportable as
  compliance evidence.

Preloop is a **remote MCP server** (streamable-HTTP at `/mcp/v1`). This package
lets any LangChain or LangGraph agent route its tool calls through that control
plane.

> Positioning note: Preloop is a full control plane — firewall, gateway,
> budgets, and audit — not only an approval button. The approval workflow is the
> most differentiated piece, but this package exposes the whole surface.

## Install

```bash
pip install langchain-preloop
```

Requires Python ≥ 3.11. Pulls in `langchain-core`, `langchain-mcp-adapters`,
`httpx`, and `pydantic`.

## Configure

The client resolves config like the `preloop` CLI does (constructor args
override environment):

| Setting    | Env var          | Default               |
| ---------- | ---------------- | --------------------- |
| `token`    | `PRELOOP_TOKEN`  | _(none)_              |
| `base_url` | `PRELOOP_URL`    | `https://preloop.ai`  |

`token` is a Preloop **API key** (create one in the web UI) or an OAuth access
token, sent as `Authorization: Bearer <token>`. OAuth-capable clients can omit
the token and complete OAuth 2.1 Dynamic Client Registration instead (Preloop
publishes `/.well-known/oauth-authorization-server`). Self-hosters point
`base_url` at their own origin; the `/mcp/v1` path is appended automatically.

## Three ways to use it

### 1. Gate your own tools behind Preloop (`wrap_with_preloop`) — the headline

Wrap any LangChain `BaseTool` so that, before it runs, Preloop evaluates the
call against policy and — when policy requires it — escalates to a human. The
underlying tool executes **only if approved**; otherwise the agent gets the
denial reason back. Same name, same schema, no rewrite of your tool.

```python
from langchain_preloop import PreloopClient, wrap_with_preloop
from langchain_core.tools import tool

@tool
def refund_customer(customer_id: str, amount_usd: float) -> str:
    """Issue a refund to a customer."""
    ...

client = PreloopClient(token="pl_...", base_url="https://preloop.ai")

# Drop-in replacement the agent can call exactly like the original tool.
governed_refund = wrap_with_preloop(refund_customer, client)

# In a LangGraph agent:
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(model, tools=[governed_refund])
```

By default the wrapped tool blocks and polls Preloop until the approval
resolves, then returns Preloop's auto-executed result. Pass `poll=False` to
return immediately on a pending decision, or `policy="my-workflow"` to route to
a named approval workflow.

### 2. Load Preloop's governed tools (`PreloopToolkit`)

Connect to a Preloop instance and get back the live, **policy-filtered** tool
set as LangChain tools — Preloop's built-in governance tools plus any external
MCP server you've registered behind Preloop (it proxies them through the same
firewall). The `tools/list` is filtered to exactly what the presented token's
policy allows.

```python
from langchain_preloop import PreloopToolkit

toolkit = PreloopToolkit(token="pl_...", base_url="https://preloop.ai")
tools = toolkit.get_tools()          # sync
# tools = await toolkit.aget_tools() # async

# Or the functional form:
from langchain_preloop import get_preloop_tools, aget_preloop_tools
tools = get_preloop_tools(token="pl_...")
```

Built-in tools surfaced (subject to policy): `request_approval`,
`get_approval_status`, `search`, `get_issue`, `create_issue`, `update_issue`,
`add_comment`, `update_comment`, `get_pull_request`, `create_pull_request`,
`update_pull_request`, `estimate_compliance`, `improve_compliance`.

### 3. Standalone approval primitives

Typed `BaseTool`s for the two human-approval primitives, usable without
negotiating the full MCP tool list:

```python
from langchain_preloop import (
    PreloopClient,
    PreloopRequestApprovalTool,
    PreloopApprovalStatusTool,
)

client = PreloopClient(token="pl_...")
approve = PreloopRequestApprovalTool(client=client)
status = PreloopApprovalStatusTool(client=client)

result = approve.invoke({
    "operation": "wire_payment",
    "context": "Wire $5,000 to vendor ACME for invoice #42.",
    "reasoning": "Invoice approved in the finance channel; vendor verified.",
})
```

`request_approval` returns either a synchronous grant or a `pending_approval`
payload with a `request_id`; poll it with `get_approval_status`. When a request
is approved, Preloop auto-executes the gated tool and returns the result inline
under `tool_result`.

## How it connects

Tool calls go over MCP streamable-HTTP to `<base_url>/mcp/v1` with
`Authorization: Bearer <token>` and `Accept: application/json,
text/event-stream`. The toolkit is built on
[`langchain-mcp-adapters`](https://github.com/langchain-ai/langchain-mcp-adapters)
so MCP tool schemas are converted to LangChain tools for you.

## Development & tests

```bash
pip install -e ".[test]"

# Unit tests — no network, mock transport:
pytest tests/unit_tests

# Standard langchain-tests suites + live integration tests
# (requires a real Preloop instance):
PRELOOP_TOKEN=pl_xxx PRELOOP_URL=https://staging.preloop.ai pytest tests
```

Unit tests include the `langchain-tests` `ToolsUnitTests` standard suite for both
standalone tools; the integration tests include the matching
`ToolsIntegrationTests` suites and are skipped unless `PRELOOP_TOKEN` is set.

## License

Apache-2.0, matching the Preloop open-source core.
