From f7350c797a537703eaa8303770296b1a9c7f54b0 Mon Sep 17 00:00:00 2001 From: Otto Date: Mon, 2 Feb 2026 13:01:05 +0000 Subject: [PATCH] fix(copilot): use messages_dict in fallback context compaction (#11922) ## Summary Fixes a bug where the fallback path in context compaction passes `recent_messages` (already sliced) instead of `messages_dict` (full conversation) to `_ensure_tool_pairs_intact`. This caused the function to fail to find assistant messages that exist in the original conversation but were outside the sliced window, resulting in orphan tool_results being sent to Anthropic and rejected with: ``` messages.66.content.0: unexpected tool_use_id found in tool_result blocks: toolu_vrtx_019bi1PDvEn7o5ByAxcS3VdA ``` ## Changes - Pass `messages_dict` and `slice_start` (relative to full conversation) instead of `recent_messages` and `reduced_slice_start` (relative to already-sliced list) ## Testing This is a targeted fix for the fallback path. The bug only manifests when: 1. Token count > 120k (triggers compaction) 2. Initial compaction + summary still exceeds limit (triggers fallback) 3. A tool_result's corresponding assistant is in `messages_dict` but not in `recent_messages` ## Related - Fixes SECRT-1861 - Related: SECRT-1839 (original fix that missed this code path) --- .../backend/backend/api/features/chat/service.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/autogpt_platform/backend/backend/api/features/chat/service.py b/autogpt_platform/backend/backend/api/features/chat/service.py index 20216162b5..ddc64d64b2 100644 --- a/autogpt_platform/backend/backend/api/features/chat/service.py +++ b/autogpt_platform/backend/backend/api/features/chat/service.py @@ -1184,11 +1184,14 @@ async def _stream_chat_chunks( else recent_messages ) # Ensure tool pairs stay intact in the reduced slice - reduced_slice_start = max( + # Note: Search in messages_dict (full conversation) not recent_messages + # (already sliced), so we can find assistants outside the current slice. + # Calculate where reduced_recent starts in messages_dict + reduced_start_in_dict = slice_start + max( 0, len(recent_messages) - keep_count ) reduced_recent = _ensure_tool_pairs_intact( - reduced_recent, recent_messages, reduced_slice_start + reduced_recent, messages_dict, reduced_start_in_dict ) if has_system_prompt: messages = [