Commit Graph

7054 Commits

Author SHA1 Message Date
jnjpng
df2e666ced test: skip deepwiki SSE MCP server test (#9218)
The deepwiki SSE MCP server is deprecated, so skip this test.

👾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-02-24 10:52:06 -08:00
jnjpng
e25a0c9cdf feat: update compact endpoint to store summary message (#9215)
* base

* add tests
2026-02-24 10:52:06 -08:00
github-actions[bot]
9471fab2cf fix: Add agent_id property to BaseAgentV2 for backward compatibility (#8806)
The LettaAgentV3 (and LettaAgentV2) agents inherit from BaseAgentV2,
which unlike the original BaseAgent class, did not expose an agent_id
attribute. This caused AttributeError: 'LettaAgentV3' object has no
attribute 'agent_id' when code attempted to access self.agent_id.

This fix adds an agent_id property to BaseAgentV2 that returns
self.agent_state.id, maintaining backward compatibility with code
that expects the self.agent_id interface from the original BaseAgent.

Closes #8805

🤖 Generated with [Letta Code](https://letta.com)

Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: Letta <noreply@letta.com>
2026-02-24 10:52:06 -08:00
github-actions[bot]
5cde3c2ec0 fix: handle data URLs in image processing to prevent LettaImageFetchError (#8958)
When users send images as base64 data URLs (data:image/jpeg;base64,...),
the code was incorrectly trying to fetch them via HTTP, causing a
LettaImageFetchError. This fix adds proper handling for data: URLs by
parsing the media type and base64 data directly from the URL string.

Fixes #8957

🤖 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>
2026-02-24 10:52:05 -08:00
github-actions[bot]
101cfefe5e fix: add retry logic for turbopuffer transient network errors (#8635)
Add async retry decorator with exponential backoff to handle transient
network connection errors (httpx.ConnectError) when connecting to
turbopuffer.com. This addresses production errors seen in memgpt-server.

Changes:
- Add `async_retry_with_backoff()` decorator for async methods
- Add `is_transient_error()` helper to identify retryable errors
- Apply retry logic to all turbopuffer network operations
- Retry config: 3 retries, 1s initial delay, 2x backoff, 10% jitter

Fixes #8390
Relates to #8155

🤖 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>
2026-02-24 10:52:05 -08:00
github-actions[bot]
81398118dd fix: add validation for per_file_view_window_char_limit to prevent int32 overflow (#8937)
The per_file_view_window_char_limit column is defined as INTEGER (32-bit)
in PostgreSQL. Without API-level validation, users could pass values
exceeding int32 max (2,147,483,647), causing database errors.

Changes:
- Added MAX_INT32, MAX_PER_FILE_VIEW_WINDOW_CHAR_LIMIT, and
  MAX_FILES_OPEN_LIMIT constants
- Added field validators to CreateAgent and UpdateAgent schemas to
  enforce these limits

Fixes #8936

🤖 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>
2026-02-24 10:52:05 -08:00
jnjpng
d28ccc0be6 feat: add summary message and event on compaction (#9144)
* base

* update

* update

* revert formatting

* routes

* legacy

* fix

* review

* update
2026-02-24 10:52:05 -08:00
Kian Jones
b0f8e16ac0 fix: check both unique constraints in provider model sync (#9193)
The sync_provider_models_async function was only checking for existing
models by (handle, organization_id, model_type) before creating, but
the database has a second unique constraint on (name, provider_id,
model_type). This caused UniqueConstraintViolationError when a model
with the same name/provider already existed under a different handle.

🤖 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-02-24 10:52:05 -08:00
Kian Jones
3b5251fbd6 fix: force statement_timeout=0 on all database connections (#9184)
Cloud SQL's connection pooler can return connections with stale
session settings from previous clients. If any client (Datadog,
monitoring tools, manual psql) sets statement_timeout, that setting
persists on the pooled connection.

This explicitly sets statement_timeout=0 via asyncpg's server_settings
on every connection, ensuring consistent behavior regardless of
connection pool state.

🤖 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-02-24 10:52:05 -08:00
Kian Jones
9a8d381b14 fix: add field validators to Block schema for int32 limit and null bytes (#9185)
- Add `validate_limit_int32` validator (mode=after) to reject limit values
  exceeding PostgreSQL INTEGER max (2147483647)
- Add `sanitize_value_null_bytes` validator (mode=before) to strip null bytes
  from block values, preventing asyncpg CharacterNotInRepertoireError

Fixes DB errors:
- "value out of int32 range" on block.limit
- "invalid byte sequence for encoding UTF8: 0x00" on block.value

🤖 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-02-24 10:52:05 -08:00
Ari Webb
7b0b1f2531 fix: warning (#9179)
* fix: warning

* just stage publish api

* note

* api
2026-02-24 10:52:05 -08:00
cthomas
65dbd7fd89 chore: bump v0.16.4 (#3168) 2026-01-29 12:50:03 -08:00
Caren Thomas
72871ff923 bump version 2026-01-29 12:45:45 -08:00
Kian Jones
00045afc3c chore: add statement timeout log (#9177)
* fix: remove duplicate 'Tag and push latest' step from crouton workflow

* startuplog

* Update apps/core/letta/server/rest_api/app.py
2026-01-29 12:44:04 -08:00
Kevin Lin
3a13c63f60 fix: preserve slashes in memory block paths (#9172)
Remove .replace("/", "_") from memory block label processing to allow hierarchical memory organization with slashes.

🐾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
Ari Webb
501de90d6c fix: fix base openrouter (#9171) 2026-01-29 12:44:04 -08:00
Ari Webb
bcd90859ec fix: byok uses our key, fix that (#9169) 2026-01-29 12:44:04 -08:00
Kian Jones
c1a02fa180 feat: add metadata-only provider trace storage option (#9155)
* feat: add metadata-only provider trace storage option

Add support for writing provider traces to a lightweight metadata-only
table (~1.5GB) instead of the full table (~725GB) since request/response
JSON is now stored in GCS.

- Add `LETTA_TELEMETRY_PROVIDER_TRACE_PG_METADATA_ONLY` setting
- Create `provider_trace_metadata` table via alembic migration
- Conditionally write to new table when flag is enabled
- Include backfill script for migrating existing data

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* chore: regenerate API spec and SDK

* fix: use composite PK (created_at, id) for provider_trace_metadata

Aligns with GCS partitioning structure (raw/date=YYYY-MM-DD/{id}.json.gz)
and enables efficient date-range queries via the B-tree index.

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* ammendments

* fix: add bulk data copy to migration

Copy existing provider_traces metadata in-migration instead of separate
backfill script. Creates indexes after bulk insert for better performance.

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* fix: remove data copy from migration, create empty table only

Old data stays in provider_traces, new writes go to provider_trace_metadata
when flag is enabled. Full traces are in GCS anyway.

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* fix: address PR comments

- Remove GCS mention from ProviderTraceMetadata docstring
- Move metadata object creation outside session context

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* fix: reads always use full provider_traces table

The metadata_only flag should only control writes. Reads always go to
the full table to avoid returning ProviderTraceMetadata where
ProviderTrace is expected.

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* feat: enable metadata-only provider trace writes in prod

Add LETTA_TELEMETRY_PROVIDER_TRACE_PG_METADATA_ONLY=true to all
Helm values (memgpt-server and lettuce-py, prod and dev).

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

---------

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
amysguan
69cad47e6a fix: respect enable_reasoner setting from .af imports instead of falling back to model defaults (#9163)
Co-authored-by: Amy Guan <amy@letta.com>
2026-01-29 12:44:04 -08:00
Ari Webb
a798cc90c4 fix: openrouter provider (#9166)
* fix: openrouter provider

* just stage publish api

* web openapi
2026-01-29 12:44:04 -08:00
cthomas
59ffaec8f4 fix: revert test comments (#9161) 2026-01-29 12:44:04 -08:00
Ari Webb
9ce1249738 feat: openrouter byok (#9148)
* feat: openrouter byok

* new client is unnecessary

* revert json diffs
2026-01-29 12:44:04 -08:00
cthomas
d992aa0df4 fix: non-streaming conversation messages endpoint (#9159)
* fix: non-streaming conversation messages endpoint

**Problems:**
1. `AssertionError: run_id is required when enforce_run_id_set is True`
   - Non-streaming path didn't create a run before calling `step()`

2. `ResponseValidationError: Unable to extract tag using discriminator 'message_type'`
   - `response_model=LettaStreamingResponse` but non-streaming returns `LettaResponse`

**Fixes:**
1. Add run creation before calling `step()` (mirrors agents endpoint)
2. Set run_id in Redis for cancellation support
3. Pass `run_id` to `step()`
4. Change `response_model` from `LettaStreamingResponse` to `LettaResponse`
   (streaming returns `StreamingResponse` which bypasses response_model validation)

**Test:**
Added `test_conversation_non_streaming_raw_http` to verify the fix.

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* api sync

---------

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
cthomas
dd7e28fae6 fix: return 400 instead of 500 for image fetch errors (#9157)
**Problem:**
When a user sends a message with an image URL that times out or fails to
fetch, the server returns a 500 Internal Server Error with a generic message.
This is confusing because the user doesn't know what went wrong.

**Root Cause:**
`LettaImageFetchError` was not registered in the exception handlers, so it
bubbled up as an unhandled exception.

**Fix:**
Register `LettaImageFetchError` with the 400 Bad Request handler. Now users
get a clear error message like:
```
Failed to fetch image from https://...: Timeout after 2 attempts
```

This tells users exactly what went wrong so they can retry with a different
image or verify the URL is accessible.

👾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
cthomas
372c8dcc85 fix: add conversation_id support to LettaAgentV3 constructor (#9156)
**Error:**
```
TypeError: LettaAgentV2.__init__() got an unexpected keyword argument 'conversation_id'
```

**Trace:** https://letta.grafana.net/goto/afbk4da3fuxhcf?orgId=stacks-1189126

**Problem:**
The `POST /v1/conversations/{conversation_id}/compact` endpoint was failing
because `LettaAgentV3` inherits from `LettaAgentV2` without overriding
`__init__`, so passing `conversation_id` to the constructor failed.

**Fix:**
1. Add `__init__` to `LettaAgentV3` that accepts optional `conversation_id`
2. Remove redundant `conversation_id` param from `_checkpoint_messages` -
   use `self.conversation_id` consistently instead
3. Clean up internal callers that were passing `conversation_id=self.conversation_id`

Backward compatible - existing code creating `LettaAgentV3(agent_state, actor)`
still works since `conversation_id` defaults to `None`.

👾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
Shubham Naik
bb2145c24c connections (#9113)
* chore: release code

* chore: release code

* chore: release code

* chore: release code

* chore: release code

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: change paths

* chore: remote

* chore: support  multi project chat
2026-01-29 12:44:04 -08:00
Kian Jones
45c0a4cd0d feat: add ID format validation to batch request schema (#9154)
* feat: add ID format validation to batch request schema

Add ID format validation to LettaBatchRequest using existing validator
types from letta.validators.

Changes:
- LettaBatchRequest.agent_id: str → AgentId

This ensures malformed agent IDs in batch requests are rejected with 422
validation errors instead of causing 500 database errors.

🤖 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* chore: regenerate API spec and SDK

---------

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
Kian Jones
eaaca141f7 feat: add ID format validation to identity schemas (#9153)
* feat: add ID format validation to identity schemas

Add ID format validation to IdentityCreate, IdentityUpsert, and IdentityUpdate
schemas using existing validator types from letta.validators.

Changes:
- agent_ids: Optional[List[str]] → Optional[List[AgentId]]
- block_ids: Optional[List[str]] → Optional[List[BlockId]]

This ensures malformed IDs are rejected with 422 validation errors instead
of causing 500 database errors.

🤖 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* chore: regenerate API spec and SDK

---------

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
Kian Jones
dd8be95142 feat: add ID format validation to group schemas (#9152)
* feat: add ID format validation to group schemas

Add ID format validation to GroupCreate, GroupUpdate, and manager config
schemas using existing validator types from letta.validators.

Changes:
- GroupCreate/GroupUpdate: agent_ids → List[AgentId], shared_block_ids → List[BlockId]
- SupervisorManager, DynamicManager, SleeptimeManager, VoiceSleeptimeManager:
  manager_agent_id → AgentId
- Update variants: manager_agent_id → Optional[AgentId]

This ensures malformed IDs are rejected with 422 validation errors instead
of causing 500 database errors.

🤖 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* chore: regenerate API spec and SDK

---------

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
Kian Jones
42b1e741dc fix: prevent duplicate block attachment in sleeptime agents (#9150)
Check if a block with the same label already exists before attaching
to sleeptime agents. This prevents UniqueConstraintViolationError on
the (agent_id, block_label) constraint when the same block is attached
multiple times due to race conditions.

🤖 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
Ari Webb
04e6d668ec fix: make it so sync updates model_endpoint info (#9138) 2026-01-29 12:44:04 -08:00
cthomas
6f8f227e64 fix: improve approval retry idempotency check for server-side tool calls (#9136)
**Problem:**
When retrying an approval response, the idempotency check only looked at
the last message. If the approved tool triggered server-side tool calls
(e.g., `memory`), those tool returns would be the last message, causing
the idempotency check to fail with:
"Cannot process approval response: No tool call is currently awaiting approval."

**Root Cause:**
The check at line 249 only validated `current_in_context_messages[-1]`,
but server-side tool calls can add additional tool return messages after
the original approved tool's return.

**Fix:**
Search the last 10 messages (instead of just the last one) for a tool
return matching the approval's tool_call_ids. This handles the case where
server-side tool calls happen after the approved tool executes, while
keeping the search bounded and efficient.

👾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
Charles Packer
0c016d3ee3 fix(core): correct cursor direction for descending pagination in list_agent_blocks_async (#9122)
The cursor-based pagination was not accounting for sort order. When using
descending order (the default), "after cursor X" should return items with
id < X (items that come after X in the descending result set), but the code
was using id > X which caused infinite loops in clients iterating through pages.

This fix adjusts the cursor comparison based on the sort order:
- ascending: after=id > X, before=id < X
- descending: after=id < X, before=id > X

Note: Other pagination methods (list_agent_sources_async, list_agent_tools_async,
list_agent_groups_async) may have the same issue and should be audited.

🐾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
Kian Jones
34eed72150 feat: add user id validation (#9128)
* add user id validation

* relax conversation id check to allow default while I'm here

* fix annotation validation

* -api changes
2026-01-29 12:44:04 -08:00
cthomas
5530d541f1 fix: skip default actor init on app start (#9125)
* fix: skip default actor init on app start

* opposite check
2026-01-29 12:44:04 -08:00
cthomas
674bfe95ec fix: no default actor setting check (#9124)
* fix: no default actor setting check

* prevent default actor creation in fallback
2026-01-29 12:44:04 -08:00
Kian Jones
0099a95a43 fix(sec): first pass of ensuring actor id is required everywhere (#9126)
first pass of ensuring actor id is required
2026-01-29 12:44:04 -08:00
Sarah Wooders
b34ad43691 feat: add minimax byok to ui (#9101)
* fix: patch minimax

* feat: add frontend changes for minimax

* add logo, fix backend

* better check for is minimax

* more references fixed for minimax

* start revering unnecessary changes

* revert backend changes, just ui

* fix minimax fully

* fix test

* add key to deploy action

---------

Co-authored-by: Ari Webb <ari@letta.com>
Co-authored-by: Ari Webb <arijwebb@gmail.com>
2026-01-29 12:44:04 -08:00
github-actions[bot]
62a00cc672 fix: remove deprecation from agent passages endpoints (#9117)
* fix: remove deprecation from agent passages endpoints

The client.agent.passages endpoints (list, create, search, delete) were
incorrectly marked as deprecated. This would break significant amounts
of user code and negatively impact developer experience.

Fixes #9116

Co-authored-by: Ari Webb <AriWebb@users.noreply.github.com>

* stage publish api

---------

Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: Ari Webb <AriWebb@users.noreply.github.com>
Co-authored-by: Ari Webb <ari@letta.com>
2026-01-29 12:44:04 -08:00
Shelley Pham
5dc70e48eb Shelley/let 7218 editor should be compatible with typescript [LET-7218] (#9087)
* fix python icon not showing up

* make typescript compatible for updating tools in typescript

* Update flags.ts

* display tools properly in navigation

* add default json schema to newly created tools

* add typescript to code editor

* make editor typescript compatible

* Update ToolsEditor.tsx

* typescript ocmpatible editor

* sandbox stuff

* update breadcrumb icon

* pass in source type to tool simulator

* undo

* Update tool-editor.cy.ts
2026-01-29 12:44:04 -08:00
Charles Packer
e0d9238bb6 fix(core): add check_api_key method to MiniMaxProvider (#9112)
The MiniMaxProvider class was missing a check_api_key() implementation,
causing /v1/providers/check to return a 500 error when validating
MiniMax API keys. The base Provider class raises NotImplementedError.

This adds check_api_key() using the Anthropic client (since MiniMax uses
an Anthropic-compatible API), following the same pattern as AnthropicProvider.

👾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
Shubham Naik
8f0ac630ab chore: nw [LET-6982] (#9081)
* chore: nw

* chore: more

* feat: redesign details view

* feat: redesign details view

* chore: poll every hour
2026-01-29 12:44:04 -08:00
Sarah Wooders
fb69a96cd6 fix: patch minimax (#9099) 2026-01-29 12:44:04 -08:00
Sarah Wooders
adab8cd9b5 feat: add MiniMax provider support (#9095)
* feat: add MiniMax provider support

Add MiniMax as a new LLM provider using their Anthropic-compatible API.

Key implementation details:
- Uses standard messages API (not beta) - MiniMax supports thinking blocks natively
- Base URL: https://api.minimax.io/anthropic
- Models: MiniMax-M2.1, MiniMax-M2.1-lightning, MiniMax-M2 (all 200K context, 128K output)
- Temperature clamped to valid range (0.0, 1.0]
- All M2.x models treated as reasoning models (support interleaved thinking)

Files added:
- letta/schemas/providers/minimax.py - MiniMax provider schema
- letta/llm_api/minimax_client.py - Client extending AnthropicClient
- tests/test_minimax_client.py - Unit tests (13 tests)
- tests/model_settings/minimax-m2.1.json - Integration test config

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* chore: regenerate API spec with MiniMax provider

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* chore: use MiniMax-M2.1-lightning for CI tests

Switch to the faster/cheaper lightning model variant for integration tests.

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* chore: add MINIMAX_API_KEY to deploy-core command

Co-authored-by: Sarah Wooders <sarahwooders@users.noreply.github.com>

* chore: regenerate web openapi spec with MiniMax provider

Co-authored-by: Sarah Wooders <sarahwooders@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: Sarah Wooders <sarahwooders@users.noreply.github.com>
2026-01-29 12:44:04 -08:00
Sarah Wooders
221b4e6279 refactor: add extract_usage_statistics returning LettaUsageStatistics (#9065)
👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

---------

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
cthomas
2bccd36382 Revert "fix: ensure stop_reason is always set and reduce noisy logs (… (#9086)
Revert "fix: ensure stop_reason is always set and reduce noisy logs (#9046)"

This reverts commit 4241a360579440d2697124ba69061d0e46ecc5e9.

**Problem:**
After the original change, caren-code-agent reported streams hanging
indefinitely. The trace shows ttft (time to first token) succeeds, but
the stream never closes.

**Root Cause (suspected):**
The change modified `is_complete=is_done` to `is_complete=saw_done`,
meaning error events no longer mark the stream as complete immediately.
This may cause timing issues where clients wait for more data before
the finalizer runs.

**Fix:**
Revert to the defensive "belt-and-suspenders" approach that always
appends [DONE]. The noisy logs are preferable to hanging streams.

The original comment noted: "Even if a previous chunk set `complete`,
an extra [DONE] is harmless and ensures SDKs that rely on explicit
[DONE] will exit."

👾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
cthomas
18274b5a42 fix: handle null step_id on approval request messages (#9074)
**Problem:**
Runs failed with error:
```
Argument step_id does not match type <class 'str'>; is None of type <class 'NoneType'>
```

This happened when processing approval responses where the original
approval request message had `step_id=None`.

**Root Cause:**
Line 672 in `_step()` directly used `approval_request.step_id`:
```python
step_id = approval_request.step_id  # Can be None!
step_metrics = await self.step_manager.get_step_metrics_async(step_id=step_id, ...)
```

`Message.step_id` is `Optional[str]` (default None), but `get_step_metrics_async`
has `step_id: str` with `@enforce_types` validation.

Old approval messages or edge cases could have `step_id=None`, causing
the enforce_types decorator to reject the call.

**Fix:**
Check if `step_id is None` and generate a new step_id + initialize step
checkpoint if needed, instead of assuming step_id always exists.

**Note:**
Similar issue exists in letta_agent_v2.py and temporal agents, but v2
is deprecated.

👾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
cthomas
3e49cf5d44 fix: load default provider config when summarizer uses different prov… (#9051)
fix: load default provider config when summarizer uses different provider

**Problem:**
Summarization failed when agent used one provider (e.g., Google AI) but
summarizer config specified a different provider (e.g., Anthropic):

```python
# Agent LLM config
model_endpoint_type='google_ai', handle='gemini-something/gemini-2.5-pro',
context_window=100000

# Summarizer config
model='anthropic/claude-haiku-4-5-20251001'

# Bug: Resulting summarizer_llm_config mixed Google + Anthropic settings
model='claude-haiku-4-5-20251001', model_endpoint_type='google_ai',  #  Wrong endpoint!
context_window=100000  #  Google's context window, not Anthropic's default!
```

This sent Claude requests to Google AI endpoints with incorrect parameters.

**Root Cause:**
`_build_summarizer_llm_config()` always copied the agent's LLM config as base,
then patched model/provider fields. But this kept all provider-specific settings
(endpoint, context_window, etc.) from the wrong provider.

**Fix:**
1. Parse provider_name from summarizer handle
2. Check if it matches agent's model_endpoint_type (or provider_name for custom)
3. **If YES** → Use agent config as base, override model/handle (same provider)
4. **If NO** → Load default config via `provider_manager.get_llm_config_from_handle()` (new provider)

**Example Flow:**
```python
# Agent: google_ai/gemini-2.5-pro
# Summarizer: anthropic/claude-haiku

provider_name = "anthropic"  # Parsed from handle
provider_matches = ("anthropic" == "google_ai")  # False 

# Different provider → load default Anthropic config
base = await provider_manager.get_llm_config_from_handle(
    handle="anthropic/claude-haiku",
    actor=self.actor
)
# Returns: model_endpoint_type='anthropic', endpoint='https://api.anthropic.com', etc. 
```

**Result:**
- Summarizer with different provider gets correct default config
- No more mixing Google endpoints with Anthropic models
- Same-provider summarizers still inherit agent settings efficiently

👾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
Shubham Naik
55a89398e1 chore: rebuild api requests (#9069) 2026-01-29 12:44:04 -08:00
github-actions[bot]
194c743223 refactor: rename stream to streaming in ConversationMessageRequest (#9063) 2026-01-29 12:44:04 -08:00