From 22cc62fff5a39c2dd60c6e16c21c4d8fd868e3c7 Mon Sep 17 00:00:00 2001 From: Aleksander Sekowski Date: Sat, 25 Jul 2026 22:04:44 -0700 Subject: [PATCH] Port the surgical toolResult stripping from buyer-agent patches/crewai_bedrock_fix.py has drifted between the two agent repos. buyer-agent's sanitizer strips only the toolResult blocks whose toolUseId has no matching toolUse in the preceding assistant message; the seller copy stripped ALL toolResult blocks in that case, discarding valid tool results along with the orphans and losing tool output from the conversation. This ports buyer's surgical version and brings the file to the union of both repos' fixes, byte-identical with the buyer-agent copy (a matching PR ports _patch_parse_native_tool_call there). Also documents the surgical-strip behavior in the sanitizer docstring. --- patches/crewai_bedrock_fix.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/patches/crewai_bedrock_fix.py b/patches/crewai_bedrock_fix.py index 98fefaa..3a922cf 100644 --- a/patches/crewai_bedrock_fix.py +++ b/patches/crewai_bedrock_fix.py @@ -90,7 +90,8 @@ def _sanitize_tool_blocks(messages: list) -> list: - If not matched, strips the toolUse blocks (keeps text blocks) - For each user message with toolResult blocks, checks if the previous assistant message has matching toolUse blocks - - If not matched, strips the toolResult blocks (keeps text blocks) + - If not matched, strips only the unmatched toolResult blocks (keeps + text blocks and toolResult blocks whose toolUseId does match) This handles both directions of orphaning: - Executor added toolUse but result is in a different message format @@ -171,7 +172,7 @@ def _sanitize_tool_blocks(messages: list) -> list: if result_ids: # Check if previous message (in fixed list) has matching toolUse prev_msg = fixed[-1] if fixed else None - matched = False + use_ids = set() if ( prev_msg @@ -180,22 +181,25 @@ def _sanitize_tool_blocks(messages: list) -> list: ): prev_content = prev_msg.get("content", []) if isinstance(prev_content, list): - use_ids = set() for block in prev_content: if isinstance(block, dict) and "toolUse" in block: tu = block["toolUse"] if isinstance(tu, dict) and "toolUseId" in tu: use_ids.add(tu["toolUseId"]) - matched = result_ids.issubset(use_ids) - if not matched: - # Strip toolResult blocks, keep text blocks - text_blocks = [ + if not result_ids.issubset(use_ids): + # Only strip toolResult blocks whose toolUseId is NOT in use_ids + kept_blocks = [ b for b in content - if isinstance(b, dict) and "text" in b + if not ( + isinstance(b, dict) + and "toolResult" in b + and isinstance(b["toolResult"], dict) + and b["toolResult"].get("toolUseId") not in use_ids + ) ] - if text_blocks: - fixed.append({"role": "user", "content": text_blocks}) + if kept_blocks: + fixed.append({"role": "user", "content": kept_blocks}) i += 1 continue @@ -205,7 +209,6 @@ def _sanitize_tool_blocks(messages: list) -> list: return fixed - def _patch_parse_native_tool_call(): """Patch CrewAgentExecutor._parse_native_tool_call to fix arg extraction.