From 779619f742ac824a7d223a5837dbc9862e8bc1f6 Mon Sep 17 00:00:00 2001 From: Teknium Date: Sat, 21 Mar 2026 06:33:05 -0700 Subject: [PATCH] fix: remove synthetic error message injection, fix session resume after repeated failures Two changes to the error handler in the agent loop: 1. Remove the 'if not pending_handled' block that injected fake [System error during processing: ...] messages into conversation history. These polluted history, burned tokens on retries, and could violate role alternation by injecting as role=user. The tool_calls error-result path (role=tool) is preserved. 2. Append the error final_response as an assistant message when hitting the iteration limit, so session resume doesn't produce consecutive user messages. --- run_agent.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/run_agent.py b/run_agent.py index 6771b709..e45dc061 100644 --- a/run_agent.py +++ b/run_agent.py @@ -6807,20 +6807,18 @@ class AIAgent: pending_handled = True break - if not pending_handled: - # Error happened before tool processing (e.g. response parsing). - # Choose role to avoid consecutive same-role messages. - last_role = messages[-1].get("role") if messages else None - err_role = "assistant" if last_role == "user" else "user" - sys_err_msg = { - "role": err_role, - "content": f"[System error during processing: {error_msg}]", - } - messages.append(sys_err_msg) - + # Non-tool errors don't need a synthetic message injected. + # The error is already printed to the user (line above), and + # the retry loop continues. Injecting a fake user/assistant + # message pollutes history, burns tokens, and risks violating + # role-alternation invariants. + # If we're near the limit, break to avoid infinite loops if api_call_count >= self.max_iterations - 1: final_response = f"I apologize, but I encountered repeated errors: {error_msg}" + # Append as assistant so the history stays valid for + # session resume (avoids consecutive user messages). + messages.append({"role": "assistant", "content": final_response}) break if final_response is None and (