The OpenAI Agents SDK is OpenAI’s own Python framework for building agents: an Agent object combines a model, an optional set of tools, and instructions, and Runner.run() drives the conversation until the agent settles on a final answer. Left on its defaults, the SDK talks to OpenAI’s own Responses API using an OPENAI_API_KEY. Point it at NativePort’s unified inference endpoint instead, and the same Agent/Runner code runs on a NativePort key and balance, with local Python functions available to the agent as tools. This tutorial sets up that connection, builds a small tool-calling agent, and runs it end to end.
What you’ll need
- A NativePort API key. Sign up to get an API key and $5 in credits.
- Python 3.10 or later.
pip install openai-agents==0.19.1.
Export your key as an environment variable rather than writing it into a script:
export NATIVEPORT_API_KEY="<your NativePort API key>"
Point the SDK at NativePort
The Agents SDK defaults to OpenAI’s Responses API. NativePort’s inference endpoint speaks the Chat Completions contract instead, so the default path won’t get you a working response. The SDK’s own docs give the fix for exactly this situation: build a custom AsyncOpenAI client and hand it to OpenAIChatCompletionsModel explicitly, which forces every request through the Chat Completions shape this endpoint actually serves.
import asyncio
import os
from agents import Agent, AsyncOpenAI, OpenAIChatCompletionsModel, Runner, set_tracing_disabled
set_tracing_disabled(True)
client = AsyncOpenAI(
api_key=os.environ["NATIVEPORT_API_KEY"],
base_url="https://api.nativeport.ai/inference/v1",
)
model = OpenAIChatCompletionsModel(model="openai/gpt-5.4-mini", openai_client=client)
agent = Agent(
name="Assistant",
instructions="You are a helpful assistant.",
model=model,
)
async def main():
result = await Runner.run(agent, "Say hello in one word.")
print(result.final_output)
asyncio.run(main())
A few parts of this are worth knowing:
base_urlpoints athttps://api.nativeport.ai/inference/v1, NativePort’s unified inference path.AsyncOpenAIis the same client class the SDK would use against OpenAI directly, just pointed elsewhere.model="openai/gpt-5.4-mini"is NativePort’s canonical model id. Theopenai/prefix tells the unified endpoint which upstream provider to route the request to;OpenAIChatCompletionsModelforwards the string unchanged, so the prefix has to stay, not just the baregpt-5.4-mini.set_tracing_disabled(True)stops the SDK from attempting to send its own trace data to OpenAI when you’re authenticating with a non-OpenAI key, which is what a NativePort key is. Call it once, near the top of the script, before running any agent.
Build a tool-calling agent
An agent gets more useful once it can call something outside the model itself. function_tool turns a typed Python function into a tool the model can invoke by name, inferring its schema from the function’s signature and docstring:
import asyncio
import os
from agents import (
Agent,
AsyncOpenAI,
OpenAIChatCompletionsModel,
Runner,
function_tool,
set_tracing_disabled,
)
set_tracing_disabled(True)
client = AsyncOpenAI(
api_key=os.environ["NATIVEPORT_API_KEY"],
base_url="https://api.nativeport.ai/inference/v1",
)
model = OpenAIChatCompletionsModel(model="openai/gpt-5.4-mini", openai_client=client)
@function_tool
def multiply(a: int, b: int) -> int:
"""Multiply two integers and return the product."""
return a * b
agent = Agent(
name="Math agent",
instructions=(
"You answer arithmetic questions by calling the multiply tool. "
"Always call it instead of computing the answer yourself."
),
model=model,
tools=[multiply],
)
async def main():
result = await Runner.run(agent, "What is 6 times 7?")
print(result.final_output)
asyncio.run(main())
Running this prints 42. Underneath, Runner.run() sent the prompt to the model, got back a request to call multiply(6, 7), ran that function locally, sent the result back as a second turn, and returned the model’s reply once it had folded the tool’s answer in. To confirm the tool actually fired instead of the model guessing, look at result.new_items for a ToolCallItem alongside a matching ToolCallOutputItem.
Tool safety
multiply above is pure and harmless by design. A tool with real consequences needs more care:
- A tool’s arguments come from the model, not from a trusted caller. Validate them the same way you’d validate any input arriving from outside your own code before using them in a query, a file path, or a shell command.
- Anything a tool can do, the agent can trigger on its own, based on how it reads a prompt. Before adding a tool that writes data, spends money, or calls another service, decide whether that action needs a confirmation step outside the agent loop. Keep
NATIVEPORT_API_KEYout of tool code entirely; tools run in the same process as the client that already holds it.
This walkthrough covers a single local tool through the SDK’s default non-streaming Runner.run(). Streaming responses and other canonical models behind the unified endpoint aren’t demonstrated here.
Troubleshooting
- Authentication errors. A missing, malformed, or revoked
NATIVEPORT_API_KEYsurfaces as anAuthenticationErrorfrom the underlyingopenaiclient, with a 401 status. Confirm the key is exported in the same environment the script runs in. 402responses. The NativePort balance backing the key is at zero. Every request fails closed here instead of degrading in quality; top up and retry.- 404s or “model not found.” Two common causes: a
base_urlmissing the/inference/v1path, or amodelvalue missing itsopenai/prefix. BothAsyncOpenAIandOpenAIChatCompletionsModelforward what you pass them unchanged, so a typo reaches the gateway exactly as written rather than falling back to something that works. - A tracing-related error shows up even though the agent’s answer looks correct. Add
set_tracing_disabled(True)if it’s missing; without it, the SDK still attempts to send trace data to OpenAI using a key OpenAI doesn’t recognize. - The model never calls the tool, or the run stalls. Check that the instructions actually tell the agent to use the tool, and that every argument on the function has a type hint. An untyped parameter gives
function_toolless to build a schema from, and a vague instruction leaves the model free to guess an answer instead of calling out.
What this costs
openai/gpt-5.4-mini through this endpoint is metered at $0.75 per 1M input tokens and $4.50 per 1M output tokens, NativePort’s real, pass-through rate with no per-call markup. result.context_wrapper.usage carries the token counts for the run if you want to track spend against your own workload. See pricing for the full billing model.
Where to go next
- OpenAI provider page: scope and pricing range for the models behind this route, including the
/inference/v1contract this tutorial runs on. - Pricing: the full billing model.
- Weighing gateways before you commit? How NativePort stacks up against OpenRouter or against Eden AI.