Skip to content

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":

  • BlockGuardrailEnforcementTriggered is raised by run_guardrails and 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