nodestep.chat.integrations.openai ¶
The OpenAI chat integration: OpenAIChat for the OpenAI Chat Completions API and APIs compatible with it.
It has the Chat protocol, so it works wherever a chat model does; see
Agents and tools.
OpenAIChat is in the openai extra:
uv add "nodestep[openai] @ git+https://github.com/nodestep-ai/nodestep"
import nodestep works without the extra. OpenAIChat is exported lazily, and
using it without the extra raises IntegrationNotInstalledError, an ImportError
whose message shows the command above.
OpenAIChat.from_env(model=...) reads the variables below. Empty ones count as
unset, and keyword arguments override them.
| Variable | Setting | Default |
|---|---|---|
OPENAI_API_KEY |
api_key |
required |
OPENAI_BASE_URL |
base_url |
the OpenAI API |
OPENAI_ORG_ID |
organization |
not sent |
OPENAI_PROJECT_ID |
project |
not sent |
OPENAI_TIMEOUT |
timeout |
60 seconds |
OPENAI_MAX_RETRIES |
max_retries |
3 |
These are the variables in the repository's .env.example. The OpenAI SDK
handles the timeout and the retries; its own defaults are 600 seconds and 2
retries. Nothing loads a .env file, so pass it to the command:
cp .env.example .env
uv run --env-file .env python app.py
Without a key, from_env raises ModelProviderError:
from nodestep import ModelProviderError, OpenAIChat
try:
OpenAIChat.from_env(model="gpt-6-luna")
except ModelProviderError as error:
print(error)
OpenAIChat.from_env found no API key: OPENAI_API_KEY is not set or is empty; set it, or pass api_key=
In an agent, create the model where the graph is built, and keep ScriptedChat
in tests:
-chat = ScriptedChat([...])
+chat = OpenAIChat.from_env(model="gpt-6-luna")
chat.requests and chat.responses exist only on ScriptedChat, so drop the
lines that read them.
The OpenAI SDK reads some variables itself when it builds a client, with or
without from_env. nodestep does not patch the SDK.
- For a client you build,
OPENAI_API_KEY,OPENAI_BASE_URL,OPENAI_ORG_IDandOPENAI_PROJECT_IDwhen you do not pass them. OPENAI_CUSTOM_HEADERSsets headers sent with every request.OPENAI_LOGsets the SDK's logging.OPENAI_ADMIN_KEYandOPENAI_WEBHOOK_SECRETare read too.- httpx reads the proxy and CA certificate variables, such as
HTTPS_PROXYandSSL_CERT_FILE.
How requests, responses and errors are mapped:
- SDK errors are raised as
ModelProviderError, with the SDK's error as the cause. - Retries happen inside the SDK and are not nodestep events.
output_schema=uses OpenAI's strict mode, and the schema is rewritten for it. Every property becomes required, so the model writes fields that have a default too. Objects forbid extra properties,"default": nullentries are removed,$refentries with siblings are inlined, and the schema is sent under the namefinal_output.- A message without content is sent as an empty string.
- A response with several choices (
n> 1), or a tool call that is not a function call, raisesModelProviderError. ChatResponse.modelis the model name the API reported;ctx.modelin middleware is the model that was requested.
| Name | What it is |
|---|---|
| Chat model | |
OpenAIChat | Chat model for the OpenAI Chat Completions API, or a compatible one. |
| Settings | |
OpenAISettings | OpenAI connection settings read from OPENAI_* variables; empty ones count as unset. |
Chat model¶
OpenAIChat¶
OpenAIChat(model, *, api_key=None, base_url=None, organization=None, project=None, timeout=None, max_retries=None, client=None, stream_usage=True, **request_parameters)
Chat model for the OpenAI Chat Completions API, or a compatible one.
The constructor reads no environment variable; from_env does. The
OpenAI SDK reads some variables itself; the
module introduction lists them.
model is always required:
from nodestep import OpenAIChat
chat = OpenAIChat(
model="gpt-6-luna",
api_key="sk-your-key",
timeout=30,
max_retries=2,
temperature=0.2,
)
print(chat.model, chat.request_parameters)
gpt-6-luna {'temperature': 0.2}
- Extra keyword arguments, such as
temperature, are sent with every request. - Keys the request mapping sets itself (
messages,tools,tool_choice,response_format,stream,stream_options,model) raiseTypeError; usemodel_node(tool_choice=...)andoutput_schema=. stream_usage=True(the default) asks for token usage at the end of streamed responses.
Pass your own AsyncOpenAI client as client=. The connection
arguments (api_key, base_url, organization, project,
timeout, max_retries) then raise TypeError, so set them on the
client:
from openai import AsyncOpenAI
from nodestep import OpenAIChat
client = AsyncOpenAI(api_key="sk-your-key", base_url="http://localhost:8000/v1")
chat = OpenAIChat(model="gpt-6-luna", client=client)
print(chat.model)
gpt-6-luna
await chat.aclose(), or async with OpenAIChat(...) as chat:, closes
the HTTP client.
model | str |
Model name, e.g. |
api_key | str | None |
API key; required unless |
base_url | str | None |
Base URL of an OpenAI-compatible API; |
organization | str | None |
OpenAI organization id, sent only when given. |
project | str | None |
OpenAI project id, sent only when given. |
timeout | float | None |
HTTP timeout in seconds; |
max_retries | int | None |
Retries of transient HTTP errors, done by the SDK; |
client | AsyncOpenAI | None |
Client to use instead of the connection arguments. |
stream_usage | bool |
Ask for token usage at the end of streamed responses. |
**request_parameters | Any |
Sent with every request, such as |
IntegrationNotInstalledError |
If the |
ModelProviderError |
If |
TypeError |
If |
Methods
from_env(model, ...)¶
class method
Create a chat model whose connection comes from OPENAI_* variables.
from_env(model, ...)¶from_env(model, **kwargs) -> OpenAIChat
Reads the variables in the table of the module introduction; empty ones count as unset and keyword arguments win.
model | str |
Model name, e.g. |
**kwargs | Any |
Passed to |
TypeError |
If |
ModelProviderError |
If |
Examples
>>> chat = OpenAIChat.from_env(model="gpt-6-luna")
async aclose()¶
Close the underlying HTTP client.
async aclose()¶async aclose() -> None
async complete(request)¶
Send a request and wait for the full response.
async complete(request)¶async complete(request) -> ChatResponse
request | ChatRequest |
Messages, tools and an optional output schema. |
ModelProviderError |
If the OpenAI SDK reports an error. |
async stream(request)¶
Stream a response, with the token usage when stream_usage is set.
async stream(request)¶async stream(request) -> AsyncIterator[ChatStreamChunk]
request | ChatRequest |
Messages, tools and an optional output schema. |
ModelProviderError |
If the OpenAI SDK reports an error. |
Settings¶
OpenAISettings¶
OpenAI connection settings read from OPENAI_* variables; empty ones count as unset.
The table in the module introduction lists the variable and the default of each field.
api_key | str | None |
OpenAI API key. |
base_url | str | None |
Base URL for the OpenAI-compatible API; None means the OpenAI API. |
organization | str | None |
OpenAI organization ID. |
project | str | None |
OpenAI project ID. |
timeout | float |
HTTP request timeout in seconds. |
max_retries | int |
Maximum retry attempts for transient failures. |