Skip to content

Async

Every method has an awaitable twin on AsyncTileward, with the same names and the same arguments.

from tileward import AsyncTileward

async with AsyncTileward() as tw:
    print(await tw.chat.say("Hello"))

    async for piece in tw.chat.stream("Count to five."):
        print(piece, end="", flush=True)

Outside a context manager, close it yourself:

tw = AsyncTileward()
try:
    ...
finally:
    await tw.aclose()

The whole surface

await tw.models.list()
await tw.models.default()

await tw.chat.say("...")
await tw.chat.completions.create("...", max_tokens=200)

await tw.guard.allows("...", allow=["customer_support"])

await tw.context.remember("...")
await tw.context.recall_text("...")

await tw.documents.ingest_file("handbook.pdf")
await tw.documents.list()

await tw.keys.list()
await tw.account.get()

with_conversation() returns an AsyncTileward view sharing the parent's connections:

thread = tw.with_conversation("thread-42")
await thread.context.recall_text("...")

Streaming

stream() is an async generator — iterate it, do not await it:

async for piece in tw.chat.stream("..."):
    ...

completions.create(stream=True) needs the extra await, because create itself is a coroutine that returns the stream:

stream = await tw.chat.completions.create("...", stream=True)
async for chunk in stream:
    ...

Awaiting the generator instead of iterating it would buffer the whole answer before you saw a token.

Concurrency

One client is safe to share across tasks and pools its connections. Building one per request throws that away.

import asyncio

async with AsyncTileward() as tw:
    answers = await asyncio.gather(*(tw.chat.say(q) for q in questions))

To bring your own pool limits or proxy, pass an httpx.AsyncClient:

AsyncTileward(http_client=my_async_client)

The client will not close a connection it did not open.