Framework Integration Guides

PhronEdge works with any Python agent framework. Same SDK. Same gateway. Same audit chain. Same 50ms overhead.

LangChain / LangGraph

Python
from phronedge import PhronEdge
from langchain.tools import tool
from langchain.agents import create_react_agent

pe = PhronEdge()

@tool
@pe.govern("search_knowledge_base")
def search_knowledge_base(query: str) -> str:
    """Search internal knowledge base for company policies."""
    return vector_store.similarity_search(query, k=5)

@tool
@pe.govern("lookup_employee")
def lookup_employee(employee_id: str) -> str:
    """Look up employee details from HR system."""
    return hr_system.get_employee(employee_id)

# Both tools are governed. The agent can use them normally.
# PhronEdge intercepts every call transparently.
agent = create_react_agent(
    llm=ChatOpenAI(model="gpt-4o"),
    tools=[search_knowledge_base, lookup_employee],
)

result = agent.invoke({"input": "Find the vacation policy for employee E-1234"})

LangGraph multi-agent

Python
from langgraph.graph import StateGraph, END
from phronedge import PhronEdge

pe = PhronEdge()

@pe.govern("research_topic")
def research_topic(query: str) -> str:
    return researcher_llm.invoke(query)

@pe.govern("write_report")
def write_report(research: str) -> str:
    return writer_llm.invoke(f"Write a report based on: {research}")

@pe.govern("review_compliance")
def review_compliance(report: str) -> str:
    return compliance_llm.invoke(f"Review for regulatory compliance: {report}")

# Each node in the graph is independently governed.
# The compliance reviewer has higher clearance than the researcher.
graph = StateGraph(AgentState)
graph.add_node("research", research_topic)
graph.add_node("write", write_report)
graph.add_node("review", review_compliance)
graph.add_edge("research", "write")
graph.add_edge("write", "review")
graph.add_edge("review", END)

CrewAI

Python
from phronedge import PhronEdge
from crewai import Agent, Task, Crew
from crewai.tools import tool

pe = PhronEdge()

@tool("search_financial_records")
@pe.govern("search_financial_records")
def search_financial_records(query: str) -> str:
    """Search financial records for audit evidence."""
    return finance_db.search(query)

@tool("generate_audit_finding")
@pe.govern("generate_audit_finding")
def generate_audit_finding(evidence: str) -> str:
    """Generate a formal audit finding from evidence."""
    return audit_engine.create_finding(evidence)

analyst = Agent(
    role="Financial Analyst",
    goal="Investigate financial anomalies",
    tools=[search_financial_records],
)

auditor = Agent(
    role="Internal Auditor",
    goal="Document audit findings",
    tools=[generate_audit_finding],
)

crew = Crew(
    agents=[analyst, auditor],
    tasks=[
        Task(description="Find Q4 anomalies", agent=analyst),
        Task(description="Document findings", agent=auditor),
    ],
)

# Both agents governed independently.
# Analyst has PII_FINANCIAL clearance.
# Auditor has CONF clearance only.
result = crew.kickoff()

Google ADK

Python
from phronedge import PhronEdge
from google.adk import Agent, Runner
from google.adk.sessions import InMemorySessionService

pe = PhronEdge()

@pe.govern("lookup_claim")
def lookup_claim(claim_id: str) -> dict:
    """Look up an insurance claim by ID."""
    return claims_db.get(claim_id)

@pe.govern("approve_claim")
def approve_claim(claim_id: str, amount: float) -> dict:
    """Approve a claim for payout."""
    return payments.approve(claim_id, amount)

agent = Agent(
    name="claims-processor",
    model="gemini-2.0-flash",
    instruction="Process insurance claims. Look up claims and approve valid ones.",
    tools=[lookup_claim, approve_claim],
)

runner = Runner(agent=agent, app_name="claims", session_service=InMemorySessionService())
result = await runner.run(user_id="adjuster-1", new_message="Process claim CLM-7891")

OpenAI Agents SDK

Python
from phronedge import PhronEdge
from openai import OpenAI

pe = PhronEdge()
client = OpenAI()

@pe.govern("get_patient_labs")
def get_patient_labs(patient_id: str) -> str:
    """Retrieve lab results for a patient."""
    return lab_system.get_results(patient_id)

@pe.govern("schedule_followup")
def schedule_followup(patient_id: str, reason: str) -> str:
    """Schedule a follow-up appointment."""
    return scheduling.create_appointment(patient_id, reason)

