Agent skill
tokio-async-code-review
Reviews tokio async runtime usage for task management, sync primitives, channel patterns, and runtime configuration. Use when reviewing Rust code that uses tokio, async/await patterns, spawn, channels, or async synchronization. Also covers tokio-util, tower, and hyper integration patterns.
Install this agent skill to your Project
npx add-skill https://github.com/existential-birds/beagle/tree/main/plugins/beagle-rust/skills/tokio-async-code-review
SKILL.md
Tokio Async Code Review
Review Workflow
- Check Cargo.toml — Note tokio feature flags (
full,rt-multi-thread,macros,sync, etc.). Missing features cause confusing compile errors. - Check runtime setup — Is
#[tokio::main]or manual runtime construction used? Multi-thread vs current-thread? - Scan for blocking — Search for
std::fs,std::net,std::thread::sleep, CPU-heavy loops in async functions. - Check channel usage — Match channel type to communication pattern (mpsc, broadcast, oneshot, watch).
- Check sync primitives — Verify correct mutex type, proper guard lifetimes, no deadlock potential.
Output Format
Report findings as:
[FILE:LINE] ISSUE_TITLE
Severity: Critical | Major | Minor | Informational
Description of the issue and why it matters.
Quick Reference
| Issue Type | Reference |
|---|---|
| Task spawning, JoinHandle, structured concurrency | references/task-management.md |
| Mutex, RwLock, Semaphore, Notify, Barrier | references/sync-primitives.md |
| mpsc, broadcast, oneshot, watch channel patterns | references/channels.md |
Review Checklist
Runtime Configuration
- Tokio features in Cargo.toml match actual usage
- Runtime flavor matches workload (
multi_threadfor I/O-bound,current_threadfor simpler cases) -
#[tokio::test]used for async tests (not manual runtime construction) - Worker thread count configured appropriately for production
Task Management
-
spawnreturn values (JoinHandle) are tracked, not silently dropped -
spawn_blockingused for CPU-heavy or synchronous I/O operations - Tasks respect cancellation (via
CancellationToken,select!, or shutdown channels) -
JoinError(task panic or cancellation) is handled, not just unwrapped -
tokio::select!branches are cancellation-safe
Sync Primitives
-
tokio::sync::Mutexused when lock is held across.await;std::sync::Mutexfor short non-async sections - No mutex guard held across await points (deadlock risk)
-
Semaphoreused for limiting concurrent operations (not ad-hoc counters) -
RwLockused when read-heavy workload (many readers, infrequent writes) -
Notifyused for simple signaling (not channel overhead)
Channels
- Channel type matches pattern: mpsc for back-pressure, broadcast for fan-out, oneshot for request-response, watch for latest-value
- Bounded channels have appropriate capacity (not too small = deadlock, not too large = memory)
-
SendError/RecvErrorhandled (indicates other side dropped) - Broadcast
Laggederrors handled (receiver fell behind) - Channel senders dropped when done to signal completion to receivers
Timer and Sleep
-
tokio::time::sleepused instead ofstd::thread::sleep -
tokio::time::timeoutwraps operations that could hang -
tokio::time::intervalused correctly (.tick().awaitfor periodic work)
Severity Calibration
Critical
- Blocking I/O (
std::fs::read,std::net::TcpStream) in async context withoutspawn_blocking - Mutex guard held across
.awaitpoint (deadlock potential) std::thread::sleepin async function (blocks runtime thread)- Unbounded channel where back-pressure is needed (OOM risk)
Major
JoinHandlesilently dropped (lost errors, zombie tasks)- Missing
select!cancellation safety consideration - Wrong mutex type (std vs tokio) for the use case
- Missing timeout on network/external operations
Minor
tokio::spawnfor trivially small async blocks (overhead > benefit)- Overly large channel buffer without justification
- Manual runtime construction where
#[tokio::main]suffices std::sync::Mutexwhere contention is high enough to benefit from tokio's async mutex
Informational
- Suggestions to use
tokio-utilutilities (e.g.,CancellationToken) - Tower middleware patterns for service composition
- Structured concurrency with
JoinSet
Valid Patterns (Do NOT Flag)
std::sync::Mutexfor short critical sections — tokio docs recommend this when no.awaitis inside the locktokio::spawnwithout explicit join — Valid for background tasks with proper shutdown signaling- Unbuffered channel capacity of 1 — Valid for synchronization barriers
#[tokio::main(flavor = "current_thread")]in simple binaries — Not every app needs multi-thread runtimeclone()onArc<T>beforespawn— Required for moving into tasks, not unnecessary cloning- Large broadcast channel capacity — Valid when lagged errors are expensive (event sourcing)
Before Submitting Findings
Load and follow beagle-rust:review-verification-protocol before reporting any issue.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
review-python
Comprehensive Python/FastAPI backend code review with optional parallel agents
review-verification-protocol
Mandatory verification steps for all code reviews to reduce false positives. Load this skill before reporting ANY code review findings.
sqlalchemy-code-review
Reviews SQLAlchemy code for session management, relationships, N+1 queries, and migration patterns. Use when reviewing SQLAlchemy 2.0 code, checking session lifecycle, relationship() usage, or Alembic migrations.
fastapi-code-review
Reviews FastAPI code for routing patterns, dependency injection, validation, and async handlers. Use when reviewing FastAPI apps, checking APIRouter setup, Depends() usage, or response models.
pytest-code-review
Reviews pytest test code for async patterns, fixtures, parametrize, and mocking. Use when reviewing test_*.py files, checking async test functions, fixture usage, or mock patterns.
postgres-code-review
Reviews PostgreSQL code for indexing strategies, JSONB operations, connection pooling, and transaction safety. Use when reviewing SQL queries, database schemas, JSONB usage, or connection management.
Didn't find tool you were looking for?