Skip to content
Merged
6 changes: 6 additions & 0 deletions pydantic_ai_slim/pydantic_ai/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,9 @@ class ModelRequest:
run_id: str | None = None
"""The unique identifier of the agent run in which this message originated."""

metadata: dict[str, Any] | None = None
"""Additional data that can be accessed programmatically by the application but is not sent to the LLM."""

@classmethod
def user_text_prompt(cls, user_prompt: str, *, instructions: str | None = None) -> ModelRequest:
"""Create a `ModelRequest` with a single user prompt as text."""
Expand Down Expand Up @@ -1214,6 +1217,9 @@ class ModelResponse:
run_id: str | None = None
"""The unique identifier of the agent run in which this message originated."""

metadata: dict[str, Any] | None = None
"""Additional data that can be accessed programmatically by the application but is not sent to the LLM."""

@property
def text(self) -> str | None:
"""Get the text in the response."""
Expand Down
7 changes: 7 additions & 0 deletions tests/test_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -3730,6 +3730,7 @@ def test_binary_content_serializable():
'instructions': None,
'kind': 'request',
'run_id': IsStr(),
'metadata': None,
},
{
'parts': [{'content': 'success (no tool calls)', 'id': None, 'part_kind': 'text'}],
Expand All @@ -3751,6 +3752,7 @@ def test_binary_content_serializable():
'kind': 'response',
'finish_reason': None,
'run_id': IsStr(),
'metadata': None,
},
]
)
Expand Down Expand Up @@ -3788,6 +3790,7 @@ def test_image_url_serializable_missing_media_type():
'instructions': None,
'kind': 'request',
'run_id': IsStr(),
'metadata': None,
},
{
'parts': [{'content': 'success (no tool calls)', 'id': None, 'part_kind': 'text'}],
Expand All @@ -3809,6 +3812,7 @@ def test_image_url_serializable_missing_media_type():
'kind': 'response',
'finish_reason': None,
'run_id': IsStr(),
'metadata': None,
},
]
)
Expand Down Expand Up @@ -3853,6 +3857,7 @@ def test_image_url_serializable():
'instructions': None,
'kind': 'request',
'run_id': IsStr(),
'metadata': None,
},
{
'parts': [{'content': 'success (no tool calls)', 'id': None, 'part_kind': 'text'}],
Expand All @@ -3874,6 +3879,7 @@ def test_image_url_serializable():
'kind': 'response',
'finish_reason': None,
'run_id': IsStr(),
'metadata': None,
},
]
)
Expand Down Expand Up @@ -4353,6 +4359,7 @@ def foo_tool(foo: Foo) -> int:
'instructions': None,
'kind': 'request',
'run_id': IsStr(),
'metadata': None,
}
)

Expand Down
7 changes: 3 additions & 4 deletions tests/test_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ def test_file_part_serialization_roundtrip():
'provider_response_id': None,
'finish_reason': None,
'run_id': None,
'metadata': None,
}
]
)
Expand All @@ -475,11 +476,9 @@ def test_model_messages_type_adapter_preserves_run_id():
ModelRequest(
parts=[UserPromptPart(content='Hi there', timestamp=datetime.now(tz=timezone.utc))],
run_id='run-123',
metadata={'key': 'value'},
),
ModelResponse(
parts=[TextPart(content='Hello!')],
run_id='run-123',
),
ModelResponse(parts=[TextPart(content='Hello!')], run_id='run-123', metadata={'key': 'value'}),
]

serialized = ModelMessagesTypeAdapter.dump_python(messages, mode='python')
Expand Down