async-await-checker

Automatically applies when writing Python functions that call async operations. Ensures proper async/await pattern usage (not asyncio.run) to prevent event loop errors.

16 stars

Best use case

async-await-checker is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Automatically applies when writing Python functions that call async operations. Ensures proper async/await pattern usage (not asyncio.run) to prevent event loop errors.

Teams using async-await-checker should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/async-await-checker/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/development/async-await-checker/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/async-await-checker/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How async-await-checker Compares

Feature / Agentasync-await-checkerStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Automatically applies when writing Python functions that call async operations. Ensures proper async/await pattern usage (not asyncio.run) to prevent event loop errors.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Async/Await Pattern Enforcer

When you are writing or modifying Python functions that:
- Call any function with `async def`
- Work with async I/O operations (database, HTTP, file I/O)
- Need to run in an async context (FastAPI, async frameworks)

**Always apply these patterns:**

## ✅ Correct Pattern

```python
# Helper function
async def fetch_user_data(user_id: str) -> dict:
    """Fetch user data from database."""
    result = await db.query(user_id)  # ✅ Use await
    return result

# API endpoint (FastAPI)
@app.get("/users/{user_id}")
async def get_user(user_id: str) -> dict:  # ✅ async def
    data = await fetch_user_data(user_id)  # ✅ await
    return data

# Multiple async calls
async def process_order(order_id: str) -> dict:
    # ✅ Run sequentially
    user = await fetch_user(order_id)
    payment = await process_payment(user.id)

    # ✅ Run in parallel with asyncio.gather
    results = await asyncio.gather(
        send_email(user.email),
        update_inventory(order_id),
        log_transaction(payment.id)
    )

    return {"status": "success"}
```

## ❌ Incorrect Pattern (Causes Runtime Errors)

```python
# ❌ Don't do this
def fetch_user_data(user_id: str):
    result = asyncio.run(db.query(user_id))  # ❌ asyncio.run in event loop = error!
    return result

# ❌ Missing async
@app.get("/users/{user_id}")
def get_user(user_id: str):  # ❌ Should be async def
    data = fetch_user_data(user_id)  # ❌ Not awaiting
    return data

# ❌ Blocking in async function
async def process_order(order_id: str):
    time.sleep(5)  # ❌ Blocks event loop! Use asyncio.sleep(5)
    return await fetch_data()
```

## Why This Matters

**Runtime Error:** `asyncio.run()` fails when called from within an already-running event loop.

**Solution:** Always use `async def` + `await` pattern.

**Performance:** Blocking operations in async functions defeat the purpose of async code.

## Common Async Operations

**Database queries:**
```python
async def get_records():
    async with db.session() as session:
        result = await session.execute(query)
        return result.fetchall()
```

**HTTP requests:**
```python
import httpx

async def fetch_api_data(url: str):
    async with httpx.AsyncClient() as client:
        response = await client.get(url)
        return response.json()
```

**File I/O:**
```python
import aiofiles

async def read_file(path: str):
    async with aiofiles.open(path, 'r') as f:
        content = await f.read()
        return content
```

## Error Handling in Async

```python
async def safe_api_call(url: str):
    try:
        async with httpx.AsyncClient() as client:
            response = await client.get(url, timeout=10.0)
            response.raise_for_status()
            return response.json()
    except httpx.TimeoutException:
        raise TimeoutError(f"Request to {url} timed out")
    except httpx.HTTPStatusError as e:
        raise APIError(f"API error: {e.response.status_code}")
```

## Testing Async Code

```python
import pytest

@pytest.mark.asyncio
async def test_fetch_user_data():
    """Test async function"""
    result = await fetch_user_data("user_123")
    assert result["id"] == "user_123"

@pytest.mark.asyncio
async def test_with_mock():
    """Test with mocked async dependency"""
    with patch('module.db.query') as mock_query:
        mock_query.return_value = {"id": "test"}
        result = await fetch_user_data("test")
        assert result["id"] == "test"
```

## ❌ Anti-Patterns

