pydantic_ai.conversation
The state a conversation carries from one run to the next.
Everything a conversation carries from one run to the next, in one object.
This is the unit to continue and to store a conversation by. A run’s
AgentRunResult.conversation (or a realtime
session’s conversation) produces one, and
every entry point that starts a run takes it back as conversation=. See
Carrying a conversation whole.
Passing message_history= instead still works, but carries only the messages. What it drops is
what a conversation reassembled by hand loses: the running
usage, without which every turn’s
UsageLimits budget starts over from zero; the
conversation_id that correlates its
runs; and the deferred_tool_requests
a paused run is waiting on, which can’t be recovered from the messages.
It serializes like any Pydantic value — as a field on a model of your own, or with
ConversationTypeAdapter — with the same
fidelity as ModelMessagesTypeAdapter. See
Persistence.
The conversation so far, in the form message_history= takes.
Type: Annotated[list[_messages.ModelMessage], pydantic.PlainSerializer(_dump_messages_json, when_used=json)] Default: dataclasses.field(default_factory=(list[_messages.ModelMessage]))
Usage accumulated across every run in this conversation.
Only some of this can be recovered from messages after the fact: the token counts and
requests are recorded on each ModelResponse, but
tool_calls is not, and a history that has since been
trimmed no longer accounts for what the dropped turns cost. Carrying it keeps a conversation’s
spend true to what was actually spent.
Type: _usage.RunUsage Default: dataclasses.field(default_factory=(_usage.RunUsage))
The identifier every run in this conversation shares, and the key to store it under.
Type: str Default: dataclasses.field(default_factory=(lambda: str(uuid7())))
The tool calls the conversation is waiting on, if its last run paused for them.
Set when a run ends with DeferredToolRequests as its
output: calls that need approval or
external execution. The messages show which calls
are unanswered, but not which kind of answer each needs or the metadata it was deferred with, so
the requests travel with the conversation rather than being rebuilt from it.
Answer them with build_results and
pass the results to the next run as deferred_tool_results= alongside the conversation; see
Pausing a conversation for deferred tools.
Type: DeferredToolRequests | None Default: None
Pydantic TypeAdapter for (de)serializing a Conversation.
The counterpart of ModelMessagesTypeAdapter for the
whole conversation rather than its messages alone.
Type: pydantic.TypeAdapter[Conversation] Default: pydantic.TypeAdapter(Conversation)