fix(warmup): pre-import the agents SDK to avoid a thread-race crash - #1173
fix(warmup): pre-import the agents SDK to avoid a thread-race crash#1173samirhvbr wants to merge 1 commit into
Conversation
The background import warm-up thread imports strix.core.runner (and thus the
openai-agents SDK) while, on the scan path, the main thread independently
imports the same package via strix.report -> strix.report.dedupe ->
`from agents.models.interface import ModelTracing`.
openai-agents has an internal import cycle (agents.agent_output <->
agents.agent). A single thread resolves it, but when two threads import the
`agents` package concurrently, CPython's per-module import locks +
deadlock-avoidance can hand one thread a partially initialized module, crashing
the run with:
ImportError: cannot import name 'AgentOutputSchemaBase' from partially
initialized module 'agents.agent_output' (most likely due to a circular
import)
--version/--help never hit it because they don't import agents; it only shows
up on a real scan, which is why it looked intermittent.
Import the `agents` package once, synchronously, on the caller's thread before
the daemon warm-up thread starts, so it is fully initialized before any
concurrent import. Also start the warm-up after parse_arguments() so
--version/--help/argparse errors exit before the now-partly-synchronous
warm-up runs; it still overlaps the Docker checks and image pull that follow.
Adds tests/test_warmup.py asserting start_import_warmup() leaves `agents` in
sys.modules synchronously.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Greptile SummaryThe PR synchronously imports the Agents SDK before starting background import warmup, closing the reported concurrent-import race. It also moves warmup after argument parsing so early-exit CLI paths remain lightweight and adds a fresh-interpreter regression test.
Confidence Score: 5/5The PR appears safe to merge, with no concrete changed-code failure identified. The synchronous SDK import completes before the background thread starts, argument parsing does not independently reach the SDK, and the added test isolates the intended pre-import behavior. Important Files Changed
Reviews (1): Last reviewed commit: "fix(warmup): pre-import the agents SDK t..." | Re-trigger Greptile |
There was a problem hiding this comment.
Pull request overview
Fixes an intermittent startup crash caused by concurrent imports of the openai-agents (agents) SDK by ensuring the SDK is imported once, synchronously, before the background warm-up thread begins. This reduces the likelihood of CPython returning a partially-initialized module during circular-import resolution on multi-threaded import paths.
Changes:
- Pre-import
agentssynchronously insidestart_import_warmup()before spawning the daemon warm-up thread. - Move the warm-up start to after
parse_arguments()so--help/--versionand argparse errors exit before doing any heavy warm-up work. - Add a subprocess-based regression test to assert that
start_import_warmup(modules=())still leavesagentsinsys.modules(proving the synchronous pre-import ran).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
strix/llm/warmup.py |
Adds a synchronous pre-import of the thread-unsafe agents SDK ahead of the daemon import warm-up thread. |
strix/interface/main.py |
Reorders startup so argument parsing happens before warm-up starts, avoiding warm-up on early-exit CLI flows. |
tests/test_warmup.py |
Adds a fresh-interpreter test that verifies agents is synchronously imported by start_import_warmup(). |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| _preimport_thread_unsafe_sdk() | ||
| _thread = threading.Thread( | ||
| target=_warm, args=(modules,), name="strix-import-warmup", daemon=True | ||
| ) |
Problem
Real scans intermittently crash at startup with:
--version/--helpnever hit it — the tell that it only happens on the scan path.Root cause
start_import_warmup()runs a daemon thread that importsstrix.core.runner→ theopenai-agentsSDK. On the scan path the main thread independently imports thesame package via
strix.report→strix.report.dedupe→from agents.models.interface import ModelTracing.openai-agentshas an internal import cycle (agents.agent_output↔agents.agent,reached through
agents/__init__.py→sandbox→run_config→lifecycle→agent). A single thread resolves the cycle, but when two threads import theagentspackage concurrently, CPython's per-module import locks + deadlock-avoidancecan let one thread proceed with a partially initialized module — producing the
ImportError above. It is scheduler-dependent, which matches the intermittent reports.
Fix
Import the
agentspackage once, synchronously, on the caller's thread before thedaemon warm-up thread starts, so it is fully in
sys.modulesbefore any concurrentimport.
start_import_warmup()is also moved to just afterparse_arguments()so--version/--help/argparse errors exit before the (now partly synchronous) warm-upruns; the warm-up still overlaps the Docker checks and image pull that follow.
Test
Adds
tests/test_warmup.py: in a fresh interpreter, with an empty warm set so thedaemon thread imports nothing,
start_import_warmup()must leaveagentsinsys.modules— proving the synchronous pre-import ran.ruff format --check,ruff check, and the new test pass locally.Original traceback
🤖 Generated with Claude Code