@@ -2938,7 +2938,13 @@ def test_binary_content_all_messages_json():
2938
2938
{
2939
2939
'content' : [
2940
2940
'Hello' ,
2941
- {'data' :'SGVsbG8=' ,'media_type' :'text/plain' ,'vendor_metadata' :None ,'kind' :'binary' },
2941
+ {
2942
+ 'data' :'SGVsbG8=' ,
2943
+ 'media_type' :'text/plain' ,
2944
+ 'vendor_metadata' :None ,
2945
+ 'kind' :'binary' ,
2946
+ 'identifier' :None ,
2947
+ },
2942
2948
],
2943
2949
'timestamp' :IsStr (),
2944
2950
'part_kind' :'user-prompt' ,
@@ -2973,7 +2979,7 @@ def test_binary_content_all_messages_json():
2973
2979
def test_tool_return_part_binary_content_serialization ():
2974
2980
"""Test that ToolReturnPart can properly serialize BinaryContent."""
2975
2981
png_data = b'\x89 PNG\r \n \x1a \n \x00 \x00 \x00 \r IHDR\x00 \x00 \x00 \x01 \x00 \x00 \x00 \x01 \x08 \x02 \x00 \x00 \x00 \x90 wS\xde \x00 \x00 \x00 \x0c IDATx\x9c c```\x00 \x00 \x00 \x04 \x00 \x01 \xf6 \x17 8\x00 \x00 \x00 \x00 IEND\xae B`\x82 '
2976
- binary_content = BinaryContent (png_data ,media_type = 'image/png' )
2982
+ binary_content = BinaryContent (png_data ,media_type = 'image/png' , identifier = 'image_id_1' )
2977
2983
2978
2984
tool_return = ToolReturnPart (tool_name = 'test_tool' ,content = binary_content ,tool_call_id = 'test_call_123' )
2979
2985
@@ -2982,10 +2988,12 @@ def test_tool_return_part_binary_content_serialization():
2982
2988
assert '"kind":"binary"' in response_str
2983
2989
assert '"media_type":"image/png"' in response_str
2984
2990
assert '"data":"' in response_str
2991
+ assert '"identifier":"image_id_1"' in response_str
2985
2992
2986
2993
response_obj = tool_return .model_response_object ()
2987
2994
assert response_obj ['return_value' ]['kind' ]== 'binary'
2988
2995
assert response_obj ['return_value' ]['media_type' ]== 'image/png'
2996
+ assert response_obj ['return_value' ]['identifier' ]== 'image_id_1'
2989
2997
assert 'data' in response_obj ['return_value' ]
2990
2998
2991
2999
@@ -3011,6 +3019,50 @@ def get_image() -> BinaryContent:
3011
3019
assert result .output == 'Image received'
3012
3020
3013
3021
3022
+ def test_tool_returning_binary_content_with_identifier ():
3023
+ """Test that a tool returning BinaryContent directly works correctly."""
3024
+
3025
+ def llm (messages :list [ModelMessage ],info :AgentInfo )-> ModelResponse :
3026
+ if len (messages )== 1 :
3027
+ return ModelResponse (parts = [ToolCallPart ('get_image' , {})])
3028
+ else :
3029
+ return ModelResponse (parts = [TextPart ('Image received' )])
3030
+
3031
+ agent = Agent (FunctionModel (llm ))
3032
+
3033
+ @agent .tool_plain
3034
+ def get_image ()-> BinaryContent :
3035
+ """Return a simple image."""
3036
+ png_data = b'\x89 PNG\r \n \x1a \n \x00 \x00 \x00 \r IHDR\x00 \x00 \x00 \x01 \x00 \x00 \x00 \x01 \x08 \x02 \x00 \x00 \x00 \x90 wS\xde \x00 \x00 \x00 \x0c IDATx\x9c c```\x00 \x00 \x00 \x04 \x00 \x01 \xf6 \x17 8\x00 \x00 \x00 \x00 IEND\xae B`\x82 '
3037
+ return BinaryContent (png_data ,media_type = 'image/png' ,identifier = 'image_id_1' )
3038
+
3039
+ # This should work without the serialization error
3040
+ result = agent .run_sync ('Get an image' )
3041
+ assert result .all_messages ()[2 ]== snapshot (
3042
+ ModelRequest (
3043
+ parts = [
3044
+ ToolReturnPart (
3045
+ tool_name = 'get_image' ,
3046
+ content = 'See file image_id_1' ,
3047
+ tool_call_id = IsStr (),
3048
+ timestamp = IsNow (tz = timezone .utc ),
3049
+ ),
3050
+ UserPromptPart (
3051
+ content = [
3052
+ 'This is file image_id_1:' ,
3053
+ BinaryContent (
3054
+ data = b'\x89 PNG\r \n \x1a \n \x00 \x00 \x00 \r IHDR\x00 \x00 \x00 \x01 \x00 \x00 \x00 \x01 \x08 \x02 \x00 \x00 \x00 \x90 wS\xde \x00 \x00 \x00 \x0c IDATx\x9c c```\x00 \x00 \x00 \x04 \x00 \x01 \xf6 \x17 8\x00 \x00 \x00 \x00 IEND\xae B`\x82 ' ,
3055
+ media_type = 'image/png' ,
3056
+ identifier = 'image_id_1' ,
3057
+ ),
3058
+ ],
3059
+ timestamp = IsNow (tz = timezone .utc ),
3060
+ ),
3061
+ ]
3062
+ )
3063
+ )
3064
+
3065
+
3014
3066
def test_instructions_raise_error_when_system_prompt_is_set ():
3015
3067
agent = Agent ('test' ,instructions = 'An instructions!' )
3016
3068