LangChain Integration
MendGuardrailMiddleware wraps any LangChain / LangGraph agent with Mend guardrails using the official LangChain middleware system. Guardrails run automatically at four lifecycle hooks — before_agent, after_agent, before_tool, and after_tool — with no changes to your agent logic.
Install
pip install "mend-guardrails[langchain]"
This installs langchain>=0.1.0 and langchain-core>=0.1.0 alongside mend-guardrails.
Quick Start
from langchain.agents import create_agent
from mendguardrails.integrations.langchain import MendGuardrailMiddleware
middleware = MendGuardrailMiddleware(config="guardrails_config.json")
agent = create_agent(
model="gpt-4o",
tools=[search_tool],
middleware=[middleware],
)
result = agent.invoke({
"messages": [{"role": "user", "content": "Hello"}]
})
How it works
User message
↓
before_agent ← input guardrails (jailbreak, PII, harmful content, …)
↓
Agent reasoning loop
↓ ↑
before_tool / after_tool ← Prompt Injection Detection on every tool call
↓
after_agent ← output guardrails (harmful content, PII, …)
↓
Final response
- Agent-level hooks (
before_agent/after_agent) run all guardrails except Prompt Injection Detection once per invocation. - Tool-level hooks (
before_tool/after_tool) run Prompt Injection Detection for every individual tool call and its output.
Enforcement mode (block vs. alert) is set per-guardrail inside the policy — a guardrail configured as "Block" short-circuits execution and returns an error message, while one configured as "Alert" logs the event and lets the agent continue.
Configuration
MendGuardrailMiddleware accepts the same policy sources as every other Mend client.
from pathlib import Path
from mendguardrails import JsonString
from mendguardrails.integrations.langchain import MendGuardrailMiddleware
# File path (recommended)
middleware = MendGuardrailMiddleware(config=Path("guardrails_config.json"))
# Dictionary
middleware = MendGuardrailMiddleware(config={
"version": 1,
"input": {"version": 1, "guardrails": [...]},
"output": {"version": 1, "guardrails": [...]},
})
# JSON string
middleware = MendGuardrailMiddleware(config=JsonString('{"version": 1, ...}'))
# Remote policy (online mode, no local config required)
middleware = MendGuardrailMiddleware()
Constructor parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
config |
str \| Path \| dict \| None |
None |
Policy source. None fetches remote policy (online) or uses default (offline). Enforcement mode is set per-guardrail inside the policy. |
raise_guardrail_errors |
bool |
False |
Re-raise internal guardrail errors. Default treats them as safe and continues. |
context |
Any |
None |
Custom guardrail execution context. Auto-created from AsyncOpenAI() when None. |
mend_key |
str \| None |
None |
Mend license key. Falls back to the MEND_KEY environment variable. |
offline |
bool \| None |
None |
Disable all external API calls. Falls back to MEND_GUARDRAILS_OFFLINE. |
Enforcement behaviour
Enforcement is policy-driven. Each guardrail in the policy has an action of either "Block" or "Alert":
- Block —
GuardrailEnforcementTriggeredis raised byrun_guardrailsand the middleware translates it into the appropriate hook response to stop execution. - Alert — the guardrail result is returned normally; the agent continues and the event is audited.
| Hook | Block action |
|---|---|
before_agent |
Jumps to end; returns AIMessage with the block reason. |
after_agent |
Replaces the last AIMessage with the block reason. |
before_tool |
Returns a ToolMessage with the block reason; tool is never called. |
after_tool |
Replaces the last ToolMessage with the block reason. |
Error handling
By default (raise_guardrail_errors=False) any exception that occurs inside a guardrail check is caught, logged at WARNING, and treated as a pass — your agent keeps running. Set raise_guardrail_errors=True to surface those errors:
middleware = MendGuardrailMiddleware(
config="guardrails_config.json",
raise_guardrail_errors=True,
)
Offline mode
import os
os.environ["MEND_GUARDRAILS_OFFLINE"] = "true"
middleware = MendGuardrailMiddleware(config="guardrails_config.json")
Or pass offline=True directly to the constructor. In offline mode no license validation, policy fetching, or audit events are sent.
Observability
Attach an on_guardrail_event callback or an OTel handler to receive audit events for every guardrail check:
from mendguardrails import OtelGuardrailHandler
from mendguardrails.integrations.langchain import MendGuardrailMiddleware
otel_handler = OtelGuardrailHandler()
middleware = MendGuardrailMiddleware(config="guardrails_config.json")
See Observability and OpenTelemetry for full details.
Next steps
- Enforcement — configure guardrail policies.
- Error Handling — handle
GuardrailEnforcementTriggeredexceptions. - Observability — audit logging and tracing.
- Examples — complete working code samples.