From 203b6ead7cb2c2b10401e861b38f2cb89013a8ed Mon Sep 17 00:00:00 2001 From: Kian Jones <11655409+kianjones9@users.noreply.github.com> Date: Wed, 4 Feb 2026 11:40:12 -0800 Subject: [PATCH] fix: remove duplicate provider trace logging and dead code (#9278) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provider traces were being created twice per step: 1. Via `request_async_with_telemetry` / `log_provider_trace_async` in LLMClient 2. Via direct `create_provider_trace_async` calls in LettaAgent This caused duplicate records in provider_trace_metadata (Postgres) and llm_traces (ClickHouse) for every agent step. Changes: - Remove redundant direct `create_provider_trace_async` calls from letta_agent.py - Remove no-op `stream_async_with_telemetry` method (was just a pass-through to `stream_async`) - Update callers to use `stream_async` directly 🤖 Generated with [Letta Code](https://letta.com) Co-authored-by: Letta --- letta/agents/letta_agent.py | 2 +- letta/llm_api/llm_client_base.py | 8 -------- letta/services/summarizer/summarizer.py | 2 +- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/letta/agents/letta_agent.py b/letta/agents/letta_agent.py index e60fda2d..8460a46a 100644 --- a/letta/agents/letta_agent.py +++ b/letta/agents/letta_agent.py @@ -1490,7 +1490,7 @@ class LettaAgent(BaseAgent): # Attempt LLM request with telemetry wrapper return ( request_data, - await llm_client.stream_async_with_telemetry(request_data, agent_state.llm_config), + await llm_client.stream_async(request_data, agent_state.llm_config), current_in_context_messages, new_in_context_messages, valid_tool_names, diff --git a/letta/llm_api/llm_client_base.py b/letta/llm_api/llm_client_base.py index c8bfbc7d..be54b6b9 100644 --- a/letta/llm_api/llm_client_base.py +++ b/letta/llm_api/llm_client_base.py @@ -127,14 +127,6 @@ class LLMClientBase: except Exception as e: logger.warning(f"Failed to log telemetry: {e}") - async def stream_async_with_telemetry(self, request_data: dict, llm_config: LLMConfig): - """Returns raw stream. Caller should log telemetry after processing via log_provider_trace_async(). - - Call set_telemetry_context() first to set agent_id, run_id, etc. - After consuming the stream, call log_provider_trace_async() with the response data. - """ - return await self.stream_async(request_data, llm_config) - async def log_provider_trace_async( self, request_data: dict, diff --git a/letta/services/summarizer/summarizer.py b/letta/services/summarizer/summarizer.py index dc9680c4..a3247497 100644 --- a/letta/services/summarizer/summarizer.py +++ b/letta/services/summarizer/summarizer.py @@ -542,7 +542,7 @@ async def simple_summary( ) # AnthropicClient.stream_async sets request_data["stream"] = True internally. - stream = await llm_client.stream_async_with_telemetry(req_data, summarizer_llm_config) + stream = await llm_client.stream_async(req_data, summarizer_llm_config) async for _chunk in interface.process(stream): # We don't emit anything; we just want the fully-accumulated content. pass