Skip to main content

Cisco AI Defense middleware for LangChain agents — runtime security inspection of LLM inputs/outputs and tool/MCP calls

Project description

langchain-cisco-aidefense

PyPI version License Python 3.10+

LangChain agent middleware for Cisco AI Defense, providing runtime security inspection of LLM inputs/outputs and tool/MCP calls.

Detects prompt injection, jailbreaks, PII leakage, toxic content, and unsafe tool usage — directly within the LangChain agent loop.

Installation

pip install langchain-cisco-aidefense

Middleware Overview

create_agent (LangChain LCEL) — four middleware classes

LLM Inspection (before_model / after_model)

Middleware Built on Best for
AIDefenseMiddleware ChatInspectionClient New integrations — lightweight, no global state
AIDefenseAgentsecMiddleware agentsec LLMInspector When you need agentsec's retry/backoff machinery

Tool / MCP Inspection (wrap_tool_call)

Middleware Built on Best for
AIDefenseToolMiddleware MCPInspectionClient New integrations — tool/MCP call inspection
AIDefenseAgentsecToolMiddleware agentsec MCPInspector When you need agentsec's retry/backoff machinery

create_react_agent (LangGraph prebuilt) — added in v1.1.0

Symbol Purpose
AIDefenseHooks Provides pre_model_hook / post_model_hook for LLM inspection
AIDefenseToolNode ToolNode subclass for tool call inspection
create_aidefense_react_agent Drop-in replacement for create_react_agent

Quick Start

pip install langchain-cisco-aidefense langchain-openai
from aidefense_langchain import AIDefenseMiddleware
from langchain.agents import create_agent

agent = create_agent(
    model="openai:gpt-4.1",
    tools=[get_weather],
    middleware=[
        AIDefenseMiddleware(
            api_key="your-cisco-ai-defense-api-key",
            region="us-west-2",
            mode="enforce",
        ),
    ],
)

result = agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})

LLM Inspection

AIDefenseMiddleware (Recommended)

Uses ChatInspectionClient directly. Self-contained configuration, no global state, no monkey-patching.

from aidefense_langchain import AIDefenseMiddleware
from langchain.agents import create_agent

agent = create_agent(
    model="openai:gpt-4.1",
    tools=[get_weather],
    middleware=[
        AIDefenseMiddleware(
            api_key="your-api-key",
            region="us-west-2",
            mode="enforce",       # "enforce" | "monitor" | "off"
            fail_open=True,
        ),
    ],
)

Parameters

Parameter Type Default Description
api_key str required Cisco AI Defense API key
region str "us-west-2" AI Defense region ("us-west-2", "eu-central-1", "ap-northeast-1")
mode str "enforce" "enforce" (block), "monitor" (log only), "off"
fail_open bool True Allow on inspection API errors
timeout int 30 Inspection timeout in seconds
rules list None Rules to enable (e.g. ["PII", "Prompt Injection"])
user str None User identity for audit
src_app str None Source application name
on_violation callable None (InspectResponse, direction) -> None callback

How it works

User message
    |
    v
+--------------------------------------------------+
|  before_model hook                               |
|  -> ChatInspectionClient.inspect_conversation()  |
|  -> if not safe and mode="enforce": jump_to=end  |
+--------------------------------------------------+
    |
    v
  LLM call
    |
    v
+--------------------------------------------------+
|  after_model hook                                |
|  -> ChatInspectionClient.inspect_conversation()  |
|  -> if not safe and mode="enforce": jump_to=end  |
+--------------------------------------------------+
    |
    v
Agent response

AIDefenseAgentsecMiddleware

Uses agentsec's LLMInspector — gets retry with exponential backoff and fail-open semantics.

from aidefense_langchain import AIDefenseAgentsecMiddleware
from langchain.agents import create_agent

agent = create_agent(
    model="openai:gpt-4.1",
    tools=[get_weather],
    middleware=[
        AIDefenseAgentsecMiddleware(
            mode="enforce",
            api_key="your-api-key",
            endpoint="https://us.api.inspect.aidefense.security.cisco.com",
            retry_total=3,
            retry_backoff=1.0,
        ),
    ],
)

Do not call agentsec.protect() when using middleware. The middleware handles all inspection directly. Calling protect() would activate monkey-patching on the underlying LLM SDK, causing every request to be inspected twice — once by the patched SDK and once by the middleware — doubling latency and API calls with no security benefit.

Parameters

