pydantic_ai.direct
Methods for making imperative requests to language models with minimal abstraction.
These methods allow you to make requests to LLMs where the only abstraction is input and output schema translation so you can use all models with the same API.
These methods are thin wrappers around Model implementations.
Synchronous wrapper to async streaming responses by running the async producer in a background thread and providing a synchronous iterator.
This class must be used as a context manager with the with statement.
Get the current state of the response.
Type: messages.ModelResponse
Get the model name of the response.
Type: str
Get the timestamp of the response.
Type: datetime
def __iter__() -> Iterator[messages.ModelResponseStreamEvent]
Stream the response as an iterable of ModelResponseStreamEvents.
Iterator[messages.ModelResponseStreamEvent]
def get() -> messages.ModelResponse
Build a ModelResponse from the data received from the stream so far.
def usage() -> RequestUsage
Get the usage of the response so far.
@async
def model_request(
model: models.Model | models.KnownModelName | str,
messages: Sequence[messages.ModelMessage],
model_settings: settings.ModelSettings | None = None,
model_request_parameters: models.ModelRequestParameters | None = None,
instrument: instrumented_models.InstrumentationSettings | bool | None = None,
) -> messages.ModelResponse
Make a non-streamed request to a model.
from pydantic_ai import ModelRequest
from pydantic_ai.direct import model_request
async def main():
model_response = await model_request(
'anthropic:claude-haiku-4-5',
[ModelRequest.user_text_prompt('What is the capital of France?')] # (1)
)
print(model_response)
'''
ModelResponse(
parts=[TextPart(content='The capital of France is Paris.')],
usage=RequestUsage(input_tokens=56, output_tokens=7),
model_name='claude-haiku-4-5',
timestamp=datetime.datetime(...),
)
''' See ModelRequest.user_text_prompt for details.
messages.ModelResponse — The model response and token usage associated with the request.
model : models.Model | models.KnownModelName | str
The model to make a request to. We allow str here since the actual list of allowed models changes frequently.
messages : Sequence[messages.ModelMessage]
Messages to send to the model
model_settings : settings.ModelSettings | None Default: None
optional model settings
model_request_parameters : models.ModelRequestParameters | None Default: None
optional model request parameters
Whether to instrument the request with OpenTelemetry/Logfire, if None the value from
logfire.instrument_pydantic_ai is used.
def model_request_sync(
model: models.Model | models.KnownModelName | str,
messages: Sequence[messages.ModelMessage],
model_settings: settings.ModelSettings | None = None,
model_request_parameters: models.ModelRequestParameters | None = None,
instrument: instrumented_models.InstrumentationSettings | bool | None = None,
) -> messages.ModelResponse
Make a Synchronous, non-streamed request to a model.
This is a convenience method that wraps model_request with
loop.run_until_complete(...). You therefore can’t use this method inside async code or if there’s an active event loop.
from pydantic_ai import ModelRequest
from pydantic_ai.direct import model_request_sync
model_response = model_request_sync(
'anthropic:claude-haiku-4-5',
[ModelRequest.user_text_prompt('What is the capital of France?')] # (1)
)
print(model_response)
'''
ModelResponse(
parts=[TextPart(content='The capital of France is Paris.')],
usage=RequestUsage(input_tokens=56, output_tokens=7),
model_name='claude-haiku-4-5',
timestamp=datetime.datetime(...),
)
''' See ModelRequest.user_text_prompt for details.
messages.ModelResponse — The model response and token usage associated with the request.
model : models.Model | models.KnownModelName | str
The model to make a request to. We allow str here since the actual list of allowed models changes frequently.
messages : Sequence[messages.ModelMessage]
Messages to send to the model
model_settings : settings.ModelSettings | None Default: None
optional model settings
model_request_parameters : models.ModelRequestParameters | None Default: None
optional model request parameters
Whether to instrument the request with OpenTelemetry/Logfire, if None the value from
logfire.instrument_pydantic_ai is used.
def model_request_stream(
model: models.Model | models.KnownModelName | str,
messages: Sequence[messages.ModelMessage],
model_settings: settings.ModelSettings | None = None,
model_request_parameters: models.ModelRequestParameters | None = None,
instrument: instrumented_models.InstrumentationSettings | bool | None = None,
) -> AbstractAsyncContextManager[models.StreamedResponse]
Make a streamed async request to a model.
from pydantic_ai import ModelRequest
from pydantic_ai.direct import model_request_stream
async def main():
messages = [ModelRequest.user_text_prompt('Who was Albert Einstein?')] # (1)
async with model_request_stream('openai:gpt-5-mini', messages) as stream:
chunks = []
async for chunk in stream:
chunks.append(chunk)
print(chunks)
'''
[
PartStartEvent(index=0, part=TextPart(content='Albert Einstein was ')),
FinalResultEvent(tool_name=None, tool_call_id=None),
PartDeltaEvent(
index=0, delta=TextPartDelta(content_delta='a German-born theoretical ')
),
PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='physicist.')),
PartEndEvent(
index=0,
part=TextPart(
content='Albert Einstein was a German-born theoretical physicist.'
),
),
]
''' See ModelRequest.user_text_prompt for details.
AbstractAsyncContextManager[models.StreamedResponse] — A stream response async context manager.
model : models.Model | models.KnownModelName | str
The model to make a request to. We allow str here since the actual list of allowed models changes frequently.
messages : Sequence[messages.ModelMessage]
Messages to send to the model
model_settings : settings.ModelSettings | None Default: None
optional model settings
model_request_parameters : models.ModelRequestParameters | None Default: None
optional model request parameters
Whether to instrument the request with OpenTelemetry/Logfire, if None the value from
logfire.instrument_pydantic_ai is used.
def model_request_stream_sync(
model: models.Model | models.KnownModelName | str,
messages: Sequence[messages.ModelMessage],
model_settings: settings.ModelSettings | None = None,
model_request_parameters: models.ModelRequestParameters | None = None,
instrument: instrumented_models.InstrumentationSettings | bool | None = None,
) -> StreamedResponseSync
Make a streamed synchronous request to a model.
This is the synchronous version of model_request_stream.
It uses threading to run the asynchronous stream in the background while providing a synchronous iterator interface.
from pydantic_ai import ModelRequest
from pydantic_ai.direct import model_request_stream_sync
messages = [ModelRequest.user_text_prompt('Who was Albert Einstein?')]
with model_request_stream_sync('openai:gpt-5-mini', messages) as stream:
chunks = []
for chunk in stream:
chunks.append(chunk)
print(chunks)
'''
[
PartStartEvent(index=0, part=TextPart(content='Albert Einstein was ')),
FinalResultEvent(tool_name=None, tool_call_id=None),
PartDeltaEvent(
index=0, delta=TextPartDelta(content_delta='a German-born theoretical ')
),
PartDeltaEvent(index=0, delta=TextPartDelta(content_delta='physicist.')),
PartEndEvent(
index=0,
part=TextPart(
content='Albert Einstein was a German-born theoretical physicist.'
),
),
]
'''
StreamedResponseSync — A sync stream response context manager.
model : models.Model | models.KnownModelName | str
The model to make a request to. We allow str here since the actual list of allowed models changes frequently.
messages : Sequence[messages.ModelMessage]
Messages to send to the model
model_settings : settings.ModelSettings | None Default: None
optional model settings
model_request_parameters : models.ModelRequestParameters | None Default: None
optional model request parameters
Whether to instrument the request with OpenTelemetry/Logfire, if None the value from
logfire.instrument_pydantic_ai is used.