OpenAI
Using OpenAI GPT and o-series models with Flux — setup, API keys, model strings, structured output, and the parameters that behave differently.
Flux talks to OpenAI through the openai Python SDK’s async client. The integration lives in flux/tasks/ai/openai.py and works against the Chat Completions API.
Install
The OpenAI SDK is an optional dependency. Install it directly:
pip install openai
Or take the full LLM bundle:
pip install flux-core[ai]
There is no per-provider extra in 0.56.0. The ai extra installs ollama, openai, anthropic, and google-genai together.
API key
The OpenAI SDK reads OPENAI_API_KEY from the environment by default. Flux constructs AsyncOpenAI() with no arguments, so the same lookup applies:
export OPENAI_API_KEY="sk-..."
The Flux integration does not currently wire up OPENAI_BASE_URL, organization IDs, or project IDs. If you need any of those, instantiate your own client in a custom provider module — see Adding a new provider.
Model string
Use the openai/ prefix:
from flux.tasks.ai import agent
assistant = await agent(
"You are a helpful assistant.",
model="openai/gpt-4o",
)
Anything after the slash is forwarded as the OpenAI model identifier. The integration is tested against gpt-4o, gpt-4o-mini, and the o-series (o3, o3-mini). Newer models work as long as they speak the Chat Completions wire format.
Streaming
Streaming is on by default. The OpenAI formatter uses client.chat.completions.create(stream=True) and yields tokens through Flux’s progress() task. Streaming is disabled automatically whenever response_format is set.
assistant = await agent(
"You are a helpful assistant.",
model="openai/gpt-4o",
stream=True,
)
max_tokens
The OpenAI formatter passes max_tokens through to the API. When set, build_messages() forwards it as max_completion_tokens — the unified token cap in the OpenAI v2 SDK, accepted by both reasoning and non-reasoning models:
researcher = await agent(
"Write concise summaries.",
model="openai/gpt-4o",
max_tokens=1024,
)
When max_tokens is left unset, output length falls back to the model’s default cap.
Reasoning effort
The OpenAI formatter passes reasoning_effort directly to the Chat Completions API. Valid values are "low", "medium", "high", or None (omitted from the call):
researcher = await agent(
"You are a careful researcher.",
model="openai/o3-mini",
reasoning_effort="high",
)
Only the o-series models accept reasoning_effort. On GPT-4 family models the parameter is rejected by the API. The Flux layer does no model-family check before forwarding, so it’s the caller’s responsibility to pair reasoning_effort only with reasoning-capable models.
The OpenAI formatter sets supports_reasoning_stream = True and surfaces reasoning_content deltas when the API returns them. See Reasoning models for the agent-loop details.
Structured output
OpenAI structured output uses the native response_format API parameter. The Flux formatter builds the request like this (openai.py::apply_structured_output):
call_kwargs["response_format"] = {
"type": "json_schema",
"json_schema": {
"name": self._response_format.__name__,
"schema": self._response_format.model_json_schema(),
},
}
This is API-enforced for the gpt-4o family and o-series. The model is guaranteed to return JSON matching the supplied schema or to refuse.
from pydantic import BaseModel
class Extraction(BaseModel):
name: str
age: int
extractor = await agent(
"Extract structured data from text.",
model="openai/gpt-4o",
response_format=Extraction,
)
result: Extraction = await extractor("Alice is 32 years old.")
The agent loop still calls response_format.model_validate_json() on the response, so you get Pydantic-level validation on top of the API-level enforcement.
Combining tools and structured output
response_format with tools works for OpenAI. The final, post-tool-loop answer is the JSON object. See Tools and structured output for the loop behavior.
What can go wrong
temperatureon o-series — o3 and o3-mini reject thetemperatureparameter at the API level. The Flux integration doesn’t exposetemperatureonagent()currently, so this is mostly an issue if you wrap the OpenAI provider yourself.- Tool calling on legacy models — older GPT-3.5 variants don’t support the structured tool-calling format Flux emits. Use
gpt-4o-minior newer for tool workloads. - Rate limits — 429s from OpenAI surface as
openai.RateLimitError. Wrap the agent task withtask.with_options(retry_max_attempts=5, retry_delay=2, retry_backoff=2)to back off automatically. response_formatvalidation — though OpenAI enforces the schema at the API level, Pydantic’s local validation still runs. A schema that disagrees with the runtime model (extra fields, type mismatch) raisesValidationErroron the way out.
See also
- Choosing a provider — capability matrix.
- Reasoning models —
reasoning_efforton o-series models. - Tools and structured output — combining
response_formatwith tools. - OpenAI API docs — model identifiers, rate limits, and pricing.