OpenAIModel
The built-in provider adapter, its retry policy, and the Model protocol for custom adapters.
OpenAIModel is an adapter for any OpenAI-compatible chat-completions endpoint. It is the only place in agentling that knows OpenAI's wire format: it converts framework-neutral ChatMessage lists into provider payloads on the way out and converts responses back on the way in.
OpenAIModel(...)#
from agentling import OpenAIModel
model = OpenAIModel(
"llama-3.1-70b",
base_url="http://localhost:8000/v1",
api_key="not-needed-locally",
)| Parameter | Default | Description |
|---|---|---|
model |
required | The model name to request. |
api_key |
env | Falls back to the OpenAI SDK's environment configuration, typically OPENAI_API_KEY. |
base_url |
None |
Point at any OpenAI-compatible endpoint. |
context_window |
128_000 |
Advertised context window for this model. |
max_retries |
2 |
Retries after the initial request for transient errors. |
retry_base_delay |
0.5 |
Initial backoff delay in seconds. It doubles on each retry. |
Retry policy#
The adapter classifies failures before deciding whether to retry:
- Transient failures are retried with exponential backoff: rate limits, connection errors, timeouts, and 5xx responses. With the defaults, a request is attempted up to three times in total, waiting 0.5 seconds and then 1 second between attempts.
- Permanent errors fail fast without retrying: a bad request or bad auth returns immediately, because retrying them cannot succeed.
See Errors for how model failures surface to your code.
Compatible endpoints#
Because the adapter speaks the OpenAI chat-completions protocol, base_url lets you use a local server, a gateway, or another vendor's compatible API without touching the rest of your agent. See Using other providers for worked examples.
The Model protocol#
Any object implementing the Model protocol works as an agent's model, so you can write your own adapter for a provider with a different wire format:
class Model(Protocol):
async def generate(self, messages, tools=None) -> ChatMessage: ...
def stream(self, messages, tools=None) -> AsyncIterator[Delta]: ...generate returns one complete ChatMessage. stream yields Delta objects: small chunks of content or fragments of a tool call. The module-level agglomerate_deltas function reassembles a delta stream back into a single ChatMessage, which is how the loop can stream text to the user and still execute tools from a complete message. Swapping providers means writing one adapter, not touching the loop.
Related pages#
- The agent loop shows where the model is called on each step.
- Streaming events covers what the loop does with each
Delta.