OpenAI Agents SDK
The OpenAI Agents SDK (pip package openai-agents) gets a governed
OpenAIChatCompletionsModel backed by a pre-built AsyncOpenAI client. The
adapter builds that client itself, with the SDK’s shared HTTP client and proxy
headers, and hands it to the Agents SDK ready-made.
What you get
- A native
agents.OpenAIChatCompletionsModel. - Full header and transport injection — both travel together in one
AsyncOpenAIobject. - Supported at
connection_kwargs().
Install
pip install "donkey-kit[openai-agents]"Quickstart
Python
from donkey_kit.integrations.openai_agents import model
llm = model("gpt-4o")llm is a real agents.OpenAIChatCompletionsModel instance — pass it to
Agent(model=...) as you would any other Agents SDK model.
Three ways to construct
1. Off a shared Donkey instance:
from donkey_kit import Donkey
async with Donkey.from_env() as donkey:
llm = donkey.openai_agents.model("gpt-4o")2. Module-level factory (shortest):
from donkey_kit.integrations.openai_agents import model
llm = model("gpt-4o")3. Governed kwargs, native constructor:
from donkey_kit import Donkey
from agents import OpenAIChatCompletionsModel
async with Donkey.from_env() as donkey:
llm = OpenAIChatCompletionsModel(
model="gpt-4o",
**donkey.openai_agents.connection_kwargs(),
)Manual equivalent
from openai import AsyncOpenAI
from agents import OpenAIChatCompletionsModel
async_client = AsyncOpenAI(
base_url=..., # from DONKEY_LLM_PROXY_URL, no /v1 suffix
api_key=...,
default_headers=..., # client_id / client_secret header pair
http_client=..., # the SDK's shared httpx client
)
llm = OpenAIChatCompletionsModel(
model="gpt-4o",
openai_client=async_client,
)connection_kwargs() returns exactly one key, openai_client, holding this
pre-built AsyncOpenAI instance.
donkey.last_call
Every model call goes through the SDK’s shared HTTP client, so the SDK records
it. last_call is contextvar-scoped, though, and Runner sends a run’s first
turn from a task of its own (run_streamed sends every turn that way). After a
one-turn Runner.run, or any run_streamed, the caller reads UNOBSERVED.
After a longer Runner.run it reads the last turn’s call. To read every call,
use RunHooks.on_llm_end, which runs in the same task as the call:
from agents import Agent, RunHooks, Runner
class LastCallHooks(RunHooks):
async def on_llm_end(self, context, agent, response):
r = donkey.last_call
print(r.request_id, r.input_tokens, r.output_tokens)
agent = Agent(name="assistant", model=donkey.openai_agents.model("gpt-4o"))
await Runner.run(agent, "hello", hooks=LastCallHooks())Notes
- A pre-built client is the preferred integration point. When a framework
accepts a ready-made
AsyncOpenAIinstead of loose kwargs, the shared transport and every proxy header travel together as one object, with no risk of a kwarg being dropped. That’s why injection is full here even though the model object never seesbase_urlordefault_headersdirectly. openai-agentsis distinct from the plainopenaipackage:agents.OpenAIChatCompletionsModellives in the Agents SDK. Installingdonkey-kit[openai-agents]pulls it in for you. For the raw governed client with no framework, usedonkey.openai()(fromdonkey-kit[llm]) instead.
See the error taxonomy for how proxy rejections surface as typed exceptions, and the verification ledger for the current status of every constructor signature this adapter depends on.