Schemas and Protocols: Turning an LLM Workflow into a Stateful System
Beyond the Chat Window · Article 2 of 8
The previous article argued that project-scale LLM work benefits from separating conversational history from canonical task state. A persistent data object can give the project stable identities, explicit relations, current values, and an execution state that does not have to be reconstructed from the transcript every time the model acts.
That solves one problem and exposes another. A persistent JSON file can still be a terrible system. The model can overwrite a value that should have been versioned, change one object without updating its dependents, silently reinterpret a field, or mark an artifact complete before the corresponding output actually exists. The data may remain syntactically valid while the project becomes semantically inconsistent.
The next distinction is therefore as important as the first: the schema defines what the state can contain; the protocol defines how that state is allowed to change. Together, they turn structured storage into something closer to a governed runtime.
Representation is not transition semantics
A schema gives names and shapes to objects. It can specify that an article has an ID, a status, a set of dependencies, a target reader state, and a list of unresolved issues. It can distinguish a claim from an example or a decision from an open question. Those distinctions are valuable because they reduce ambiguity and make the state addressable.
But a schema does not answer questions such as these: May a published article revert to drafted? What must happen when a canonical term is renamed? Can a dependency be removed without checking downstream artifacts? When should a section count as committed? What should happen if the model discovers that the schema itself is missing an important type? Those are transition questions. They require contracts over mutation.
For this series, the protocol evolved into an explicit cycle: read the relevant state, interpret the requested operation, identify affected objects, propose changes, validate them against invariants, persist the new state, update derivative artifacts, and record the change. The point is not bureaucratic ceremony. The point is to ensure that “we changed the project” means more than “the model said in chat that it would remember something differently from now on.” Consider a simple invariant: an article should not be marked publication_ready while it still has an unresolved blocking issue. JSON will happily represent that invalid combination. The protocol is what says the combination is unacceptable. Likewise, if a terminology change affects several article plans, the protocol can require propagation to dependent objects before the change is considered complete.
This is the first place where the method starts to resemble conventional software architecture. The state space may contain many representable configurations, but only some are valid. Invariants define the subset the workflow is allowed to commit.
Mutation needs boundaries
Once a workflow spans multiple files and derivative artifacts, commit boundaries become practical rather than theoretical. Imagine that the model drafts a section, writes the text file, updates the manifest, and records provenance.
If the process stops halfway through, the system can end up with a mismatched state: perhaps the prose exists but the manifest still says pending, or the manifest says complete even though the file write failed.
A protocol can treat a unit of work transactionally. A section is not committed merely because some prose was generated. It becomes committed only when the artifact exists, the state metadata has been updated, required provenance has been recorded, and validation passes. If interruption happens before that boundary, the workflow returns to the previous valid checkpoint. If it happens after the boundary, the next run can move forward.
This discipline matters more as tasks become larger. It is also one reason a persistent state file should not be confused with a scratchpad. A scratchpad is allowed to be messy. Canonical state needs rules about authority, completeness, and recovery.
The production of this series provided an unexpectedly good example. During the first attempt at drafting, I introduced a rule that Articles 2 through 5 would each inherit “one precise result” from the preceding article. That sounded tidy, but it was not justified by the argument. A later article might need several earlier results, and those results might come from more than one predecessor. I stopped the process and corrected the rule.
A weak workflow would simply leave the correction in the transcript and continue. A stronger workflow changes the protocol itself. The continuity contract was rewritten so that inheritance is necessity-driven: a later article may use as many prior results as its argument requires, while restating only enough for independent readability. The correction was also stored as a durable decision. The project no longer depended on remembering which conversational sentence overruled which previous one. That episode shows what governance buys us. The model can be wrong; the protocol does not make inference infallible. What it does is provide a place where a correction can become authoritative and inspectable.
The protocol has to govern its own evolution There is a recursive problem here. If the schema and protocol are fixed forever, they will eventually become obstacles in an open-ended project. If they can change arbitrarily, the system can drift.
The solution is to make structural change itself a governed operation. A nontrivial schema change should record why it is needed, which objects are affected, whether existing state requires backfill, whether the change is provisional or stable, and what compatibility consequences follow. The same is true for protocol changes: a new rule should have a rationale and a scope.
This series changed in exactly that way. It began with a data model for five article topics. When I reframed the series as an instructive argument, the schema acquired reader assumptions, target beliefs, and argument moves. When more granularity was needed, the model gained premises, warrants, objections, and examples. When the first prose pipeline failed, the protocol acquired a composition layer with an orchestrator and specialized revision roles. When I asked for adversarial editorial review, the protocol changed again so that two independent revision agents would submit competing paragraph-level proposals to a strict referee. Those changes are not evidence that the original schema was badly designed. They are evidence that the task revealed structure as it developed. The protocol's job is to let that structure become formal without losing control of the project.
The result is a hybrid of flexibility and constraint. The LLM can infer that a new distinction matters; the persistent system can give that distinction an identity; the protocol can decide how it becomes authoritative. This is much stronger than asking the model to “be consistent” across a long conversation.
From prompting to a lightweight runtime
At this point, the workflow contains several components with recognizably computational roles. The schema provides a state representation. The protocol supplies transition semantics. Invariants define valid states. Commit rules define durable progress. Change records preserve history. Validation checks whether a proposed state can be accepted.
None of this turns the model into a deterministic program. The model remains probabilistic and semantic. It can misunderstand an instruction, propose a poor change, or write bad prose - as the first draft of this series demonstrated rather clearly. The point is not to eliminate judgment; it is to stop making judgment carry responsibilities that can be externalized.
A useful phrase for this architecture is a lightweight runtime contract. The LLM does the work that benefits from interpretation and generation, but it acts inside a persistent environment that records what exists, what may change, what has changed, and what counts as complete.
That runtime contract enables the next major step. Once progress is representable and mutations are commit-able, one user-level task can be decomposed into many model-level operations without losing continuity. A long artifact can be built section by section. A process can stop and resume. A late correction can invalidate only the affected units rather than the entire project.
The practical consequence is that model output limits stop being the natural boundary of the work. The next article turns to that execution layer: manifests, checkpoints, resumability, and the separation between the size of a task and the size of any one completion.