This fixes a 400 INVALID_ARGUMENT error from Google's Gemini API where
function calls were missing required thought_signature in functionCall parts.
Changes:
- Allow signatures when self.model is None (backwards compatibility for
older messages that may not have had their model field set)
- Only add thought_signature to the FIRST function call for parallel
tool calls, per Google's docs
- Take the first non-None signature found (don't keep overwriting)
Reference: https://ai.google.dev/gemini-api/docs/thought-signaturesCloses#8589🤖 Generated with [Letta Code](https://letta.com)
Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: datadog-official[bot] <datadog-official[bot]@users.noreply.github.com>
Co-authored-by: Kian Jones <11655409+kianjones9@users.noreply.github.com>
* fix: handle missing tool_call_id in Anthropic message conversion
- Add null check for self.tool_returns before iterating
- Fall back to message's tool_call_id when tool_return.tool_call_id is None
- Improve error message to show actual tool name from message.name
- Only raise error if no valid tool_call_id is available from either source
This fixes the error "Anthropic API requires tool_use_id to be set" that
occurs when a ToolReturn object in the database doesn't have tool_call_id
set, by using the message-level tool_call_id as a fallback.
Fixes#8379🤖 Generated with [Letta Code](https://letta.com)
Co-authored-by: datadog-official[bot] <datadog-official[bot]@users.noreply.github.com>
Co-Authored-By: Letta <noreply@letta.com>
* fix: restrict tool_call_id fallback to single tool returns
The message-level `self.tool_call_id` is set to the first tool return's ID
for legacy compatibility. For parallel tool calls with multiple tool_returns,
using this as a fallback would incorrectly assign the first tool return's ID
to all subsequent returns missing their own ID.
This change:
- Only allows the fallback when there's exactly one tool return
- For multiple tool returns, each must have its own ID or raise an error
- Adds tool return index to error messages for better debugging
Co-authored-by: Kian Jones <kianjones9@users.noreply.github.com>
🤖 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
---------
Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: datadog-official[bot] <datadog-official[bot]@users.noreply.github.com>
Co-authored-by: Letta <noreply@letta.com>
Co-authored-by: Kian Jones <11655409+kianjones9@users.noreply.github.com>
* feat: Add conversation_id filtering to message list and search endpoints
Add optional conversation_id parameter to filter messages by conversation:
- client.agents.messages.list
- client.messages.list
- client.messages.search
Changes:
- Added conversation_id field to MessageSearchRequest and SearchAllMessagesRequest schemas
- Added conversation_id filtering to list_messages in message_manager.py
- Updated get_agent_recall_async and get_all_messages_recall_async in server.py
- Added conversation_id query parameter to router endpoints
- Updated Turbopuffer client to support conversation_id filtering in searches
Fixes#8320🤖 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Charles Packer <cpacker@users.noreply.github.com>
* add conversation_id to message and tpuf
* default messages filter for backward compatibility
* add test and auto gen
* fix integration test
* fix test
* update test
---------
Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: Charles Packer <cpacker@users.noreply.github.com>
Co-authored-by: christinatong01 <christina@letta.com>
* fix: prevent empty reasoning messages in streaming interfaces
Prevents empty "Thinking..." indicators from appearing in clients by
filtering out reasoning messages with no content at the source.
Changes:
- Gemini: Don't emit ReasoningMessage when only thought_signature exists
- Gemini: Only emit reasoning content if text is non-empty
- Anthropic: Don't emit ReasoningMessage for BetaSignatureDelta
- Anthropic: Only emit reasoning content if thinking text is non-empty
This fixes the issue where providers send signature metadata before
actual thinking content, causing empty reasoning blocks to appear
in the UI after responses complete.
Affects: Gemini reasoning, Anthropic extended thinking
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
* fix: handle Anthropic thinking signature correctly
- Only include 'signature' in Anthropic message payload if it is not None (fixes BadRequestError).
- Capture and attach 'signature' to ReasoningMessage in streaming interface.
* fix(anthropic): attach signature to last reasoning message in stream
---------
Co-authored-by: Letta <noreply@letta.com>
fix AssistantMessage validation error when content is dict
validate_function_response can return either a string or dict, but
AssistantMessage.content expects a string. When a tool returns a dict
like {'tofu': 1, 'mofu': 1, 'bofu': 1}, it needs to be JSON-serialized
before passing to AssistantMessage.
Fixes: pydantic_core._pydantic_core.ValidationError: 2 validation errors for AssistantMessage
* claude code first pass
* rename routes
* search_messages and list_messages
* revert agents messagesearch
* generate api
* fix backend for list all messages
* request for message search
* return list of letta message
* add tests
* error in archive endpoint
* archive delete return type wrong
* optional params for archive creation
* add passage to tpuf on create
* fix archive manager
* support global passage search
* search by agent
* just do basic org wide search for now
* change message test to be about fresh data, cleanup after
---------
Co-authored-by: Ari Webb <ari@letta.com>
* fix(core): sanitize messages to anthropic in the main path the same way (or similar) to how we do it in the token counter
* fix: also patch poison error in backend by filtering lazily
* fix: remap streaming errors (what the fuck)
* fix: dedupe tool clals
* fix: cleanup, removed try/catch
* fix: patch hole in the fallback summarizer where we weren't actually truncating
* fix: remove no-op
* chore: comment
* fix: simplify the new fallback
* fix: properly handle images in summarizer payload
* first hack
* clean up
* first implementation working
* revert package-lock
* remove openai test
* error throw
* typo
* Update integration_test_send_message_v2.py
* Update integration_test_send_message_v2.py
* refine test
* Only make changes for openai non streaming
* Add tests
---------
Co-authored-by: Ari Webb <ari@letta.com>
Co-authored-by: Matt Zhou <mattzh1314@gmail.com>
* letta coded
* migrate to stainless from fern
* revert core workflows
* fix if statement
* fix typo
* run on self-hosted ci runners
* add empty check
* change file
* fix upstream renaming and special character escaping
* fix letta-code with opus
* remove random client type import
* remove env localhost
* remove fialing tests
* ignore ts for now
* fix caching maybe
* tar.gz -> whl
* retain name metadata
* don't build on cache hit
* add sdk_v1 tests
* refactor not to use warnings.warn
* temp circular import fix maybe unecessary/bnad
* fix Deprecation warning
* fix deprecation warning and mcp thing?
* revert changes to mcp server test
* fix deprecation warning
* claude coded first pass
* fix test cases to expect errors instead
* fix this
* let's see how letta-code did
* claude
* fix tests, remove dangling comments, retrofit all managers functions with decorator
* revert to main for these since we are not erroring on invalid tool and block ids
* reorder decorators
* finish refactoring test cases
* reorder agent_manager decorators and fix test tool manager
* add decorator on missing managers
* fix id sources
* remove redundant check
* uses enum now
* move to enum
* fix: patch the issue with the GET failing (tested)
* fix(web): patch for the FE UI
* parse func_response
---------
Co-authored-by: Caren Thomas <carenthomas@gmail.com>
* wip
* Fix parallel tool calling interface
* wip
* wip adapt using id field
* Integrate new multi tool return schemas into parallel tool calling
* Remove example script
* Reset changes to llm stream adapter since old agent loop should not enable parallel tool calling
* Clean up fallback logic for extracting tool calls
* Remove redundant check
* Simplify logic
* Clean up logic in handle ai response
* Fix tests
* Write anthropic dict conversion to be back compatible
* wip
* Double write tool call id for legacy reasons
* Fix override args failures
* Patch for approvals
* Revert comments
* Remove extraneous prints
* Adapt to support multiple tool returns
* remove unused create_tool_return_message
* Add explanation to otid index
* Simplify explicit tool returns
* Simplify function return to only return single object
* repro pr for claude 4-5 only returns reasoning
* add new test instead of overloading existing one
* update test
* filter out trailing thinking message to patch context bug