Skip to main content
Most agents never need this page. The default loop handles streaming, tools, retries, compaction and persistence. Reach for a custom loop when your product needs orchestration the loop does not model, such as routing between models, running a planning pass, or enforcing a state machine.

Hooking without replacing

Events are dicts, so you can observe and react while still passing everything through.
You can also transform or drop events, or inject your own around them.

Replacing the loop

fn is an async generator that yields events. Accept **kw so new keyword arguments do not break your loop as the SDK grows.

The kit

Session

Session is the part worth understanding, because it is what makes a run survivable.
add_user writes to disk before the model is called, so a dropped connection never loses what the person said. rollback removes only the assistant tail, so a failed turn does not corrupt the transcript.

The provider interface

stream yields UI events, bare strings for text deltas, then exactly one Turn carrying the assistant content, stop reason and token counts. Adding a new provider means one file that conforms to this protocol. The message shape is Anthropic’s, which is the richest superset across vendors. Each provider translates from it to its own wire format.

What you give up

Writing your own loop means owning the behavior the default one provides: retries with backoff, compaction before overflow, one recovery replay on a context error, checkpointing between tool batches, heartbeats during long tool runs, cost logging, and unwinding cleanly on cancellation. Start by wrapping default_loop and intercepting what you need, then replace it only when wrapping stops being enough.

Next

Interface

Branding, themes, the explore menu and the example gallery.