Guardrails AIguardrails-ai 0.11.0 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
27 small wins to finish your pathNext lesson

AsyncGuard

Lesson 21's stream still blocked the thread it ran on. A desk answering several customers at once wants the awaitable version, and it is the same object with await in front of it.

Example
import asyncio

from guardrails import AsyncGuard
from guardrails_ai.valid_length import ValidLength

desk = AsyncGuard().use(ValidLength(min=1, max=20, on_fail="noop"))
outcome = await desk.validate("Order 8821 is running late and arrives Friday.")

print(outcome.validation_passed)
print(outcome.validated_output)

AsyncGuard is imported from guardrails beside Guard, takes the same validators, and returns the same ValidationOutcome. Everything you learned about on_fail, history and summaries carries over unchanged.

An async model

Example
async def slow_model(**kwargs):
    await asyncio.sleep(0.01)
    return "Order 8821 ships today."


answer = await desk(slow_model, messages=[{"role": "user", "content": "Where is 8821?"}])

print(answer.raw_llm_output)
print(answer.validation_passed)

The callable is the one from lesson 13 with async in front. Guardrails awaits it, which is the only difference in the contract.

Several at once

The stand-in model from lesson 13 is an ordinary synchronous callable, and AsyncGuard awaits whatever it is given. Two lines wrap it, which is the same thing you would do to any client that has no async version.

Example
model = PretendModel()

async def call(**kwargs):
    return model(**kwargs)

async def ask(question):
    answer = await desk(call, messages=[{"role": "user", "content": question}])
    return answer.validation_passed, answer.validated_output

questions = ["Where is order 8821?", "Can I get a refund on 8821?", "hello"]
for passed, text in await asyncio.gather(*(ask(q) for q in questions)):
    print(passed, "|", text)

Three calls in flight together, results in the order you asked. The Performance page recommends AsyncGuard as the first thing to reach for when latency matters, on the grounds that the Guard itself runs in under ten milliseconds and everything slow is either the model or a validator that calls one.

Validators inside a single Guard already run concurrently, whichever class you use. That is why lesson 6 sorted the summaries before printing them.

Try it yourself
  • Give one of the three questions a validator that raises and see what asyncio.gather does with the exception.
  • Time the loop with and without gather using a model that sleeps for a second.
  • Try await on a plain Guard and read the error, so you recognise it later.

You understood something today that you didn't yesterday.