From c9bea3f13e09c782a97196ae356fda67827da9d0 Mon Sep 17 00:00:00 2001 From: Toshal Kumbhar Date: Sat, 4 Jul 2026 05:33:12 +0530 Subject: [PATCH 1/3] fix(core): ensure tool_choice maps to structured object for AWS Bedrock compliance --- strix/core/execution.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/strix/core/execution.py b/strix/core/execution.py index 06dc3ddf5..f252e3008 100644 --- a/strix/core/execution.py +++ b/strix/core/execution.py @@ -349,6 +349,15 @@ async def _run_cycle( # noqa: PLR0912, PLR0915 while True: try: await coordinator.mark_running(agent_id) + + # --- PRODUCTION FIX FOR AWS BEDROCK TOOL_CHOICE COMPLIANCE --- + if hasattr(run_config, "extra_body") and isinstance(run_config.extra_body, dict): + if "tool_choice" in run_config.extra_body: + run_config.extra_body["tool_choice"] = {"type": "auto"} + elif hasattr(run_config, "tool_choice") and (run_config.tool_choice == "auto" or isinstance(run_config.tool_choice, str)): + run_config.tool_choice = {"type": "auto"} + # ------------------------------------------------------------- + stream = Runner.run_streamed( agent, input=input_data, From c336d9ce2803ac66d9fb4bcc99af25870c0170b6 Mon Sep 17 00:00:00 2001 From: Toshal Kumbhar Date: Sun, 5 Jul 2026 05:56:00 +0530 Subject: [PATCH 2/3] fix: resolve workspace materialization race on Windows Docker Desktop (#671) --- strix/runtime/backends.py | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/strix/runtime/backends.py b/strix/runtime/backends.py index d7eba3357..93efa2752 100644 --- a/strix/runtime/backends.py +++ b/strix/runtime/backends.py @@ -3,6 +3,8 @@ from __future__ import annotations import logging +import os +import sys from collections.abc import Awaitable, Callable from typing import TYPE_CHECKING, Any @@ -47,10 +49,41 @@ async def _docker_backend( from strix.runtime.docker_client import StrixDockerSandboxClient + # Handle Issue #671 Edge Cases: Concurrency limits for Windows Docker Desktop + concurrency_limits = None + try: + from agents.sandbox.artifacts import SandboxConcurrencyLimits + + # Default to 1 (serial) on Windows to prevent race conditions. + # Leave as None (SDK default) for Linux/WSL2 where execution is fast enough. + default_limit = 1 if sys.platform == "win32" else None + + # Check for env var override (e.g., STRIX_DOCKER_CONCURRENCY=4) + limit_val = os.environ.get("STRIX_DOCKER_CONCURRENCY", default_limit) + + if limit_val is not None: + limit = int(limit_val) + concurrency_limits = SandboxConcurrencyLimits( + manifest_entries=limit, + local_dir_files=limit + ) + logger.debug(f"Applied SandboxConcurrencyLimits: {limit}") + + except ImportError: + logger.warning("Could not import SandboxConcurrencyLimits from SDK. Proceeding with defaults.") + except ValueError: + logger.warning("STRIX_DOCKER_CONCURRENCY must be a valid integer. Proceeding with defaults.") + client = StrixDockerSandboxClient(docker.from_env()) client.strix_bind_mounts = bind_mounts or [] options = DockerSandboxClientOptions(image=image, exposed_ports=exposed_ports) - session = await client.create(options=options, manifest=manifest) + + # Pass concurrency_limits if successfully configured + create_kwargs = {"options": options, "manifest": manifest} + if concurrency_limits is not None: + create_kwargs["concurrency_limits"] = concurrency_limits + + session = await client.create(**create_kwargs) await session.start() return client, session @@ -90,4 +123,4 @@ def register_backend(name: str, backend: SandboxBackend) -> None: def supported_backends() -> list[str]: - return sorted(_BACKENDS) + return sorted(_BACKENDS) \ No newline at end of file From 722eefba2f68ec2adce9d1166940a6a9cf573e95 Mon Sep 17 00:00:00 2001 From: Toshal Kumbhar Date: Sun, 5 Jul 2026 06:21:52 +0530 Subject: [PATCH 3/3] fix: resolve workspace materialization race on Windows Docker Desktop (#671) --- strix/runtime/backends.py | 50 +++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/strix/runtime/backends.py b/strix/runtime/backends.py index 93efa2752..7d8a464ea 100644 --- a/strix/runtime/backends.py +++ b/strix/runtime/backends.py @@ -49,42 +49,46 @@ async def _docker_backend( from strix.runtime.docker_client import StrixDockerSandboxClient - # Handle Issue #671 Edge Cases: Concurrency limits for Windows Docker Desktop + # Handle Issue #671 Edge Cases concurrency_limits = None - try: - from agents.sandbox.artifacts import SandboxConcurrencyLimits - - # Default to 1 (serial) on Windows to prevent race conditions. - # Leave as None (SDK default) for Linux/WSL2 where execution is fast enough. - default_limit = 1 if sys.platform == "win32" else None - - # Check for env var override (e.g., STRIX_DOCKER_CONCURRENCY=4) - limit_val = os.environ.get("STRIX_DOCKER_CONCURRENCY", default_limit) - - if limit_val is not None: - limit = int(limit_val) + default_limit = 1 if sys.platform == "win32" else None + limit_val = os.environ.get("STRIX_DOCKER_CONCURRENCY", default_limit) + + if limit_val is not None: + try: + # Prevents <= 0 limits breaking the SDK validation + limit = max(1, int(limit_val)) + + # Try primary import path, fallback if SDK changes + try: + from agents.sandbox.artifacts import SandboxConcurrencyLimits + except ImportError: + from agents.sandbox import SandboxConcurrencyLimits + concurrency_limits = SandboxConcurrencyLimits( manifest_entries=limit, local_dir_files=limit ) logger.debug(f"Applied SandboxConcurrencyLimits: {limit}") - - except ImportError: - logger.warning("Could not import SandboxConcurrencyLimits from SDK. Proceeding with defaults.") - except ValueError: - logger.warning("STRIX_DOCKER_CONCURRENCY must be a valid integer. Proceeding with defaults.") + except (ImportError, ValueError) as e: + if sys.platform == "win32" and limit_val == 1: + # Fail loudly on Windows to avoid silent race condition + raise RuntimeError("Failed to import SandboxConcurrencyLimits required for Windows execution.") from e + logger.warning("Invalid STRIX_DOCKER_CONCURRENCY or import failed. Proceeding with defaults.") client = StrixDockerSandboxClient(docker.from_env()) client.strix_bind_mounts = bind_mounts or [] options = DockerSandboxClientOptions(image=image, exposed_ports=exposed_ports) - # Pass concurrency_limits if successfully configured - create_kwargs = {"options": options, "manifest": manifest} + # Create the session (without concurrency_limits keyword) + session = await client.create(options=options, manifest=manifest) + + # Pass concurrency_limits where the session is actually started/materialized + start_kwargs = {} if concurrency_limits is not None: - create_kwargs["concurrency_limits"] = concurrency_limits + start_kwargs["concurrency_limits"] = concurrency_limits - session = await client.create(**create_kwargs) - await session.start() + await session.start(**start_kwargs) return client, session