OpenAI Agents SDK
The Agents SDK reads OPENAI_API_KEY and OPENAI_BASE_URL from the environment,
which makes both the zero-code shape and the proxy shape configuration-only. The
one thing to know about is the tracing exporter.
Start here if seekrit is new: three
commands put the keys in
an environment, mint a token bound to it, and export SEEKRIT_TOKEN. A token
reads everything in its
environment, so
there is no per-key or per-framework setup to do before any of the below.
1. Wrap the process
seekrit run -- python agent.py
from agents import Agent, Runner
agent = Agent(name="Assistant", instructions="You are a helpful assistant")
result = Runner.run_sync(agent, "Write a haiku about recursion.")
print(result.final_output)
No seekrit-specific code at all — the key arrives in the environment the SDK already reads.
2. Resolve in code
import seekrit
from agents import set_default_openai_key
set_default_openai_key(seekrit.Client().get("OPENAI_API_KEY"))
Set it before the first model call. For a fully custom client — a different
endpoint, an org header, a shared httpx client:
import seekrit
from openai import AsyncOpenAI
from agents import set_default_openai_client
secrets = seekrit.Client().resolve()
set_default_openai_client(AsyncOpenAI(api_key=secrets["OPENAI_API_KEY"]))
Pass either openai_client or api_key/base_url, never both — combining
them raises UserError rather than silently ignoring one.
3. Never hold the key
Environment only, no source change:
export OPENAI_BASE_URL=http://127.0.0.1:8080/openai/v1
export OPENAI_API_KEY='{{seekrit:OPENAI_API_KEY}}'
# seekrit-proxy.toml
listen = "127.0.0.1:8080"
[[route]]
prefix = "/openai"
upstream = "https://api.openai.com"
allow = ["OPENAI_API_KEY"]
methods = ["POST"]
paths = ["/v1/responses", "/v1/chat/completions"]
Without running the proxy
set_default_openai_client takes a client, and a client takes a transport:
import httpx
from openai import AsyncOpenAI
from agents import set_default_openai_client
from seekrit.transport import AsyncSeekritTransport
set_default_openai_client(
AsyncOpenAI(
api_key="{{seekrit:OPENAI_API_KEY}}",
http_client=httpx.AsyncClient(
transport=AsyncSeekritTransport(allow={"api.openai.com": ["OPENAI_API_KEY"]}),
),
)
)
Weaker than the proxy, since it runs in your process: in-process injection sets out the trade-off.
Gotchas
- Tracing uses the same credential, to a different path. The SDK exports
traces to OpenAI by default with your API key. Behind the proxy that means
trace uploads carry the placeholder too — so either allow the trace ingest
path in your route, give tracing its own credential with
set_tracing_export_api_key(...), or turn it off withset_tracing_disabled(True). If traces vanish the moment you add the proxy, this is why. OPENAI_WEBSOCKET_BASE_URLis separate. Realtime/websocket transport does not followOPENAI_BASE_URL. The proxy substitutes on HTTP requests, so websocket traffic needs its own decision — usually: don't put a placeholder in that path.- Handoffs share the process. Every agent in a handoff chain sees the same environment. Per-agent credential separation needs the proxy's session tickets, not a second env var.