From 4eb07c44b982076f29331e2d41e1f6963cfc48db Mon Sep 17 00:00:00 2001 From: Nikolas de Hor Date: Fri, 20 Feb 2026 09:21:27 -0300 Subject: [PATCH 1/2] fix: preserve interim content as fallback when retry produces empty response Fixes regression from #825 where models that respond with final text directly (no tools) had their answer discarded by the retry mechanism. Closes #878 --- nanobot/agent/loop.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/nanobot/agent/loop.py b/nanobot/agent/loop.py index 3016d92..d817815 100644 --- a/nanobot/agent/loop.py +++ b/nanobot/agent/loop.py @@ -185,6 +185,7 @@ class AgentLoop: final_content = None tools_used: list[str] = [] text_only_retried = False + interim_content: str | None = None # Fallback if retry produces nothing while iteration < self.max_iterations: iteration += 1 @@ -231,9 +232,11 @@ class AgentLoop: else: final_content = self._strip_think(response.content) # Some models send an interim text response before tool calls. - # Give them one retry; don't forward the text to avoid duplicates. + # Give them one retry; save the content as fallback in case + # the retry produces nothing useful (e.g. model already answered). if not tools_used and not text_only_retried and final_content: text_only_retried = True + interim_content = final_content logger.debug("Interim text response (no tools used yet), retrying: {}", final_content[:80]) messages = self.context.add_assistant_message( messages, response.content, @@ -241,6 +244,9 @@ class AgentLoop: ) final_content = None continue + # Fall back to interim content if retry produced nothing + if not final_content and interim_content: + final_content = interim_content break return final_content, tools_used From 45f33853cf952b8642c104a5ecaa263a473f4963 Mon Sep 17 00:00:00 2001 From: Nikolas de Hor Date: Fri, 20 Feb 2026 09:37:42 -0300 Subject: [PATCH 2/2] fix: only apply interim fallback when no tools were used Addresses Codex review: if the model sent interim text then used tools, the interim text should not be used as fallback for the final response. --- nanobot/agent/loop.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nanobot/agent/loop.py b/nanobot/agent/loop.py index d817815..177302e 100644 --- a/nanobot/agent/loop.py +++ b/nanobot/agent/loop.py @@ -245,7 +245,8 @@ class AgentLoop: final_content = None continue # Fall back to interim content if retry produced nothing - if not final_content and interim_content: + # and no tools were used (if tools ran, interim was truly interim) + if not final_content and interim_content and not tools_used: final_content = interim_content break