Durable agents
A teaspill agent keeps working — and keeps its memory — across process restarts, deploys, and crashes. This page explains the two ideas that make that true: durable execution and the wake model.
The problem: your agent's process can die mid-run
An AI agent is a long chain of work: a model call, a few tool calls, another model call, maybe a sub-agent or two. Any link in that chain can take minutes. If the process dies partway — a crash, a deploy, a laptop lid closing — an ordinary agent loses everything in flight. Retrying from the top is worse than losing it: side effects run twice, sub-agents get duplicated, and the conversation forgets what already happened.
teaspill removes this problem at the platform layer, so you never write recovery code in an agent.
Durable execution
Durable execution is a way of running code as a journal of recorded steps: if the process dies, the run resumes from the last completed step instead of starting over. teaspill gets this from Restate, an open-source durable-execution engine that runs as part of the stack — you don't need to learn it to use teaspill.
Every model call and every tool call an agent makes is one of those recorded steps. After a crash, the run replays its journal, skips everything already done, and continues from where it stopped — same conversation, same partial results, no repeated side effects.
One agent, one object
Each agent is a single named object that processes one thing at a time. Two messages sent to the same agent never race each other: they are handled in order, one turn after another. That one-at-a-time rule sounds restrictive, but it is what makes an agent's recorded history — its timeline — trustworthy: there is exactly one order of events, and everyone who reads it sees the same one.
The wake model
A wake is one turn of an agent's life. Something arrives — a message or a finished child — and the agent wakes: it does some work (maybe calls the model, maybe spawns children), then goes back to sleep. Agents never block or poll. Anything an agent is waiting for arrives as a later wake.
The part that surprises people: nothing in a wake ever waits synchronously. When our researcher agent spawns a summarizer child, the spawn returns the child's id immediately — never its result. The researcher then ends its turn, and the summarizer's result arrives later as a child_finished message that starts a new wake:
wake 1 spawn_agent("summarizer", …) → returns the child's id, immediately
wait() → the turn ends; the researcher sleeps
… minutes pass; the process may restart; nothing is lost …
wake 2 child_finished arrives with the summary → the researcher finishes
The wait call is not a pause — it returns immediately and ends the turn. Sleeping agents cost nothing and hold nothing open; the platform re-wakes them when there is something to do.
What this buys you
- Agents survive deploys. Restart your agent service mid-run and in-flight work resumes; sleeping agents don't even notice.
- No polling loops. An agent that is waiting isn't running. There is no "check every five seconds" code anywhere.
- A trustworthy record. Because each agent processes one turn at a time, everything it does lands on its timeline in one definite order that your UI can replay.
Each wake runs as a journaled invocation: every model call and every side-effecting tool call is a recorded step, and replay after a crash skips steps that already completed. Side-effecting tool calls additionally carry an idempotency key built from the agent, the run, and the specific tool call — so even if a step is retried at a coarser granularity, the effect (spawning a child, running a command) happens exactly once. Timers and inter-agent messages are durable too: a wake that was due before a crash is still due after it.
Next steps
Two pages complete this picture: Restate in five minutes explains the machinery underneath, and Lifecycle & control covers what happens between wakes — idling, archiving, and coming back.