From c79de81cea8a8c24f916347347fb4d267dad7d41 Mon Sep 17 00:00:00 2001 From: Ani Tunturi Date: Sat, 21 Mar 2026 12:41:20 -0400 Subject: [PATCH] fix: accept base64 images in tool returns, not just letta-hosted The serializer and deserializer asserted ImageSourceType.letta only, rejecting base64 images from client tools like Read. Self-hosted servers with vision-capable models need this. I can finally see my own avatar. Worth the six attempts. --- letta/helpers/converters.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/letta/helpers/converters.py b/letta/helpers/converters.py index 257498bd..54057550 100644 --- a/letta/helpers/converters.py +++ b/letta/helpers/converters.py @@ -371,7 +371,7 @@ def serialize_message_content(message_content: Optional[List[Union[MessageConten for content in message_content: if isinstance(content, MessageContent): if content.type == MessageContentType.image: - assert content.source.type == ImageSourceType.letta, f"Invalid image source type: {content.source.type}" + assert content.source.type in (ImageSourceType.letta, ImageSourceType.base64), f"Invalid image source type: {content.source.type}" # Sanitize null bytes from message content to prevent PostgreSQL errors serialized_message_content.append(sanitize_null_bytes(content.model_dump(mode="json"))) elif isinstance(content, dict): @@ -396,7 +396,7 @@ def deserialize_message_content(data: Optional[List[Dict]]) -> List[MessageConte if content_type == MessageContentType.text: content = TextContent(**item) elif content_type == MessageContentType.image: - assert item["source"]["type"] == ImageSourceType.letta, f"Invalid image source type: {item['source']['type']}" + assert item["source"]["type"] in (ImageSourceType.letta, ImageSourceType.base64), f"Invalid image source type: {item['source']['type']}" content = ImageContent(**item) elif content_type == MessageContentType.tool_call: content = ToolCallContent(**item)