Parameter Type Default Description
mode str "enforce" "enforce", "monitor", or "off"
api_key str from state/env AI Defense API key
endpoint str from state/env AI Defense API endpoint
fail_open bool True Allow on inspection errors
timeout_ms int from state Timeout in milliseconds
retry_total int 1 Retry attempts
retry_backoff float 0.0 Backoff factor in seconds
rules list None Inspection rules
user str None User identity
src_app str None Source application name
on_violation callable None (Decision, direction) -> None callback

Tool / MCP Inspection

AIDefenseToolMiddleware (Recommended for tools)

Uses MCPInspectionClient to inspect tool call requests (name + arguments) and tool call results.

from aidefense_langchain import AIDefenseMiddleware, AIDefenseToolMiddleware
from langchain.agents import create_agent

agent = create_agent(
    model="openai:gpt-4.1",
    tools=[search_db, send_email],
    middleware=[
        AIDefenseMiddleware(api_key="your-key", mode="enforce"),
        AIDefenseToolMiddleware(api_key="your-key", mode="enforce"),
    ],
)

AIDefenseAgentsecToolMiddleware

Uses agentsec's MCPInspector with retry, backoff, and fail-open support.

from aidefense_langchain import AIDefenseAgentsecMiddleware, AIDefenseAgentsecToolMiddleware

agent = create_agent(
    model="openai:gpt-4.1",
    tools=[read_file, execute_query],
    middleware=[
        AIDefenseAgentsecMiddleware(mode="enforce", api_key="your-key"),
        AIDefenseAgentsecToolMiddleware(mode="enforce", api_key="your-key"),
    ],
)

Tool Middleware Parameters

Parameter Type Default Description
api_key str required / from env Cisco AI Defense API key
region str "us-west-2" AI Defense region (ChatClient variant only)
mode str "enforce" "enforce", "monitor", or "off"
fail_open bool True Allow on inspection API errors
inspect_requests bool True Inspect tool call requests before execution
inspect_responses bool True Inspect tool results after execution
on_violation callable None Violation callback

How tool inspection works

Tool call (from LLM)
    |
    v
+--------------------------------------------------+
|  wrap_tool_call -- PRE-CALL inspection           |
|  -> MCPInspectionClient.inspect_tool_call()      |
|  -> if not safe and mode="enforce": return block |
+--------------------------------------------------+
    |
    v
  Tool executes
    |
    v
+--------------------------------------------------+
|  wrap_tool_call -- POST-CALL inspection          |
|  -> MCPInspectionClient.inspect_response()       |
|  -> if not safe and mode="enforce": return block |
+--------------------------------------------------+
    |
    v
Tool result returned to agent

This covers all tool types:

  • LangChain tools (@tool decorated functions)
  • MCP tools registered via LangChain's MCP integration
  • Any tool executed through the agent's tool node

Environment Variables

The middleware can also be configured via environment variables (used by from_env() class methods):

export AIDEFENSE_API_KEY=your-api-key
export AIDEFENSE_REGION=us-west-2
export AIDEFENSE_MODE=enforce
export AIDEFENSE_FAIL_OPEN=true
export AIDEFENSE_TIMEOUT=30
from aidefense_langchain import AIDefenseMiddleware

middleware = AIDefenseMiddleware.from_env()

Comparison

Criteria AIDefenseMiddleware AIDefenseAgentsecMiddleware
No global state / side effects Yes No (uses _state)
Self-contained config Yes Yes (pass explicitly)
Built-in retry + backoff Via Config Custom
Built-in fail-open In middleware In inspector
inspect_prompt / inspect_response Yes No (inspect_conversation only)
Dependency footprint Lighter (aidefense.runtime) Heavier (aidefense.runtime.agentsec)

Recommendation: Use AIDefenseMiddleware for new projects. Use AIDefenseAgentsecMiddleware when you need agentsec's retry/backoff machinery.

Enforcement Modes

Mode Behavior
enforce Block violations — agent returns a "blocked" message via jump_to: "end"
monitor Log violations and invoke on_violation callback; never blocks
off Skip inspection entirely

Fail-Open Behavior

When fail_open=True (default) and the AI Defense inspection API is unreachable:

  • The request is allowed to proceed
  • A warning is logged

When fail_open=False:

  • The request is blocked (or an exception is raised)

Examples

