langchain-preloop
LangChain / LangGraph integration for Preloop — 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
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.
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.
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 BaseTools for the two human-approval primitives, usable without
negotiating the full MCP tool list:
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
so MCP tool schemas are converted to LangChain tools for you.
Development & tests
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.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file langchain_preloop-0.1.0.tar.gz.
File metadata
- Download URL: langchain_preloop-0.1.0.tar.gz
- Upload date:
- Size: 19.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3051ac696ef3304795ca08900f437e77d55cefd3a403c10b8a9d1da167ab2893
|
|
| MD5 |
f2e910bf6051e17665e40427a8fd2af2
|
|
| BLAKE2b-256 |
2cb5f0b8445c7f6888a135961720e31eb487f9bd9e3752a129654995bfdc858b
|
File details
Details for the file langchain_preloop-0.1.0-py3-none-any.whl.
File metadata
- Download URL: langchain_preloop-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3de51492a3c5c33144ac8e9f0e63c09947c4d4b0140fd0b504b2d4155056cb2d
|
|
| MD5 |
ab4664d51a097637ae9cc931ba399c74
|
|
| BLAKE2b-256 |
e8cbbb41d75313c0c5806dc5ced1635964c7de6e4945c6ae359ab326874144e1
|