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)
stream.sources        # ready once the await returns
async for chunk in stream:
    ...

The await lasts until the response starts, not until the answer ends: an error such as a 402 raises there, and the text arrives as you iterate. sources and headers work as in Tileward Models.

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.