Timelines & events
Every agent writes an append-only timeline of everything it does, and your UI can replay it or live-follow it. This page teaches the timeline's shape and vocabulary; the field-by-field specification lives in the Event schema reference.
The timeline
The timeline is the record of one entity's life — messages, tool calls, results, lifecycle markers — as numbered events. The number is called seq, and it is strict: 0-based, counting up by exactly one, with no gaps. The first event of every entity is entity_spawned at seq 0.
Gaplessness is a feature you can lean on. A reader holding events 0–41 knows it has missed nothing; a reader that sees 43 after 41 knows something is wrong and can say so. "Did I miss anything?" is always answerable — which is what makes timelines safe to build UIs on.
Each event carries its entity's URL, its seq, a timestamp, a type, and a typed payload. There are fifteen event types in all; you'll meet them fastest by scenario.
A wake, on the timeline
One wake writes a bracketed group of events. Here is our researcher handling a request and delegating to a summarizer:
seq 4 run_started wake source: message
seq 5 message role: user — "look into the history of tea"
seq 6 tool_call spawn_agent → summarizer
seq 7 tool_result "Spawned summarizer as /t/default/a/summarizer/01j…"
seq 8 child_spawned childId: /t/default/a/summarizer/01j…
seq 9 tool_call wait
seq 10 tool_result "Turn yielded."
seq 11 run_finished outcome: success, token usage
Every wake opens with run_started and closes with run_finished. In between: message events for finalized conversation turns, tool_call/tool_result pairs for every tool the model used, and reasoning for finalized thinking (display-only — it is never fed back to the model).
Family and lifecycle activity appears the same way: child_spawned and child_finished bracket a sub-agent's life from the parent's point of view; control records an outside intervention; error records a failure; archived marks the end of an episode. All fifteen types are cataloged in the reference.
Token deltas: the live channel
While the model is mid-sentence, the finalized message event doesn't exist yet. Token deltas are the live, streaming fragments of a message while the model is still producing it. They ride a sibling stream next to the timeline, they are droppable, and they are always superseded by the finalized event.
Roughly: deltas are for pixels, events are for truth. A UI renders deltas as they arrive for that live-typing feel; the moment the finalized event lands on the timeline, all buffered deltas for it are discarded. If a delta is lost in transit nothing is harmed — the finalized event always contains the complete text.
Snapshots: joining late
A conversation that has run for weeks might hold thousands of events. A snapshot (state_snapshot) is a periodic event that carries the entity's complete state at that point, so a UI can join at the latest snapshot and fold forward from there instead of replaying from event 0. Snapshots occupy a normal seq slot like any other event, so the "no gaps" arithmetic keeps working across them.
History, never control flow
One rule shapes everything above. Roughly: the platform writes the timeline for you and your UI — it never reads the timeline to decide what to do next. The agent's own durable state is the single source of truth; the timeline is a one-way copy of what happened.
If the platform both wrote history and read it back to make decisions, there would be two sources of truth — the agent's state and its history — and every disagreement between them would be a bug with no right answer. teaspill keeps the arrow one-way: state lives with the agent object, and the timeline can always be regenerated forward from what agents do, never the reverse. This is also what keeps reading cheap and safe: a timeline is append-only and cacheable, and no reader — however slow, however many — can affect a running agent.
Only the entity's own handler assigns seq — the harness produces unnumbered events, and the one writer numbers them at commit time through an outbox. The outbox appends to the history store via an idempotent producer keyed on (entityId, seq), so a crash-and-retry between "appended" and "confirmed" replays as a harmless duplicate, never a double write or a gap. Readers in turn deduplicate by the seq embedded in each event, so even a rare server-side duplicate record collapses cleanly.
Next steps
The timeline is one of two things you read from teaspill. The other — the live registry of every entity — is next: Projections & the catalog.