Framework Adapters

Each framework below gets governed at the boundary that framework actually exposes — a process-wide hook, or a per-tool wrapper. Pick your framework and language; the rest of this page follows the same shape everywhere: start Netzilo once, then wrap or register your tools as usual.

See Custom Agents first if you haven't installed the SDK or called start() yet.

CrewAI

from netzilo.crewai import govern

govern(config={"server": "...", "pat": "...", "agent_name": "my-agent"})

MyCrew().crew().kickoff(inputs={...})   # governed

CrewAI AMP (the managed runtime) only executes Flow @start/@listen steps, so put govern() inside a @start method instead:

from crewai.flow import Flow, listen, start

class MyFlow(Flow):
    @start()
    def init_governance(self):
        import netzilo, netzilo.crewai
        netzilo.crewai.govern(config={"server": "...", "pat": "...", "agent_name": "my-agent"})

    @listen(init_governance)
    def run(self):
        return MyCrew().crew().kickoff(inputs={...})

LangGraph

import netzilo.langgraph

graph = StateGraph(State)
graph.add_node("agent", agent_fn)
graph.add_node("tools", tool_fn)

netzilo.langgraph.govern(graph, config={"server": "...", "pat": "..."})  # call before compile()

app = graph.compile()
app.invoke({...})

For full prompt/response redaction at the chat-model level:

from netzilo.langgraph import govern_model

model = govern_model(ChatAnthropic(model="claude-sonnet-4-6"))
agent = create_react_agent(model, tools)   # redaction enforced end-to-end

AutoGen

from netzilo.autogen import handler
from autogen_core import SingleThreadedAgentRuntime

runtime = SingleThreadedAgentRuntime(
    intervention_handlers=[handler(config={"server": "...", "pat": "..."})]
)

Strands / Bedrock AgentCore

from netzilo.strands import govern

govern()   # config from NETZILO_* env vars; non-blocking

LangChain

from netzilo.langchain import govern, govern_tool
from langchain_core.tools import StructuredTool

govern()

@govern_tool
def get_order_status(order_id: str) -> str:
    ...

tool = StructuredTool.from_function(func=get_order_status)

Full prompt/response redaction at the chat-model level (Python only):

from netzilo.langchain import govern_model

model = govern_model(ChatAnthropic(model="claude-sonnet-4-6"))

LlamaIndex

from netzilo.llamaindex import govern, govern_tool
from llama_index.core.tools import FunctionTool

govern()

@govern_tool
def get_order_status(order_id: str) -> str:
    ...

tool = FunctionTool.from_defaults(fn=get_order_status)

OpenAI Agents SDK

from netzilo.openai_agents import govern, govern_tool
from agents import Agent, function_tool

govern()

@function_tool
@govern_tool
def get_order_status(order_id: str) -> str:
    """Look up an order's status."""
    ...

agent = Agent(name="Support", tools=[get_order_status])

Google ADK

from netzilo.google_adk import govern, govern_tool
from google.adk.tools import FunctionTool

govern()

@govern_tool
def get_order_status(order_id: str) -> str:
    ...

tool = FunctionTool(get_order_status)

Pydantic AI

from netzilo.pydantic_ai import govern, govern_tool
from pydantic_ai import Agent

govern()

@govern_tool
def get_order_status(order_id: str) -> str:
    ...

agent = Agent("openai:gpt-4o", tools=[get_order_status])

Semantic Kernel

from netzilo.semantic_kernel import govern, govern_tool
from semantic_kernel.functions import kernel_function

govern()

class OrdersPlugin:
    @kernel_function(description="Look up an order's status")
    @govern_tool
    def get_order_status(self, order_id: str) -> str:
        ...

smolagents

from netzilo.smolagents import govern, govern_tool
from smolagents import tool

govern()

@tool
@govern_tool
def get_order_status(order_id: str) -> str:
    """Look up an order's status.

    Args:
        order_id: The order to look up.
    """
    ...

Haystack

from netzilo.haystack import govern, govern_tool
from haystack.tools import create_tool_from_function

govern()

@govern_tool
def get_order_status(order_id: str) -> str:
    """Look up an order's status."""
    ...

tool = create_tool_from_function(get_order_status)

Vercel AI SDK

import { tool } from "ai";
import { z } from "zod";
import { wrapTool } from "netzilo/wrapTool";

const getOrderStatus = wrapTool(
  "get_order_status",
  async ({ orderId }: { orderId: string }) => fetchOrder(orderId)
);

const orderTool = tool({
  description: "Look up an order's status",
  parameters: z.object({ orderId: z.string() }),
  execute: getOrderStatus,
});

Mastra

import { createTool } from "@mastra/core/tools";
import { z } from "zod";
import { wrapTool } from "netzilo/wrapTool";

const getOrderStatus = wrapTool(
  "get_order_status",
  async ({ orderId }: { orderId: string }) => fetchOrder(orderId)
);

const orderTool = createTool({
  id: "get_order_status",
  description: "Look up an order's status",
  inputSchema: z.object({ orderId: z.string() }),
  execute: async ({ context }) => getOrderStatus(context),
});

Any other framework

Every Python/JS agent framework's "tool" is ultimately a plain function the model calls with arguments. If your framework isn't listed above, gate at that same boundary directly:

from netzilo.tools import govern, govern_tool

govern()

@govern_tool
def get_order_status(order_id: str) -> str:
    ...

# Register get_order_status with your framework's tool registry exactly as
# you would the original function.

A blocked call raises NetziloBlockedError (Python) / throws NetziloBlockedError (TypeScript) instead of invoking the wrapped function. A tool result that trips a redaction rule (e.g. an AWS key or PII pattern) is returned to the agent already sanitized.

Optional Python extras install a framework alongside netzilo, e.g. pip install netzilo[crewai], netzilo[llamaindex], netzilo[bedrock] — none are required, since every adapter imports its framework lazily.