Debug aiohttp with Smello
aiohttp is a popular async HTTP client and server framework for Python. Smello patches aiohttp.ClientSession._request to capture all outgoing requests made through aiohttp's client.
Setup
Then run your script with smello run:
All requests made via aiohttp.ClientSession are captured automatically. No code changes needed.
Example script:
basic_aiohttp.py
Scenario: debugging connection pooling issues
You're making many concurrent requests with aiohttp and some are failing with ClientConnectionError. Is the target server throttling you? Are connections being reused properly?
async with aiohttp.ClientSession() as session:
tasks = [session.get(f"https://api.example.com/items/{i}") for i in range(100)]
responses = await asyncio.gather(*tasks, return_exceptions=True)
# Some responses are ClientConnectionError: which ones?
Debug in the dashboard
Open the Smello dashboard. You can see every request that succeeded and every one that failed:
- Filter by status code: quickly find the 5xx or failed requests among hundreds.
- Timing patterns: sort by duration to spot requests that hung before failing.
- Host filter: if your code calls multiple services, filter to just
api.example.comto focus.
Debug with an AI agent
If you use Claude Code or another AI coding tool, the /smello-debugger skill can query captured events and cross-reference them with your source code. Install it once:
Then ask your agent:
The skill is also invoked automatically when your agent recognizes a debugging question, but calling /smello-debugger explicitly gives the best results. See AI Agent Skills for compatible tools.
Tips
- Session methods: Smello captures requests regardless of which session method you use (
get,post,put,request, etc.): they all flow through the same patched method. - Connector limits: If you're debugging throughput, pair the Smello timeline with aiohttp's
TCPConnector(limit=...)setting to understand how connection limits affect your request patterns. - Response body reading: Smello captures the response body at the transport level. Even if your code doesn't call
resp.json()orresp.text(), the body is still visible in the dashboard.
Next step: follow the getting started guide for installation, configuration, and more.