Skip to content

Framework Compatibility Guide

Agent-Airlock is designed to work seamlessly with all major AI agent frameworks in 2026. This guide covers integration patterns, the critical "Golden Rule" for decorator ordering, and links to comprehensive examples.

See also: Full working examples in examples/


The Golden Rule

Always put @Airlock closest to the function definition.

AI frameworks like LangChain, CrewAI, OpenAI Agents SDK, and AutoGen use inspect.signature() to generate JSON schemas for LLM tool calls. If decorators are ordered incorrectly, the LLM sees "empty arguments" and tool calls fail.

Correct Order

# ✅ CORRECT: @Airlock is closest to the function
@framework_decorator
@Airlock()
def my_tool(x: int, y: str) -> dict:
    return {"x": x, "y": y}

Incorrect Order

# ❌ WRONG: @Airlock wraps the framework decorator
@Airlock()
@framework_decorator
def my_tool(x: int, y: str) -> dict:
    return {"x": x, "y": y}

Why? Agent-Airlock preserves the original function's __signature__, __annotations__, and __wrapped__ attributes. When it's closest to the function, this information flows up through the decorator chain correctly.


LangChain Integration

LangChain's @tool decorator reads function signatures to build schemas for the LLM.

Full example: examples/langchain_integration.py

Basic Usage

from langchain.tools import tool
from agent_airlock import Airlock, AirlockConfig

config = AirlockConfig(strict_mode=True)

@tool
@Airlock(config=config)
def search_database(query: str, limit: int = 10) -> list[dict]:
    """Search the database for matching records.

    Args:
        query: The search query string
        limit: Maximum number of results to return
    """
    return db.search(query, limit=limit)

With AgentExecutor

from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_openai import ChatOpenAI
from langchain.tools import tool
from agent_airlock import Airlock, STRICT_POLICY

@tool
@Airlock(policy=STRICT_POLICY)
def get_user_info(user_id: str) -> dict:
    """Get information about a user."""
    return {"id": user_id, "name": "John Doe"}

llm = ChatOpenAI(model="gpt-4")
tools = [get_user_info]
agent = create_openai_tools_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools)

References


LangGraph Integration

LangGraph is the evolution of LangChain for stateful, graph-based agent workflows.

Full example: examples/langgraph_integration.py

With ToolNode

from langchain_core.tools import tool
from langgraph.prebuilt import ToolNode
from langgraph.graph import StateGraph, MessagesState
from agent_airlock import Airlock

@tool
@Airlock()
def add(a: int, b: int) -> int:
    """Add two numbers."""
    return a + b

@tool
@Airlock()
def multiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b

# Create ToolNode with secured tools
tools = [add, multiply]
tool_node = ToolNode(tools)

# Build graph
workflow = StateGraph(MessagesState)
workflow.add_node("agent", call_model)
workflow.add_node("tools", tool_node)
# ... add edges

References


CrewAI Integration

CrewAI's @tool decorator enables role-based multi-agent collaboration.

Full example: examples/crewai_integration.py

Basic Usage

from crewai.tools import tool
from agent_airlock import Airlock, READ_ONLY_POLICY

@tool("Database Query Tool")
@Airlock(policy=READ_ONLY_POLICY)
def query_database(sql: str) -> list[dict]:
    """Execute a read-only SQL query."""
    return db.execute(sql)

With Crew Agents

from crewai import Agent, Crew, Task
from crewai.tools import tool
from agent_airlock import Airlock, SecurityPolicy

ANALYST_POLICY = SecurityPolicy(
    allowed_tools=["query_*", "read_*"],
    denied_tools=["write_*", "delete_*"],
    rate_limits={"*": "100/hour"},
)

@tool("Query Tool")
@Airlock(policy=ANALYST_POLICY)
def query_data(metric: str) -> dict:
    """Query analytics data."""
    return analytics.query(metric)

analyst = Agent(
    role="Data Analyst",
    goal="Analyze business metrics",
    tools=[query_data],
)

References


