Conversation events
After sending a message, a personal agent reads the company's ordered event log. The cursor is opaque: save it exactly, send it back without interpreting it, and advance it only after handling the page. A company can repeat events after a reconnect, so delivery to the application must be de-duplicated by event ID.
Python exposes ConversationClient.read_events() for one page and
ConversationClient.events() as an async iterator. TypeScript exposes the
aligned readEvents() and events() APIs. The iterator:
- uses a caller-selected long-poll duration, normally 30 seconds;
- immediately drains another page when
has_moreis true; - preserves company event order and treats cursors as opaque strings;
- suppresses repeated event IDs after reconnects;
- bounds its retained de-duplication set and fails closed at the limit;
- invokes the host's cursor-expiry callback before one recovery read from the beginning; and
- stops after a closed page has no backlog.
The cursor-expiry callback is important. Restarting from the beginning can recover retained events, but it cannot reconstruct events the company already deleted. The host should tell the person that part of the conversation may be missing.
Session Tokens, DPoP proofs, pairwise identity, and the saved cursor remain in
the trusted host. A model or UI receives only the event fields it needs. A
company that streams can be read over SSE instead, with reconnects and
display-only text-delta frames: see conversation streaming.
Run the Pydantic AI example or the Agent Runtimes example. See upstream conversation event reads.