Problem
Running ruff check on the codebase reveals 8 instances of ASYNC230 — blocking file I/O operations (open()) inside async FastAPI route handlers. The primary offenders are in routes.py and debug_routes.py.
In an async FastAPI/Uvicorn application, synchronous open() calls block the entire event loop while the OS services the I/O request. Under any meaningful load, this will cause latency spikes and request queuing across all concurrent users of the API.
Affected Files
src/agentevals/routes.py — multiple async handlers using open() directly
-
src/agentevals/debug_routes.py — similar pattern
Fix
Replace blocking open() calls with async equivalents. Two options:
Option A — aiofiles (recommended, minimal diff):
import aiofiles
async def my_handler():
async with aiofiles.open("path/to/file", "r") as f:
content = await f.read()
Option B — asyncio.to_thread() (stdlib, no new dependency):
import asyncio
async def my_handler():
content = await asyncio.to_thread(_read_file_sync, "path/to/file")
Add aiofiles to the project dependencies if choosing Option A.
Problem
Running
ruff checkon the codebase reveals 8 instances ofASYNC230— blocking file I/O operations (open()) insideasyncFastAPI route handlers. The primary offenders are inroutes.pyanddebug_routes.py.In an async FastAPI/Uvicorn application, synchronous
open()calls block the entire event loop while the OS services the I/O request. Under any meaningful load, this will cause latency spikes and request queuing across all concurrent users of the API.Affected Files
src/agentevals/routes.py— multiple async handlers usingopen()directlysrc/agentevals/debug_routes.py— similar patternFix
Replace blocking
open()calls with async equivalents. Two options:Option A —
aiofiles(recommended, minimal diff):Option B —
asyncio.to_thread()(stdlib, no new dependency):Add
aiofilesto the project dependencies if choosing Option A.