# File Description
1 01_chat_client_enforce.py ChatClient middleware — enforce mode (block violations)
2 02_chat_client_monitor.py ChatClient middleware — monitor mode with violation callback
3 03_chat_client_with_rules.py ChatClient middleware — specific rules (PII, Prompt Injection)
4 04_agentsec_enforce.py Agentsec middleware — enforce mode with retry config
5 05_composed_middleware.py AI Defense + custom logging middleware composed together
6 06_side_by_side.py Same request through both middleware — side-by-side comparison
7 07_tool_inspection_enforce.py Tool inspection — LLM + tool call inspection combined
8 08_tool_inspection_agentsec.py Agentsec tool inspection — MCPInspector with retry
9 09_callback_handler_create_react_agent.py create_react_agent with OpenAI — Options A & B
10 10_azure_openai_create_react_agent.py create_react_agent with Azure OpenAI + macOS SSL fix

create_react_agent Integration (v1.1.0)

LangGraph's create_react_agent does not expose before_model / after_model hooks, so the middleware classes above cannot be used with it directly. v1.1.0 adds native support via LangGraph's pre_model_hook, post_model_hook, and ToolNode.wrap_tool_call.

Requires langgraph >= 0.2.27.

Option A — Primitives (maximum control)

from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langgraph.prebuilt import create_react_agent
from aidefense_langchain import AIDefenseHooks, AIDefenseToolNode, AIDefenseViolationError

@tool
def get_weather(city: str) -> str:
    """Return current weather for a city."""
    return f"It's 72°F and sunny in {city}!"

hooks = AIDefenseHooks(api_key="<AIDEFENSE_API_KEY>", mode="enforce")
tool_node = AIDefenseToolNode([get_weather], api_key="<AIDEFENSE_API_KEY>", mode="enforce")

agent = create_react_agent(
    model=ChatOpenAI(model="gpt-4o-mini"),
    tools=tool_node,
    pre_model_hook=hooks.pre_model_hook,
    post_model_hook=hooks.post_model_hook,
)

try:
    result = agent.invoke({"messages": [("user", "What's the weather in Seattle?")]})
    print(result["messages"][-1].content)
except AIDefenseViolationError as e:
    print(f"Blocked at '{e.direction}': {e}")

Option B — Convenience wrapper (minimum changes)

from aidefense_langchain import create_aidefense_react_agent, AIDefenseViolationError

agent = create_aidefense_react_agent(
    model=ChatOpenAI(model="gpt-4o-mini"),
    tools=[get_weather],
    api_key="<AIDEFENSE_API_KEY>",
    mode="enforce",
)

Violation handling

AIDefenseViolationError carries:

  • .direction"input", "output", "tool '<name>' input", or "tool '<name>' output"
  • .response — the full InspectResponse from the SDK (includes event_id, severity, explanation)

In "monitor" mode, violations are logged and the optional on_violation callback is invoked, but the agent continues:

violations = []
agent = create_aidefense_react_agent(
    model=llm, tools=[get_weather],
    api_key="<AIDEFENSE_API_KEY>",
    mode="monitor",
    on_violation=lambda resp, direction: violations.append(direction),
)

LangGraph V2.0 note: create_react_agent is deprecated in langgraph.prebuilt (LangGraph V1.0) and will move to langchain.agents in V2.0. Update your import when you upgrade.

Development

git clone https://github.com/cisco-ai-defense/ai-defense-langchain-middleware.git
cd ai-defense-langchain-middleware
pip install -e ".[dev,examples]"
pytest

License

Apache-2.0 — see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

langchain_cisco_aidefense-1.1.0.tar.gz (33.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

langchain_cisco_aidefense-1.1.0-py3-none-any.whl (33.0 kB view details)

Uploaded Python 3

File details

Details for the file langchain_cisco_aidefense-1.1.0.tar.gz.

File metadata

File hashes

Hashes for langchain_cisco_aidefense-1.1.0.tar.gz
Algorithm Hash digest
SHA256 1843908d671bbd104a7dbcb3bcc85706e4e7c6bfef0176a124370319c81fa401
MD5 9c2eb34c348a3e0ec7ce96576cf22c82
BLAKE2b-256 2b1456ede2233fafb7c11a1a8e8ea913be6442338141ea87845c7dbb52e2ed4d

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_cisco_aidefense-1.1.0.tar.gz:

Publisher: release.yml on cisco-ai-defense/ai-defense-langchain-middleware

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file langchain_cisco_aidefense-1.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for langchain_cisco_aidefense-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f0b87f7cb81870a5aeb3af3cf229c2676dd9c4154763e53ceebe2631612de596
MD5 82dde9cd1105e99be462d53f031ccf5e
BLAKE2b-256 449278e9123f1d2bce8678c80e2c3b5e886495a4b99d9062ef9800390bb89988

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_cisco_aidefense-1.1.0-py3-none-any.whl:

Publisher: release.yml on cisco-ai-defense/ai-defense-langchain-middleware

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page