Skip to main content

OpenAI Python SDK

The OpenAI Python SDK takes a base_url on the client constructor, so pointing it at an LLM Registry entry needs no wrapper. It can also send custom headers, which is how the Agent Access Key travels when an entry requires one.

note

base_url must end in /v1, on both routes below. The SDK appends only the operation path, so the version segment has to come from the base URL. This applies to every OpenAI-compatible provider (OpenAI, OpenRouter, Kimi, Groq, Mistral). Gemini is the exception and takes no /v1; for Gemini agents see the Google ADK guide.

Which setup do you need?

What you getUse it when
LLM Registry entryThe model, governedYou only need model access
Agent PersonaThe model and the persona's MCP tools, in the same requestYou want the model to call tools as well

Which credentials you send depends on the entry's credential mode. If you haven't read which credentials your entry needs, start there.

Connect to an LLM Registry entry

Pick the credential mode on the entry's Provider Credential panel. All three are verified working against an OpenAI entry.

The gateway stores the OpenAI credential, so no OpenAI key leaves your machine. api_key carries your Agent Access Key instead.

from openai import OpenAI

client = OpenAI(
base_url="https://<gateway-host>/llm/<url-prefix>/v1",
api_key="<your-agent-access-key>"
)

response = client.chat.completions.create(
model="<model-id>",
messages=[{"role": "user", "content": "Hello"}]
)

print(response)

The SDK sends api_key as Authorization: Bearer, which the gateway accepts as your credential on this mode. It then attaches the stored OpenAI credential on the outbound side.

Connect through an Agent Persona

The SDK reaches a persona differently from a terminal client. Rather than registering an MCP server locally, it declares the persona's tools socket as a tool in the request, and OpenAI connects to that socket so the model can call the persona's tools within the same request.

Three things change from the setups above:

  • base_url becomes the persona-scoped route, ending in /v1 as before.
  • The call moves from client.chat.completions.create to client.responses.create. Remote MCP tools are a Responses API feature, so chat.completions will not accept them. Note the Responses API takes input rather than messages.
  • A tool entry of type: "mcp" points at https://<gateway-host>/p/<persona-id>.

One Agent Access Key covers both. It authenticates the model route and, in the tool's headers, the tools socket.

note

Because OpenAI's servers open the connection to the tools socket, the persona endpoint has to be reachable from the public internet. This differs from Codex CLI or Gemini CLI, where your own machine connects to it.

note

Two separate settings are in play here, and only one of them changes the code below.

  • The entry's credential mode — API Key or Passthrough — decides which credentials you send. This is what the tabs below switch between, exactly as on the route above.
  • The persona's own Inbound Authentication method — Interactive or Passthrough — decides how the persona identifies you. Either way an Agent Access Key is issued, and neither changes the configuration below.

Because a persona always identifies you by an Agent Access Key, the entry's third mode — Passthrough (No Agent Access Key) — has no tab here. It applies to the LLM Registry entry route only.

from openai import OpenAI

client = OpenAI(
base_url="https://<gateway-host>/p/<persona-id>/llm/<registry-entry-id>/v1",
api_key="<your-agent-access-key>"
)

response = client.responses.create(
model="<model-id>",
input="Hello",
tools=[{
"type": "mcp",
"server_label": "<persona-name>",
"server_url": "https://<gateway-host>/p/<persona-id>",
"headers": {"X-Agent-Key": "<your-agent-access-key>"},
"require_approval": "never",
}],
)

print(response)

What the tool fields do:

  • server_url is the persona root. It takes no /llm/... path and no /v1 suffix, unlike base_url. The model route and the tools socket are different endpoints on the same persona.
  • server_label is any short label you want to give the tools socket.
  • headers carries the Agent Access Key on X-Agent-Key, which OpenAI presents when it connects to the socket.
  • require_approval: "never" lets the model call the persona's tools without pausing for per-call confirmation. Leave it out if you'd rather approve each call.

Troubleshooting

The model answers but never calls a tool

Check the server_url. It is the persona root, /p/<persona-id>, with neither the /llm/... path nor the /v1 suffix that base_url needs.

tools is rejected as an unknown parameter

You're on client.chat.completions.create. Remote MCP tools require client.responses.create.

A not-found error rather than an authentication one

Check that base_url ends in /v1. A missing version segment looks like a routing failure, not a credential problem.

Where to find each value

PlaceholderWhere to find it
<gateway-host>Host from the entry's Overview tab, for example gw.aigateway.example.com
<url-prefix>The URL prefix field on the entry's Overview tab
<persona-id>The persona's ID on the Agent Persona page
<persona-name>Any short label you want to give the tools socket in your code
<registry-entry-id>The LLM Registry entry's ID in the entry's URL
<model-id>A model identifier from the entry's Allowed Models list, for example gpt-5-nano
<your-agent-access-key>Generate from the entry's Agent Access Keys step, or the persona's Connect flow. Plaintext is shown once.
<your-openai-api-key>Your own OpenAI API key, needed only in the passthrough modes

Tips

  • Keep credentials out of your source. The snippets inline the values so the shape is clear, but read them from environment variables or a secret store in anything you commit.
  • Two URLs, two shapes. base_url is persona-scoped and ends in /v1; server_url is the bare persona root. Copying one into the other is the most common setup mistake here.
  • Anthropic entries need the Anthropic SDK. This guide is verified against an OpenAI entry. Pointing the OpenAI SDK at an Anthropic-provider entry is not a supported path today, so use the Anthropic Python SDK for those.
  • Working in a different SDK? There are sibling guides for the Anthropic Python SDK and Google ADK.