Hooking without replacing
Events are dicts, so you can observe and react while still passing everything through.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 wrappingdefault_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.