```python
# ❌ Mixing sync and async incorrectly
def sync_function():
    return asyncio.run(async_function())  # Only OK at top level!

# ❌ Not using asyncio.gather for parallel operations
async def slow_version():
    result1 = await operation1()  # Waits
    result2 = await operation2()  # Waits
    result3 = await operation3()  # Waits
    return [result1, result2, result3]

# ✅ Better: parallel execution
async def fast_version():
    results = await asyncio.gather(
        operation1(),
        operation2(),
        operation3()
    )
    return results

# ❌ Forgetting error handling in gather
async def unsafe():
    await asyncio.gather(op1(), op2())  # If op1 fails, op2 continues

# ✅ Better: return exceptions
async def safe():
    results = await asyncio.gather(
        op1(), op2(),
        return_exceptions=True
    )
    for result in results:
        if isinstance(result, Exception):
            handle_error(result)
```

## Best Practices Checklist

- ✅ Use `async def` for any function that awaits
- ✅ Use `await` for all async calls
- ✅ Use `asyncio.gather()` for parallel operations
- ✅ Use `async with` for async context managers
- ✅ Use `asyncio.sleep()` instead of `time.sleep()`
- ✅ Add proper error handling with try/except
- ✅ Use `@pytest.mark.asyncio` for async tests
- ✅ Consider timeouts for external operations
- ✅ Use `return_exceptions=True` in gather when appropriate

## Auto-Apply

When you see code calling async functions, automatically:
1. Make the calling function `async def`
2. Use `await` for async calls
3. Update callers to also be async (chain up)
4. Add `@pytest.mark.asyncio` to tests
5. Replace blocking calls with async equivalents

## Related Skills

- pytest-patterns - For testing async code
- structured-errors - For async error handling
- tool-design-pattern - For async tools

Related Skills

asyncredux-connector-pattern

16
from diegosouzapw/awesome-omni-skill

Implement the Connector pattern for separating smart and dumb widgets. Covers creating StoreConnector widgets, implementing VmFactory and Vm classes, building view-models, and optimizing rebuilds with view-model equality.

Asyncio Programming

16
from diegosouzapw/awesome-omni-skill

Master asynchronous programming with asyncio, async/await, concurrent operations, and async frameworks

asyncio-concurrency-patterns

16
from diegosouzapw/awesome-omni-skill

Complete guide for asyncio concurrency patterns including event loops, coroutines, tasks, futures, async context managers, and performance optimization

asynchronous

16
from diegosouzapw/awesome-omni-skill

Master asynchronous JavaScript patterns including callbacks, promises, async/await, event loop mechanics, and real-world async patterns.

async-runner

16
from diegosouzapw/awesome-omni-skill

Run background agents and bash commands asynchronously for CircleTel development. Use when running dev servers, parallel tests, long builds, or multi-agent research tasks without blocking the main workflow.

async-python-patterns

16
from diegosouzapw/awesome-omni-skill

Master Python asyncio, concurrent programming, and async/await patterns for high-performance applications. Use when building async APIs, concurrent systems, or I/O-bound applications requiring non-blocking operations.

async-programming

16
from diegosouzapw/awesome-omni-skill

Concurrent operations with asyncio and Tokio, focusing on race condition prevention, resource safety, and performance

async-programming-skill

16
from diegosouzapw/awesome-omni-skill

This skill provides async/await patterns and best practices for concurrent programming

async-patterns-guide

16
from diegosouzapw/awesome-omni-skill

Guides users on modern async patterns including native async fn in traits, async closures, and avoiding async-trait when possible. Activates when users work with async code.

async-expert

16
from diegosouzapw/awesome-omni-skill

Expert in asynchronous programming patterns across languages (Python asyncio, JavaScript/TypeScript promises, C# async/await, Rust futures). Use for concurrent programming, event loops, async patterns, error handling, backpressure, cancellation, and performance optimization in async systems.

async-drop

16
from diegosouzapw/awesome-omni-skill

Guide to the AsyncDrop pattern for async cleanup in Rust. Use when working with AsyncDropGuard, implementing AsyncDrop trait, or handling async resource cleanup.

async-await-patterns

16
from diegosouzapw/awesome-omni-skill

Use when writing JavaScript or TypeScript code with asynchronous operations