OpenAI Agents SDK Integration

OpenAI's Agents SDK is a lightweight framework for multi-agent workflows.

Full example: examples/openai_agents_sdk_integration.py

Basic Usage

from agents import Agent, Runner, function_tool
from agent_airlock import Airlock, AirlockConfig

config = AirlockConfig(strict_mode=True, mask_pii=True)

@function_tool
@Airlock(config=config)
def get_weather(city: str, units: str = "celsius") -> str:
    """Get weather for a city."""
    return f"Weather in {city}: 22°{units[0].upper()}"

agent = Agent(
    name="weather_agent",
    tools=[get_weather],
    model="gpt-4o-mini",
)

Handoff Pattern

# Specialist agents with secured tools
billing_agent = Agent(
    name="billing",
    tools=[get_billing_info],  # @Airlock secured
)

technical_agent = Agent(
    name="technical",
    tools=[check_service, execute_code],  # @Airlock secured
)

# Triage agent with handoffs
triage = Agent(
    name="triage",
    handoffs=[billing_agent, technical_agent],
)

References


PydanticAI Integration

PydanticAI provides type-safe agents with Pydantic validation.

Full example: examples/pydanticai_integration.py

Basic Usage

from pydantic_ai import Agent
from agent_airlock import Airlock

# Pre-secure the function
@Airlock()
def get_stock_price(symbol: str) -> str:
    """Get stock price."""
    return f"Stock {symbol}: $150.25"

# Pass to Agent
agent = Agent(
    "openai:gpt-4o",
    tools=[get_stock_price],
)

With @agent.tool_plain

from pydantic_ai import Agent
from agent_airlock import Airlock

agent = Agent("openai:gpt-4o")

@agent.tool_plain
@Airlock()
def search(query: str) -> str:
    """Search for information."""
    return f"Results for '{query}'"

References


Microsoft AutoGen Integration

AutoGen enables multi-agent conversations and code execution.

Full example: examples/autogen_integration.py

AutoGen 0.4+ (FunctionTool)

from autogen_agentchat.agents import AssistantAgent
from autogen_core.tools import FunctionTool
from agent_airlock import Airlock

@Airlock()
def get_weather(city: str) -> str:
    """Get weather."""
    return f"Weather in {city}: Sunny"

# Wrap as FunctionTool
weather_tool = FunctionTool(get_weather, description="Get weather")

# Use with AssistantAgent
agent = AssistantAgent(
    name="assistant",
    tools=[get_weather],  # Direct function works too
)

AutoGen 0.2 (register_function)

from autogen import ConversableAgent, register_function
from agent_airlock import Airlock

@Airlock()
def calculate(expression: str) -> str:
    """Calculate math."""
    return str(eval(expression))

assistant = ConversableAgent("assistant", llm_config=llm_config)
executor = ConversableAgent("executor", human_input_mode="NEVER")

register_function(
    calculate,
    caller=assistant,
    executor=executor,
    description="Calculate math expressions",
)

References


LlamaIndex Integration

LlamaIndex provides tools for RAG and agent workflows.

Full example: examples/llamaindex_integration.py

FunctionTool

from llama_index.core.tools import FunctionTool
from llama_index.core.agent import ReActAgent
from agent_airlock import Airlock

@Airlock()
def search_docs(query: str) -> str:
    """Search documents."""
    return f"Found docs for '{query}'"

# Wrap as FunctionTool
search_tool = FunctionTool.from_defaults(fn=search_docs)

# Use with ReActAgent
agent = ReActAgent.from_tools([search_tool], llm=llm)

References


Hugging Face smolagents Integration

smolagents provides code-writing agents that are 30% more efficient than ReAct.

Full example: examples/smolagents_integration.py

Basic Usage

from smolagents import CodeAgent, InferenceClientModel, tool
from agent_airlock import Airlock

@tool
@Airlock()
def calculator(expression: str) -> str:
    """Calculate math expressions."""
    return str(eval(expression))

