State ownership in agent products
Reliable agent products begin by deciding which system owns each fact—not by making the reasoning loop more elaborate.
When an Agent grows beyond a demo, a reasonable instinct is to make the loop durable. Persist every message, tool event, plan, partial result, pause, and retry. If the process disconnects, reconstruct everything and continue as if nothing happened.
I used to think this was the path to reliability. In practice, it often creates a second operating system inside the product.
The database begins to mirror the runtime. The frontend builds another reducer to interpret that mirror. Recovery code decides which snapshot is newer. A completed piece of work can exist in one store while the conversation still believes it is running.
The fundamental problem is not durability. It is authority.
One fact, one authority
An Agent product contains several kinds of state that look related but have different lifecycles:
- Conversation preserves what the user and system said.
- The current stream represents an answer still being produced.
- Background work owns execution that must survive the request.
- Artifacts preserve the durable result delivered by that work.
- Domain records own product-specific facts, permissions, and lineage.
Reliability improves when each fact has one authoritative owner. Other surfaces may derive a view of it, but they should not create parallel truths.
If both a message timeline and a custom run snapshot claim to own the current answer, reconnection becomes a merge problem. If both the browser and the worker claim to own task status, refresh becomes a race. If an Artifact is copied into several messages, “which result is current?” becomes surprisingly hard to answer.
The architecture becomes simpler when it can answer a basic question for every piece of state:
If two representations disagree, which one wins?
A request is not a lifecycle
The HTTP request is a transport boundary. It is not automatically the lifecycle of the work.
This distinction matters whenever an Agent submits something slow, expensive, or externally visible. Closing a tab may end the current stream, but it should not make an accepted job disappear. Conversely, cancelling a request should not be mistaken for cancelling work that an external system has already begun.
These events are different:
- the user disconnects;
- the model stops producing the current turn;
- the product asks a background task to cancel;
- the external executor accepts or rejects that cancellation;
- a late result still arrives.
Treating them as one boolean called isRunning is how duplicate work, phantom failures, and lost results enter the product.
Recover the outcome, not every token
Durability does not require replaying the entire internal experience of the Agent.
Some state deserves recovery because it has product consequences: a confirmed user decision, an accepted job, a payment boundary, a completed Artifact, or an unresolved request for human input. Other state can be transient: a partially streamed sentence, an abandoned branch of reasoning, or UI animation state.
A useful recovery contract is narrower:
- the conversation remains coherent;
- accepted work remains discoverable;
- completed results become visible exactly once;
- the user can understand what still needs attention;
- retries do not create a second external effect.
This may not recreate every token that existed before a disconnect. It preserves what the user actually cares about.
Chat explains; Artifacts deliver
Messages are excellent for intent, negotiation, and explanation. They are poor authorities for durable outputs.
An Artifact has its own identity, status, version, provenance, and relationship to the work that created it. A message can reference that Artifact without becoming another copy of it.
This separation removes a large class of interface ambiguity. The conversation can say what happened. The Artifact surface can show the current result. The task system can say whether execution is still active. None of them needs to impersonate the others.
Autonomy lives inside invariants
Clarifying authority does not mean prescribing every path the Agent must take.
The product should own permissions, spending limits, valid output contracts, identity, and externally consequential state. The Agent can own planning, exploration, tool selection, candidate count, and when to change direction.
This is the difference between an invariant and a workflow. An invariant protects the system. A workflow decides the method in advance.
If we persist a fixed sequence of stages and call it an Agent runtime, we have made the control plane more durable without making the Agent more capable.
Observability should follow ownership
Good observability is not a single timeline containing every internal event. It lets us answer questions at the correct authority:
- What did the user ask and confirm?
- Which work was accepted, and by whom?
- What is running, cancelled, failed, or complete?
- Which Artifact was produced from which invocation?
- Which external effect may already have happened?
When those answers come from explicit owners, debugging becomes evidence gathering rather than archaeology across competing snapshots.
Reliability often comes from deletion
It is tempting to answer every failure with another state field, compatibility path, recovery worker, or reducer branch. Sometimes that is necessary. Often it is evidence that two systems believe they own the same fact.
The more useful refactor is frequently subtractive: choose the authority, make other layers derive from it, and delete the parallel control plane.
The durable Agent product is not the one that remembers every internal motion. It is the one that preserves the right outcomes, gives every fact a clear owner, and stays understandable when the network, process, model, or user does something unexpected.


Discussion
Comments
Questions, disagreements, and useful additions are all welcome.