From 2348b56d430e8cf4f4dcea5421d119ac45c953e9 Mon Sep 17 00:00:00 2001 From: Sehastrajit <197297650+Sehastrajit-S@users.noreply.github.com> Date: Tue, 22 Sep 2026 21:36:51 -0700 Subject: [PATCH] fix(core): forward annotations and metadata in Content.from_dict raw-data path Content.from_dict popped annotations, additional_properties, and raw_representation off the input mapping but never passed them to from_data() when handling raw-data content, silently dropping them. from_data() already accepts all three as keyword arguments, so this just forwards what was already extracted. Fixes microsoft/agent-framework#8632 --- .../packages/core/agent_framework/_types.py | 8 ++++++- python/packages/core/tests/core/test_types.py | 24 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/python/packages/core/agent_framework/_types.py b/python/packages/core/agent_framework/_types.py index 990c55c4ae9..d4f5182e627 100644 --- a/python/packages/core/agent_framework/_types.py +++ b/python/packages/core/agent_framework/_types.py @@ -1531,7 +1531,13 @@ def from_dict(cls: type[ContentT], data: Mapping[str, Any]) -> ContentT: # Special handling for DataContent with data and media_type if content_type == "data" and "data" in remaining and "media_type" in remaining: # Use from_data() to properly create the DataContent with URI - return cls.from_data(remaining["data"], remaining["media_type"]) + return cls.from_data( + remaining["data"], + remaining["media_type"], + annotations=annotations, + additional_properties=additional_properties, + raw_representation=raw_representation, + ) # Handle nested Content objects (e.g., function_call in function_approval_request) if (function_call := remaining.get("function_call")) and isinstance(function_call, dict): diff --git a/python/packages/core/tests/core/test_types.py b/python/packages/core/tests/core/test_types.py index 846c45e0b2a..2fbdaa8889c 100644 --- a/python/packages/core/tests/core/test_types.py +++ b/python/packages/core/tests/core/test_types.py @@ -2564,6 +2564,30 @@ def test_content_from_dict_roundtrip_via_json() -> None: assert restored.arguments == {"key": "value"} +def test_content_from_dict_data_preserves_metadata() -> None: + """Test Content.from_dict forwards annotations, additional_properties, and raw_representation + for raw-data content mappings, matching Content.from_data behavior (see GH issue #8632).""" + raw = object() + data = { + "type": "data", + "data": b"test data", + "media_type": "text/plain", + "annotations": [{"type": "citation", "title": "Source document", "file_id": "file-123"}], + "additional_properties": {"filename": "document.txt"}, + "raw_representation": raw, + } + + content = Content.from_dict(data) + assert content.annotations == data["annotations"] + assert content.additional_properties == data["additional_properties"] + assert content.raw_representation is raw + + message_content = Message("user", [data]).contents[0] + assert message_content.annotations == data["annotations"] + assert message_content.additional_properties == data["additional_properties"] + assert message_content.raw_representation is raw + + def test_content_to_dict_exclude_none() -> None: """Test Content.to_dict excludes None fields by default.""" content = Content.from_text("Hello")