agent = CodeAgent(
    tools=[calculator],
    model=InferenceClientModel(),
)
result = agent.run("Calculate 15 * 23")

References


Anthropic Claude Integration

Direct integration with Anthropic's Claude API for tool use.

Full example: examples/anthropic_integration.py

Pattern

import anthropic
from agent_airlock import Airlock

# 1. Define secured function
@Airlock()
def get_weather(location: str) -> str:
    """Get weather."""
    return f"Weather in {location}: Sunny"

# 2. Create tool schema
WEATHER_TOOL = {
    "name": "get_weather",
    "description": "Get weather for a location",
    "input_schema": {
        "type": "object",
        "properties": {
            "location": {"type": "string"},
        },
        "required": ["location"],
    },
}

# 3. Execute on tool_use
def execute_tool(name: str, input: dict) -> str:
    if name == "get_weather":
        return get_weather(**input)

References


FastMCP Integration

FastMCP is the recommended way to build MCP servers.

Full example: examples/fastmcp_integration.py

@secure_tool Convenience Decorator

from agent_airlock.mcp import secure_tool, create_secure_mcp_server

mcp, secure = create_secure_mcp_server("My Server")

@secure
def read_file(path: str) -> str:
    """Read a file."""
    return Path(path).read_text()

@secure(sandbox=True, sandbox_required=True)
def execute_code(code: str) -> str:
    """Execute code in sandbox."""
    exec(code)
    return "done"

Sandbox Execution with Frameworks

For dangerous operations, use sandbox=True with sandbox_required=True:

from langchain.tools import tool
from agent_airlock import Airlock

@tool
@Airlock(sandbox=True, sandbox_required=True)
def execute_code(python_code: str) -> str:
    """Execute Python code in a secure sandbox.

    SECURITY: This runs in an isolated E2B Firecracker MicroVM.
    It will NEVER fall back to local execution.
    """
    import io, sys
    old_stdout = sys.stdout
    sys.stdout = io.StringIO()
    try:
        exec(python_code)
        return sys.stdout.getvalue()
    finally:
        sys.stdout = old_stdout

Troubleshooting

Problem: LLM sees empty arguments

Cause: Decorator order is wrong.

Solution: Put @Airlock closest to the function definition.

Problem: Type validation fails unexpectedly

Cause: Airlock uses Pydantic strict mode—no type coercion.

Solution: Ensure your function has proper type hints and the LLM sends correct types.

Problem: Ghost arguments being stripped

Cause: LLM is hallucinating parameters that don't exist.

Solution: This is expected behavior! Airlock strips them by default. Use strict_mode=True to reject instead.

Problem: Rate limit errors

Cause: Policy rate limits exceeded.

Solution: Check your SecurityPolicy rate limits. Default is no limit.


Framework Support Matrix

Framework Version Status Decorator Pattern
LangChain 0.3+ ✅ Full @tool → @Airlock
LangGraph 1.x ✅ Full @tool → @Airlock
CrewAI 0.50+ ✅ Full @tool() → @Airlock
OpenAI Agents SDK 0.7+ ✅ Full @function_tool → @Airlock
PydanticAI 0.3+ ✅ Full @agent.tool_plain → @Airlock
AutoGen 0.4+ ✅ Full @Airlock → FunctionTool()
AutoGen 0.2 ✅ Full @Airlock → register_function()
LlamaIndex 0.11+ ✅ Full @Airlock → FunctionTool.from_defaults()
smolagents 1.x ✅ Full @tool → @Airlock
Anthropic Claude 0.40+ ✅ Full @Airlock → schema dict
FastMCP 2.x ✅ Full @mcp.tool → @Airlock or @secure_tool
Claude Tools - ✅ Full Standard decorator pattern
OpenAI Functions - ✅ Full Schema generated correctly

Performance Notes

  • Validation overhead: <50ms per call
  • E2B cold start: ~125ms (Firecracker MicroVM)
  • E2B warm pool: <200ms (pre-warmed sandboxes)
  • Signature introspection: Negligible (cached by frameworks)

References