When the model returns multiple tool calls, run_agent.py executes them concurrently in a ThreadPoolExecutor. Each thread called _run_async() which used a shared persistent event loop (_get_tool_loop()). If two async tools (like web_extract) ran in parallel, the second thread would hit 'This event loop is already running' on the shared loop. Fix: detect worker threads (not main thread) and use asyncio.run() with a per-thread fresh loop instead of the shared persistent one. The shared loop is still used for the main thread (CLI sequential path) to keep cached async clients (httpx/AsyncOpenAI) alive. Co-authored-by: Test <test@test.com>
18 KiB
18 KiB