Use promo code BETATEST1 for full access
seekrit
← all posts

Managing secrets in the OpenAI Agents SDK

Frameworks

The OpenAI Agents SDK reads OPENAI_API_KEY and OPENAI_BASE_URL from the environment. Both the zero-code setup and the proxy setup are configuration only. For local development:

seekrit secrets import .env --app agent --env development && rm .env
seekrit run -- python agent.py

The one thing specific to this SDK is the tracing exporter. It uses the same API key as the model, to a different path. Skip that section and traces stop the day you add a proxy.

Setup 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 code. The key arrives in the environment the SDK already reads. Delete the .env afterwards. A file that still exists is a file an agent can still read.

Setup 2: resolve in code

import seekrit
from agents import set_default_openai_key

set_default_openai_key(seekrit.Client().get("OPENAI_API_KEY"))

Call it before the first model call. For a custom client, with a different endpoint, an org header, or 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. Passing both raises UserError.

Setup 3: the process never holds 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}}'

The SDK sends the placeholder. The seekrit proxy swaps it for the real key against a default-deny rule list:

# 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"]

Nothing in the agent's process, prompt, or tool output contains the key. A prompt injection that asks the agent to print its environment gets the placeholder.

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"]}),
        ),
    )
)

This runs in your process, so it is a weaker boundary than the proxy. The in-process injection page sets out the trade-off.

Why did tracing stop when I added the proxy?

The SDK exports traces to OpenAI by default, with your API key. Behind the proxy the trace upload carries the placeholder too, to a path the route above does not allow, so the proxy denies it. Pick one:

  • Allow the trace ingest path in the route.
  • Give tracing its own credential with set_tracing_export_api_key(...).
  • Turn it off with set_tracing_disabled(True).

Two related notes. OPENAI_WEBSOCKET_BASE_URL does not follow OPENAI_BASE_URL, and the proxy substitutes on HTTP requests, so do not put a placeholder in the realtime path. And 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 variable.

Which setup for which credential

CredentialSetup
Model key, local development1
Model key, your own deployment2, or 3 if the agent runs generated code
A tool credential (Stripe, GitHub, a database)3 with methods and paths set
Agents in a handoff chain with different reach3 with session tickets

Setup

Three commands put the keys in an environment, mint a token bound to it, and export SEEKRIT_TOKEN. The frameworks guide has them. Values are encrypted before they are stored, so the service holding them cannot read them. The full page is at /docs/guides/frameworks/openai-agents.