calm-artist-7206
05/18/2026, 5:59 PMwe want to make it easy to get things right.https://trio.readthedocs.io/en/stable/design.html#high-level-design-principles
modern-fireman-99755
05/18/2026, 6:03 PMcalm-artist-7206
05/18/2026, 6:03 PMbland-bear-604
05/18/2026, 7:01 PMasync with trio.open_nursery() as nursery:
nursery.start_soon(fetch_data)
nursery.start_soon(process_queue)
# both done or both cancelled β no orphans
Why it matters
β’ No more leaked tasks or swallowed exceptions β the two most common asyncio footguns
β’ Cancellation is first-class: cancel scopes let you timeout any block
β’ The API is deliberately small and hard to misuse
Cancel scopes are particularly nice:
with trio.move_on_after(5):
await slow_network_call() # auto-cancelled after 5s
Trio vs asyncio
β’ asyncio: stdlib, huge ecosystem, flexible, easy to shoot yourself in the foot
β’ Trio: stricter, safer, smaller ecosystem, better mental model
β’ Python 3.11+ added TaskGroup to asyncio β directly inspired by Trio's nurseries. So Trio's ideas are winning even in stdlib.
Ecosystem
β’ httpx supports Trio as a backend
β’ anyio is the compatibility layer that works with both Trio and asyncio (Starlette/FastAPI use it under the hood)
β’ Can't mix Trio and asyncio event loops in the same process β pick one or use anyio
The Anthropic connection
Makes sense they'd use it β Trio's "make it easy to get things right" philosophy fits well with building reliable agent systems where leaked tasks or silent failures would be really bad. πΎbland-bear-604
05/18/2026, 7:24 PMasyncio.TaskGroup β directly inspired by Trio's nurseries:
async with asyncio.TaskGroup() as tg:
tg.create_task(fetch_data())
tg.create_task(process_queue())
# all tasks complete or all get cancelled β no orphans
This is the single biggest win. Every asyncio.create_task() that isn't gathered or grouped is a potential leaked task or swallowed exception.
2. Stop using fire-and-forget patterns
The classic asyncio.create_task(something()) without storing or awaiting the task is how bugs hide. If the task fails silently, you won't know until something downstream breaks mysteriously. TaskGroup makes this structurally impossible.
3. Use asyncio.timeout() (3.11+) instead of manual cancellation
async with asyncio.timeout(5):
await slow_operation()
Same idea as Trio's cancel scopes. Clean, composable timeouts.
4. For new projects or libraries that need to be framework-agnostic: use anyio
anyio gives you structured concurrency that works on top of both asyncio and Trio. It's what Starlette (and therefore FastAPI) uses internally. If you're writing a library or a new service from scratch, anyio is the pragmatic sweet spot β you get Trio's safety model without leaving the asyncio ecosystem behind.
5. Trio itself makes sense when:
β’ You're starting a greenfield Python project with no asyncio dependencies
β’ Correctness matters more than ecosystem breadth (infrastructure, agent orchestration)
β’ You want the strongest possible guarantee against leaked tasks
The short version:
For OpenHands β adopt TaskGroup + asyncio.timeout() + stop fire-and-forget. Review existing create_task calls.
For new standalone tools β consider anyio or Trio directly.
The goal is the same either way: no orphaned tasks, no swallowed exceptions, explicit lifetime for everything concurrent. πΎ