diff --git a/pydantic_ai_slim/pydantic_ai/messages.py b/pydantic_ai_slim/pydantic_ai/messages.py index 988430d12a..c880c75a74 100644 --- a/pydantic_ai_slim/pydantic_ai/messages.py +++ b/pydantic_ai_slim/pydantic_ai/messages.py @@ -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.""" @@ -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.""" diff --git a/tests/test_agent.py b/tests/test_agent.py index d8323f3c98..29b54643f0 100644 --- a/tests/test_agent.py +++ b/tests/test_agent.py @@ -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'}], @@ -3751,6 +3752,7 @@ def test_binary_content_serializable(): 'kind': 'response', 'finish_reason': None, 'run_id': IsStr(), + 'metadata': None, }, ] ) @@ -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'}], @@ -3809,6 +3812,7 @@ def test_image_url_serializable_missing_media_type(): 'kind': 'response', 'finish_reason': None, 'run_id': IsStr(), + 'metadata': None, }, ] ) @@ -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'}], @@ -3874,6 +3879,7 @@ def test_image_url_serializable(): 'kind': 'response', 'finish_reason': None, 'run_id': IsStr(), + 'metadata': None, }, ] ) @@ -4353,6 +4359,7 @@ def foo_tool(foo: Foo) -> int: 'instructions': None, 'kind': 'request', 'run_id': IsStr(), + 'metadata': None, } ) diff --git a/tests/test_messages.py b/tests/test_messages.py index 9b6ad3fbb8..d971ac46b3 100644 --- a/tests/test_messages.py +++ b/tests/test_messages.py @@ -463,6 +463,7 @@ def test_file_part_serialization_roundtrip(): 'provider_response_id': None, 'finish_reason': None, 'run_id': None, + 'metadata': None, } ] ) @@ -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')