tools = [
    {"type": "function", "function": {"name": "get_patient_labs", "parameters": {...}}},
    {"type": "function", "function": {"name": "schedule_followup", "parameters": {...}}},
]

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Check labs for patient P-456 and schedule followup if needed"}],
    tools=tools,
)

# When OpenAI calls get_patient_labs, PhronEdge validates:
#   - Agent has PII_HEALTH clearance
#   - Tool is in permitted_tools
#   - Jurisdiction allows health data access
# All before the function body executes.

Pydantic AI

Python
from phronedge import PhronEdge
from pydantic_ai import Agent

pe = PhronEdge()

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

@agent.tool
@pe.govern("query_database")
def query_database(ctx, sql: str) -> str:
    """Execute a read-only SQL query."""
    return db.execute_readonly(sql)

@agent.tool
@pe.govern("send_notification")
def send_notification(ctx, recipient: str, message: str) -> str:
    """Send a notification to a team member."""
    return notifications.send(recipient, message)

result = agent.run_sync("How many open tickets do we have this week?")

AutoGen

Python
from phronedge import PhronEdge
from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager

pe = PhronEdge()

@pe.govern("execute_trade")
def execute_trade(ticker: str, quantity: int, side: str) -> str:
    """Execute a stock trade."""
    return trading_api.execute(ticker, quantity, side)

@pe.govern("check_compliance")
def check_compliance(trade: dict) -> str:
    """Check if a trade meets regulatory requirements."""
    return compliance_engine.validate(trade)

trader = AssistantAgent(
    name="trader",
    system_message="You execute trades.",
    llm_config={"functions": [{"name": "execute_trade", ...}]},
)

compliance_officer = AssistantAgent(
    name="compliance_officer",
    system_message="You validate trades against regulations.",
    llm_config={"functions": [{"name": "check_compliance", ...}]},
)

# Multi-agent group chat. Both agents governed independently.
# Trader has PII_FINANCIAL clearance.
# Compliance officer has CONF clearance.
# Trader cannot call check_compliance. Compliance cannot call execute_trade.
group = GroupChat(agents=[trader, compliance_officer], messages=[])
manager = GroupChatManager(groupchat=group)

LlamaIndex

Python
from phronedge import PhronEdge
from llama_index.core.tools import FunctionTool
from llama_index.core.agent import ReActAgent

pe = PhronEdge()

@pe.govern("search_contracts")
def search_contracts(query: str) -> str:
    """Search the contract repository."""
    return contract_index.query(query)

@pe.govern("extract_obligations")
def extract_obligations(contract_id: str) -> str:
    """Extract legal obligations from a contract."""
    return obligation_extractor.run(contract_id)

agent = ReActAgent.from_tools(
    tools=[
        FunctionTool.from_defaults(fn=search_contracts),
        FunctionTool.from_defaults(fn=extract_obligations),
    ],
    llm=OpenAI(model="gpt-4o"),
)

response = agent.chat("What are our obligations under contract CTR-2025-001?")

Smolagents

Python
from phronedge import PhronEdge
from smolagents import CodeAgent, HfApiModel, tool

pe = PhronEdge()

@tool
@pe.govern("web_search")
def web_search(query: str) -> str:
    """Search the web for current information."""
    return search_api.search(query)

@tool
@pe.govern("read_document")
def read_document(url: str) -> str:
    """Read and extract text from a document URL."""
    return document_reader.extract(url)

agent = CodeAgent(
    tools=[web_search, read_document],
    model=HfApiModel("Qwen/Qwen2.5-72B-Instruct"),
)

result = agent.run("Find the latest EU AI Act amendments and summarize them")

Decorator order

The decorator order matters. PhronEdge should be the inner decorator (closest to the function). The framework decorator goes on the outside:

Python
# Correct: framework outside, PhronEdge inside
@tool
@pe.govern("my_tool")
def my_tool(params):
    ...

# Wrong: PhronEdge outside
@pe.govern("my_tool")
@tool
def my_tool(params):
    ...

PhronEdge intercepts at the function execution boundary. The framework sees a normal function. The governance is invisible to the agent.

What gets governed

ComponentGovernedHow
Tool callsYes@pe.govern wraps the function
Model callsYesModel validated against permitted_models
Agent delegationYescan_delegate_to checked on every delegation
Data accessYesdata_classifications checked on every call
OutputYesResponse scanned before return
PromptNoPhronEdge governs actions, not thoughts

Next steps

Previous
SDK Reference
Next
Multi-Agent