OpenAI Agents SDK adapter
For the OpenAI Agents SDK. Wraps three things:
- Tool execution — every tool call becomes a
FunctionToolwhoseon_invoke_toolruns through the Kite Logik policy gate - Handoffs —
register_handoff()produces a governedHandoffthat evaluates anagent.delegatepolicy event before transferring control - Agent-as-tool —
register_agent_as_tool()wrapsagent.as_tool()with the same delegation governance
This is the right adapter when you're using multi-agent orchestration (handoffs, sub-agents) — the others don't have a first-class delegation hook.
Install
pip install kitelogik openai-agentsopenai-agents is not a hard dependency — the import only runs when you call agent_tools(), register_handoff(), or register_agent_as_tool().
Setup
from kitelogik import OPAClient, PolicyGate, SessionContext
from kitelogik.adapters.openai_agents import OpenAIAgentsAdapter
gate = PolicyGate(opa_client=OPAClient())
context = SessionContext(
session_id="sess_001",
user_role="support_agent",
session_scopes=["read_customer", "approve_refund_under_100"],
)
adapter = OpenAIAgentsAdapter(gate=gate, context=context)Register tools
register(name, fn, description="", params=None, action=None). The params dict is the JSON-Schema properties block — Kite Logik wraps it as {"type": "object", "properties": params} for the SDK.
async def search_docs(query: str, limit: int = 10) -> str:
return f"Found {limit} results for {query}"
adapter.register(
"search_docs",
search_docs,
description="Search internal documentation.",
params={
"query": {"type": "string"},
"limit": {"type": "integer", "default": 10},
},
)Pass the governed tools to an Agent
from agents import Agent, Runner
agent = Agent(
name="support_agent",
instructions="Help customers with refunds and lookups.",
tools=adapter.agent_tools(), # ← governed FunctionTool list
)
result = await Runner.run(agent, "Refund $50 to cust_001")
print(result.final_output)Every tool invocation passes through the policy gate. Denied calls return a JSON string {"blocked": true, "reason": "..."} as the tool result — the agent loop continues, the model sees the denial.
strict_json_schema
The adapter sets strict_json_schema=False on the generated FunctionTool so ad-hoc params schemas don't get rejected for missing fields like additionalProperties: false. If you need strict mode, register the tool yourself with the SDK and use @governed on the underlying function.
Multi-agent governance — handoffs
Wrap any handoff with an agent.delegate policy check:
from agents import Agent
triage_agent = Agent(name="triage_agent", ...)
refund_agent = Agent(name="refund_agent", ...)
support_agent = Agent(name="support_agent", ...)
# Wrap the handoff so every delegation hits the policy gate
to_refund = adapter.register_handoff(
target_agent=refund_agent,
action="agent.delegate", # OPA action — defaults to this
on_handoff=lambda ctx: print("Handing off to refund"), # optional
)
triage_agent.handoffs = [to_refund, adapter.register_handoff(support_agent)]The handoff is evaluated as an agent.delegate event with delegation_target = "refund_agent". If the policy denies, the SDK raises and the handoff is rejected; the optional on_handoff callback only fires on allow.
Input-typed handoffs
Handoffs that take typed input (input_type=...) aren't supported through register_handoff(). Call agents.handoff() directly with a custom callback that invokes governed_handoff yourself.
Multi-agent governance — agent-as-tool
Sometimes you want a sub-agent exposed to the parent as a callable tool rather than a handoff. Wrap that with delegation governance too:
report_agent = Agent(name="report_agent", ...)
generate_report_tool = adapter.register_agent_as_tool(
agent=report_agent,
tool_name="generate_report",
tool_description="Produce a quarterly report from the data warehouse.",
action="agent.delegate",
)
main_agent = Agent(
name="main_agent",
tools=[*adapter.agent_tools(), generate_report_tool],
)Same agent.delegate evaluation as a handoff. Denied invocations return {"blocked": true, "reason": "..."} so the parent agent can recover.
Methods at a glance
| Method | Use |
|---|---|
register(name, fn, description="", params=None, action=None) | Register a tool. Chainable. |
agent_tools() | Returns governed FunctionTool list for Agent(tools=…). |
register_handoff(target_agent, action=…, on_handoff=…) | Build a governed Handoff for Agent(handoffs=…). |
register_agent_as_tool(agent, tool_name, tool_description, action=…) | Build a governed FunctionTool from agent.as_tool(). |
Source
kitelogik/adapters/openai_agents.py on GitHub.