SOLWYN
Guides

Async Usage

Use AsyncSolwyn for async applications — context managers, event loops, and provider examples

import asyncio
import os
from openai import AsyncOpenAI
from solwyn import AsyncSolwyn

async def main():
    async with AsyncSolwyn(
        AsyncOpenAI(),
        api_key=os.environ["SOLWYN_API_KEY"],
    ) as client:
        response = await client.chat.completions.create(
            model="gpt-4o",
            messages=[{"role": "user", "content": "Hello!"}],
        )
        print(response.choices[0].message.content)

asyncio.run(main())

AsyncSolwyn provides the same API as Solwyn but with async/await support. Use it when your application runs in an async event loop (FastAPI, aiohttp, etc.).

Context manager

Always use async with to ensure resources are properly cleaned up:

async with AsyncSolwyn(
    AsyncOpenAI(),
    api_key=os.environ["SOLWYN_API_KEY"],
) as client:
    # client is ready -- reporter is started
    response = await client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Hello!"}],
    )
# client.close() is called automatically

The async with block calls __aenter__() which starts the background metadata reporter, and __aexit__() which flushes pending reports and closes HTTP connections.

If you cannot use a context manager, call await client.close() explicitly:

client = AsyncSolwyn(
    AsyncOpenAI(),
    api_key=os.environ["SOLWYN_API_KEY"],
)

try:
    response = await client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Hello!"}],
    )
finally:
    await client.close()

Per-provider async

The async surface mirrors the sync wrapper for every provider: pass the provider's async client to AsyncSolwyn() and call it the same way you would synchronously. Each provider page carries its own async example and any provider-specific notes:

Event loop notes

  • AsyncSolwyn must be used within a running async event loop.
  • The background metadata reporter uses asyncio.create_task() to send batches without blocking your LLM calls.
  • Do not mix Solwyn (sync) and AsyncSolwyn (async) in the same event loop. Use Solwyn for synchronous code and AsyncSolwyn for async code.
  • asyncio.run(main()) creates and manages the event loop. If you are using a framework like FastAPI, the framework manages the event loop for you -- just use async with in your lifespan or dependency injection.

Concurrent calls

AsyncSolwyn supports concurrent LLM calls with asyncio.gather:

import asyncio
import os
from openai import AsyncOpenAI
from solwyn import AsyncSolwyn

async def main():
    async with AsyncSolwyn(
        AsyncOpenAI(),
        api_key=os.environ["SOLWYN_API_KEY"],
    ) as client:
        tasks = [
            client.chat.completions.create(
                model="gpt-4o",
                messages=[{"role": "user", "content": f"Count to {i}"}],
            )
            for i in range(1, 4)
        ]
        responses = await asyncio.gather(*tasks)

        for r in responses:
            print(r.choices[0].message.content)

asyncio.run(main())

Each concurrent call independently checks budget, reports metadata, and updates the circuit breaker.

On this page