{"repo":"NousResearch/hermes-agent","public_id":"46592","display_label":"Bedrock converse_stream boto3 version compatibility guard","summary":"These issues and PRs address an AttributeError raised when using converse_stream with a boto3 version older than 1.34.59, and add a version check to guard against it.","subsystem":null,"counts":{"members":4,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":2,"merged_prs":1,"attempt_prs":1},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":46633},"resolution":{"state":"partially_resolved","by":"pr-46633"},"freshness":{"state":"verified","last_verified_at":"2026-06-15T12:25:18+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_PARTIAL","link_density":0.3933333333333333},"fix_edges":[{"issue_number":46592,"pr_number":46633,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true}],"members":[{"kind":"issue","number":46592,"title":"bedrock: `converse_stream` AttributeError when boto3 < 1.34.59 installed system-wide","url":null,"state":"closed"},{"kind":"issue","number":46888,"title":"bedrock: `converse_stream` AttributeError when boto3 < 1.34.59 installed system-wide","url":null,"state":"closed"},{"kind":"pr","number":46608,"title":"fix(bedrock): check boto3 version >= 1.34.59 before using converse_stream","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#46633","number":46633}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":46633,"title":"fix(bedrock): check boto3 version before Converse streaming","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["agent/bedrock_adapter.py","tests/agent/test_bedrock_adapter.py"],"fix_hunks":[{"file":"agent/bedrock_adapter.py","hunks":["@@ -58,17 +58,34 @@\n _bedrock_control_client_cache: Dict[str, Any] = {}\n \n \n+_MIN_BOTO3_VERSION = (1, 34, 59)\n+\n+\n def _require_boto3():\n-    \"\"\"Import boto3, raising a clear error if not installed.\"\"\"\n+    \"\"\"Import boto3, raising a clear error if not installed or too old.\"\"\"\n     try:\n         import boto3\n-        return boto3\n     except ImportError:\n         raise ImportError(\n             \"The 'boto3' package is required for the AWS Bedrock provider. \"\n             \"Install it with: pip install boto3\\n\"\n             \"Or install Hermes with Bedrock support: pip install -e '.[bedrock]'\"\n         )\n+    # converse() / converse_stream() were added in boto3 1.34.59.\n+    # When Hermes is installed editable into system Python, the system boto3\n+    # (e.g. Ubuntu 24.04 ships 1.34.46) may take precedence over the venv\n+    # version pinned in pyproject.toml.\n+    try:\n+        version = tuple(int(x) for x in boto3.__version__.split(\".\")[:3])\n+    except (AttributeError, ValueError):\n+        return boto3  # can't parse — don't block on version check\n+    if version < _MIN_BOTO3_VERSION:\n+        raise RuntimeError(\n+            f\"boto3 {boto3.__version__} does not support converse_stream \"\n+            f\"(minimum 1.34.59 required). Upgrade with: \"\n+            f\"pip install --upgrade boto3\"\n+        )\n+    return boto3\n \n \n def _get_bedrock_runtime_client(region: str):"]},{"file":"tests/agent/test_bedrock_adapter.py","hunks":["@@ -1663,3 +1663,52 @@ def test_falls_back_to_converse_on_streaming_denial(self):\n         assert result.choices[0].message.content == \"hi\"\n         # Not a stale connection — client stays cached.\n         assert _bedrock_runtime_client_cache.get(\"us-east-1\") is client\n+\n+\n+# ---------------------------------------------------------------------------\n+# boto3 version check\n+# ---------------------------------------------------------------------------\n+\n+\n+class TestRequireBoto3VersionCheck:\n+    \"\"\"Test that _require_boto3() rejects boto3 versions older than 1.34.59.\"\"\"\n+\n+    def test_raises_runtime_error_when_boto3_too_old(self):\n+        \"\"\"boto3 < 1.34.59 should raise RuntimeError with upgrade instructions.\"\"\"\n+        from agent.bedrock_adapter import _require_boto3\n+\n+        fake_boto3 = MagicMock()\n+        fake_boto3.__version__ = \"1.34.46\"\n+        with patch.dict(\"sys.modules\", {\"boto3\": fake_boto3}):\n+            with pytest.raises(RuntimeError, match=\"does not support converse_stream\"):\n+                _require_boto3()\n+\n+    def test_accepts_boto3_at_minimum_version(self):\n+        \"\"\"boto3 == 1.34.59 should be accepted.\"\"\"\n+        from agent.bedrock_adapter import _require_boto3\n+\n+        fake_boto3 = MagicMock()\n+        fake_boto3.__version__ = \"1.34.59\"\n+        with patch.dict(\"sys.modules\", {\"boto3\": fake_boto3}):\n+            result = _require_boto3()\n+            assert result is fake_boto3\n+\n+    def test_accepts_newer_boto3(self):\n+        \"\"\"boto3 > 1.34.59 should be accepted.\"\"\"\n+        from agent.bedrock_adapter import _require_boto3\n+\n+        fake_boto3 = MagicMock()\n+        fake_boto3.__version__ = \"1.42.89\"\n+        with patch.dict(\"sys.modules\", {\"boto3\": fake_boto3}):\n+            result = _require_boto3()\n+            assert result is fake_boto3\n+\n+    def test_accepts_boto3_with_unparseable_version(self):\n+        \"\"\"If version string can't be parsed, don't block on version check.\"\"\"\n+        from agent.bedrock_adapter import _require_boto3\n+\n+        fake_boto3 = MagicMock()\n+        fake_boto3.__version__ = \"dev\"\n+        with patch.dict(\"sys.modules\", {\"boto3\": fake_boto3}):\n+            result = _require_boto3()\n+            assert result is fake_boto3\n"]}]}],"trust":{"default_tier":"verified","includes_suggested":false}}