Skip to content

pydantic_ai.messages

Message module-attribute

Any message send to or returned by a model.

SystemPrompt dataclass

A system prompt, generally written by the application developer.

This gives the model context and guidance on how to respond.

Source code in pydantic_ai_slim/pydantic_ai/messages.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@dataclass
class SystemPrompt:
    """A system prompt, generally written by the application developer.

    This gives the model context and guidance on how to respond.
    """

    content: str
    """The content of the prompt."""

    role: Literal['user'] = 'user'
    """Message source identifier, this type is available on all messages as either 'user' or 'model'."""

    message_kind: Literal['system-prompt'] = 'system-prompt'
    """Message type identifier, this type is available on all messages as a discriminator."""

content instance-attribute

content: str

The content of the prompt.

role class-attribute instance-attribute

role: Literal['user'] = 'user'

Message source identifier, this type is available on all messages as either 'user' or 'model'.

message_kind class-attribute instance-attribute

message_kind: Literal['system-prompt'] = 'system-prompt'

Message type identifier, this type is available on all messages as a discriminator.

UserPrompt dataclass

A user prompt, generally written by the end user.

Content comes from the user_prompt parameter of Agent.run, Agent.run_sync, and Agent.run_stream.

Source code in pydantic_ai_slim/pydantic_ai/messages.py
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@dataclass
class UserPrompt:
    """A user prompt, generally written by the end user.

    Content comes from the `user_prompt` parameter of [`Agent.run`][pydantic_ai.Agent.run],
    [`Agent.run_sync`][pydantic_ai.Agent.run_sync], and [`Agent.run_stream`][pydantic_ai.Agent.run_stream].
    """

    content: str
    """The content of the prompt."""

    timestamp: datetime = field(default_factory=_now_utc)
    """The timestamp of the prompt."""

    role: Literal['user'] = 'user'
    """Message source identifier, this type is available on all messages as either 'user' or 'model'."""

    message_kind: Literal['user-prompt'] = 'user-prompt'
    """Message type identifier, this type is available on all messages as a discriminator."""

content instance-attribute

content: str

The content of the prompt.

timestamp class-attribute instance-attribute

timestamp: datetime = field(default_factory=now_utc)

The timestamp of the prompt.

role class-attribute instance-attribute

role: Literal['user'] = 'user'

Message source identifier, this type is available on all messages as either 'user' or 'model'.

message_kind class-attribute instance-attribute

message_kind: Literal['user-prompt'] = 'user-prompt'

Message type identifier, this type is available on all messages as a discriminator.

ToolReturn dataclass

A tool return message, this encodes the result of running a tool.

Source code in pydantic_ai_slim/pydantic_ai/messages.py
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
@dataclass
class ToolReturn:
    """A tool return message, this encodes the result of running a tool."""

    tool_name: str
    """The name of the "tool" was called."""

    content: Any
    """The return value."""

    tool_call_id: str | None = None
    """Optional tool call identifier, this is used by some models including OpenAI."""

    timestamp: datetime = field(default_factory=_now_utc)
    """The timestamp, when the tool returned."""

    role: Literal['user'] = 'user'
    """Message source identifier, this type is available on all messages as either 'user' or 'model'."""

    message_kind: Literal['tool-return'] = 'tool-return'
    """Message type identifier, this type is available on all messages as a discriminator."""

    def model_response_str(self) -> str:
        if isinstance(self.content, str):
            return self.content
        else:
            return tool_return_ta.dump_json(self.content).decode()

    def model_response_object(self) -> dict[str, Any]:
        # gemini supports JSON dict return values, but no other JSON types, hence we wrap anything else in a dict
        if isinstance(self.content, dict):
            return tool_return_ta.dump_python(self.content, mode='json')  # pyright: ignore[reportUnknownMemberType]
        else:
            return {'return_value': tool_return_ta.dump_python(self.content, mode='json')}

tool_name instance-attribute

tool_name: str

The name of the "tool" was called.

content instance-attribute

content: Any

The return value.

tool_call_id class-attribute instance-attribute

tool_call_id: str | None = None

Optional tool call identifier, this is used by some models including OpenAI.

timestamp class-attribute instance-attribute

timestamp: datetime = field(default_factory=now_utc)

The timestamp, when the tool returned.

role class-attribute instance-attribute

role: Literal['user'] = 'user'

Message source identifier, this type is available on all messages as either 'user' or 'model'.

message_kind class-attribute instance-attribute

message_kind: Literal['tool-return'] = 'tool-return'

Message type identifier, this type is available on all messages as a discriminator.

RetryPrompt dataclass

A message back to a model asking it to try again.

This can be sent for a number of reasons:

  • Pydantic validation of tool arguments failed, here content is derived from a Pydantic ValidationError
  • a tool raised a ModelRetry exception
  • no tool was found for the tool name
  • the model returned plain text when a structured response was expected
  • Pydantic validation of a structured response failed, here content is derived from a Pydantic ValidationError
  • a result validator raised a ModelRetry exception
Source code in pydantic_ai_slim/pydantic_ai/messages.py
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
@dataclass
class RetryPrompt:
    """A message back to a model asking it to try again.

    This can be sent for a number of reasons:

    * Pydantic validation of tool arguments failed, here content is derived from a Pydantic
      [`ValidationError`][pydantic_core.ValidationError]
    * a tool raised a [`ModelRetry`][pydantic_ai.exceptions.ModelRetry] exception
    * no tool was found for the tool name
    * the model returned plain text when a structured response was expected
    * Pydantic validation of a structured response failed, here content is derived from a Pydantic
      [`ValidationError`][pydantic_core.ValidationError]
    * a result validator raised a [`ModelRetry`][pydantic_ai.exceptions.ModelRetry] exception
    """

    content: list[pydantic_core.ErrorDetails] | str
    """Details of why and how the model should retry.

    If the retry was triggered by a [`ValidationError`][pydantic_core.ValidationError], this will be a list of
    error details.
    """

    tool_name: str | None = None
    """The name of the tool that was called, if any."""

    tool_call_id: str | None = None
    """Optional tool call identifier, this is used by some models including OpenAI."""

    timestamp: datetime = field(default_factory=_now_utc)
    """The timestamp, when the retry was triggered."""

    role: Literal['user'] = 'user'
    """Message source identifier, this type is available on all messages as either 'user' or 'model'."""

    message_kind: Literal['retry-prompt'] = 'retry-prompt'
    """Message type identifier, this type is available on all messages as a discriminator."""

    def model_response(self) -> str:
        if isinstance(self.content, str):
            description = self.content
        else:
            json_errors = ErrorDetailsTa.dump_json(self.content, exclude={'__all__': {'ctx'}}, indent=2)
            description = f'{len(self.content)} validation errors: {json_errors.decode()}'
        return f'{description}\n\nFix the errors and try again.'

content instance-attribute

content: list[ErrorDetails] | str

Details of why and how the model should retry.

If the retry was triggered by a ValidationError, this will be a list of error details.

tool_name class-attribute instance-attribute

tool_name: str | None = None

The name of the tool that was called, if any.

tool_call_id class-attribute instance-attribute

tool_call_id: str | None = None

Optional tool call identifier, this is used by some models including OpenAI.

timestamp class-attribute instance-attribute

timestamp: datetime = field(default_factory=now_utc)

The timestamp, when the retry was triggered.

role class-attribute instance-attribute

role: Literal['user'] = 'user'

Message source identifier, this type is available on all messages as either 'user' or 'model'.

message_kind class-attribute instance-attribute

message_kind: Literal['retry-prompt'] = 'retry-prompt'

Message type identifier, this type is available on all messages as a discriminator.

ModelResponse dataclass

A response from a model.

Source code in pydantic_ai_slim/pydantic_ai/messages.py
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
@dataclass
class ModelResponse:
    """A response from a model."""

    parts: list[ModelResponsePart]
    """The parts of the response."""

    timestamp: datetime = field(default_factory=_now_utc)
    """The timestamp of the response.

    If the model provides a timestamp in the response (as OpenAI does) that will be used.
    """

    role: Literal['model'] = 'model'
    """Message source identifier, this type is available on all messages as either 'user' or 'model'."""

    message_kind: Literal['model-response'] = 'model-response'
    """Message source identifier, this type is available on all messages as a discriminator."""

    @classmethod
    def from_text(cls, content: str, timestamp: datetime | None = None) -> ModelResponse:
        return cls([TextPart(content)], timestamp=timestamp or _now_utc())

    @classmethod
    def from_tool_call(cls, tool_call: ToolCallPart) -> ModelResponse:
        return cls([tool_call])

parts instance-attribute

parts: list[ModelResponsePart]

The parts of the response.

timestamp class-attribute instance-attribute

timestamp: datetime = field(default_factory=now_utc)

The timestamp of the response.

If the model provides a timestamp in the response (as OpenAI does) that will be used.

role class-attribute instance-attribute

role: Literal['model'] = 'model'

Message source identifier, this type is available on all messages as either 'user' or 'model'.

message_kind class-attribute instance-attribute

message_kind: Literal['model-response'] = 'model-response'

Message source identifier, this type is available on all messages as a discriminator.

ArgsJson dataclass

Tool arguments as a JSON string.

Source code in pydantic_ai_slim/pydantic_ai/messages.py
151
152
153
154
155
156
@dataclass
class ArgsJson:
    """Tool arguments as a JSON string."""

    args_json: str
    """A JSON string of arguments."""

args_json instance-attribute

args_json: str

A JSON string of arguments.

MessagesTypeAdapter module-attribute

MessagesTypeAdapter = TypeAdapter(
    list[Annotated[Message, Discriminator("message_kind")]],
    config=ConfigDict(defer_build=True),
)

Pydantic TypeAdapter for (de)serializing messages.