From 7c3e5706d8968a6741b68c93574238c19368a345 Mon Sep 17 00:00:00 2001 From: bsgdigital Date: Fri, 24 Apr 2026 07:24:47 -0700 Subject: [PATCH] fix(bedrock): Bedrock-aware _rebuild_anthropic_client helper on interrupt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three interrupt-recovery sites in run_agent.py rebuilt self._anthropic_client with build_anthropic_client(self._anthropic_api_key, ...) unconditionally. When provider=bedrock + api_mode=anthropic_messages (AnthropicBedrock SDK path), self._anthropic_api_key is the sentinel 'aws-sdk' — build_anthropic_client doesn't accept that and the rebuild either crashed or produced a non-functional client. Extract a _rebuild_anthropic_client() helper that dispatches to build_anthropic_bedrock_client(region) when provider='bedrock', falling back to build_anthropic_client() for native Anthropic and other anthropic_messages providers (MiniMax, Kimi, Alibaba, etc.). Three inline rebuild sites now call the helper. Partial salvage of #14680 by @bsgdigital — only the _rebuild_anthropic_client helper. The normalize_model_name Bedrock-prefix piece was subsumed by #14664, and the aux client aws_sdk branch was subsumed by #14770 (both in the same salvage PR as this commit). --- run_agent.py | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/run_agent.py b/run_agent.py index 0322e018c9..4911e4899e 100644 --- a/run_agent.py +++ b/run_agent.py @@ -5432,6 +5432,26 @@ class AIAgent: self._try_refresh_anthropic_client_credentials() return self._anthropic_client.messages.create(**api_kwargs) + def _rebuild_anthropic_client(self) -> None: + """Rebuild the Anthropic client after an interrupt or stale call. + + Handles both direct Anthropic and Bedrock-hosted Anthropic models + correctly — rebuilding with the Bedrock SDK when provider is bedrock, + rather than always falling back to build_anthropic_client() which + requires a direct Anthropic API key. + """ + if getattr(self, "provider", None) == "bedrock": + from agent.anthropic_adapter import build_anthropic_bedrock_client + region = getattr(self, "_bedrock_region", "us-east-1") or "us-east-1" + self._anthropic_client = build_anthropic_bedrock_client(region) + else: + from agent.anthropic_adapter import build_anthropic_client + self._anthropic_client = build_anthropic_client( + self._anthropic_api_key, + getattr(self, "_anthropic_base_url", None), + timeout=get_provider_request_timeout(self.provider, self.model), + ) + def _interruptible_api_call(self, api_kwargs: dict): """ Run the API call in a background thread so the main conversation loop @@ -5539,14 +5559,8 @@ class AIAgent: ) try: if self.api_mode == "anthropic_messages": - from agent.anthropic_adapter import build_anthropic_client - self._anthropic_client.close() - self._anthropic_client = build_anthropic_client( - self._anthropic_api_key, - getattr(self, "_anthropic_base_url", None), - timeout=get_provider_request_timeout(self.provider, self.model), - ) + self._rebuild_anthropic_client() else: rc = request_client_holder.get("client") if rc is not None: @@ -5571,14 +5585,8 @@ class AIAgent: # seed future retries. try: if self.api_mode == "anthropic_messages": - from agent.anthropic_adapter import build_anthropic_client - self._anthropic_client.close() - self._anthropic_client = build_anthropic_client( - self._anthropic_api_key, - getattr(self, "_anthropic_base_url", None), - timeout=get_provider_request_timeout(self.provider, self.model), - ) + self._rebuild_anthropic_client() else: request_client = request_client_holder.get("client") if request_client is not None: @@ -6428,14 +6436,8 @@ class AIAgent: if self._interrupt_requested: try: if self.api_mode == "anthropic_messages": - from agent.anthropic_adapter import build_anthropic_client - self._anthropic_client.close() - self._anthropic_client = build_anthropic_client( - self._anthropic_api_key, - getattr(self, "_anthropic_base_url", None), - timeout=get_provider_request_timeout(self.provider, self.model), - ) + self._rebuild_anthropic_client() else: request_client = request_client_holder.get("client") if request_client is not None: