From 43fbac8bc5d1966e10c7370527c560f2a29ab21c Mon Sep 17 00:00:00 2001 From: Rachit Mehta Date: Mon, 11 May 2026 12:36:16 -0400 Subject: [PATCH 1/2] fix: swarm bug --- src/strands/multiagent/swarm.py | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/strands/multiagent/swarm.py b/src/strands/multiagent/swarm.py index f5731a371..1a2e9130a 100644 --- a/src/strands/multiagent/swarm.py +++ b/src/strands/multiagent/swarm.py @@ -17,6 +17,7 @@ import copy import json import logging +import sys import time from collections.abc import AsyncIterator, Callable, Mapping from dataclasses import dataclass, field @@ -439,28 +440,22 @@ async def _stream_with_timeout( Exception: If total execution time exceeds timeout """ if timeout is None: - # No timeout - just pass through async for event in async_generator: yield event + elif sys.version_info >= (3, 11): + try: + async with asyncio.timeout(timeout): + async for event in async_generator: + yield event + except asyncio.TimeoutError as err: + raise Exception(timeout_message) from err else: - # Track start time for total timeout start_time = asyncio.get_event_loop().time() - - while True: - # Calculate remaining time from total timeout budget + async for event in async_generator: elapsed = asyncio.get_event_loop().time() - start_time - remaining = timeout - elapsed - - if remaining <= 0: + if elapsed > timeout: raise Exception(timeout_message) - - try: - event = await asyncio.wait_for(async_generator.__anext__(), timeout=remaining) - yield event - except StopAsyncIteration: - break - except asyncio.TimeoutError as err: - raise Exception(timeout_message) from err + yield event def _setup_swarm(self, nodes: list[Agent]) -> None: """Initialize swarm configuration.""" From ca773039023999f66c87e2eb5cc5858443ec4c52 Mon Sep 17 00:00:00 2001 From: Rachit Mehta Date: Tue, 12 May 2026 08:49:00 -0400 Subject: [PATCH 2/2] address comments --- src/strands/multiagent/swarm.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/strands/multiagent/swarm.py b/src/strands/multiagent/swarm.py index 1a2e9130a..b0f9f4a86 100644 --- a/src/strands/multiagent/swarm.py +++ b/src/strands/multiagent/swarm.py @@ -450,9 +450,12 @@ async def _stream_with_timeout( except asyncio.TimeoutError as err: raise Exception(timeout_message) from err else: - start_time = asyncio.get_event_loop().time() + # Python 3.10 fallback: timeout is only checked between yielded events. + # A generator that hangs mid-await won't be interrupted until the next event. + # Remove once Python 3.10 support is dropped (Oct 2026). + start_time = asyncio.get_running_loop().time() async for event in async_generator: - elapsed = asyncio.get_event_loop().time() - start_time + elapsed = asyncio.get_running_loop().time() - start_time if elapsed > timeout: raise Exception(timeout_message) yield event