Skip to content
Technical Analysis
High Quality87 / 100
Evidence31/35Judgment22/25Structure16/20Usefulness18/20
Batched State Saving Is Not a Rollback Transaction: Three Boundaries of Recovery Evidence
Research

Batched State Saving Is Not a Rollback Transaction: Three Boundaries of Recovery Evidence

Local state saving and external work facts require different evidence and recovery responsibilities.

2026-10-23中文 →

Batched State Saving Is Not a Rollback Transaction: Three Boundaries of Recovery Evidence ​

In the isolated experiment, an exception inside a batching block propagated, yet the save hook still received the modified value 9. The meaning of a context manager comes from its methods; syntax does not confer rollback guarantees. Recovery has another boundary as well: a complete local record can still leave the outcome of an external action unknown.

What was saved after the exception ​

The same-day analysis extracted unchanged methods from OpenHands at revision 60192ed54db73ac658ac1a07462916126c32d3a0. It executed seventeen scenarios: five saving controls, eight action-matching or constructed-history controls, and four restore-identity controls. Pinned conversation-state source

This was an internal method probe. Saving used a spy that recorded calls, while events and models were minimal doubles. The full SDK was not installed or run. A recorded save invocation does not establish power-loss durability of an actual file.

Saving scenarioInternal experimental observationSupported interpretation
Ordinary assignments of 1 and 2Save receives 1 and 2Two ordinary updates call save twice
Assignments of 1 and 2 in one batchSave receives only 2Saving is deferred and coalesced
Set 9, then raise a controlled exceptionError propagates; save receives 9These methods do not exhibit exception rollback
Nested batchingSave receives only 2The outermost exit coalesces saving
Unchanged batchNo save callNo mutation means no save is introduced

In the source, __setattr__ marks the state dirty while save depth is positive. __exit__ calls save when depth reaches zero, without undoing assignments based on the exception type. The experiment separates that method behavior from an imagined transaction that reverses all changes on error. It does not test storage-write atomicity.

Identity consistency does not reveal the effect ​

The four identity controls expose a different boundary. A requested conversation ID that differs from the persisted ID is rejected before rebuilding the event view. Without a supplied agent, the persisted agent is retained. With a supplied agent, a verification double is called before replacement; its rejection propagates. These controls test branching and call order, not the real agent-verification implementation, expired approval, revoked permissions or credential rotation.

The eight matching controls ask whether an action has a corresponding visible event. An action alone remains unmatched. A correctly linked observation, user rejection, or error linked by tool-call ID clears the unmatched item. An unrelated observation does not; an event without executable content is excluded from the pending list.

The crucial pair deliberately constructs two hidden histories. In one, the action never executed. In the other, the external effect occurred but its observation was lost. Their visible logs contain the same action event, so the matcher returns the same unmatched result. These are not two real external executions or observed incidents. They demonstrate that the supplied information cannot distinguish the histories.

Our interpretation is that a pending list can identify work needing examination, but cannot turn a missing observation into proof that an effect is absent. Retry decisions require an application idempotency or reconciliation protocol. No automatic-replay recommendation follows from this experiment. Identity compatibility, current authority and external effects are separate evidence questions.

What another recovery unit adds to the comparison ​

Microsoft Agent Framework documents recovery in terms of workflows and executor identities, requiring matching topology and stable identities after reconstruction. Its checkpoint documentation also treats checkpoint storage as trusted private infrastructure. Restricted type decoding does not make arbitrary untrusted data safe.

The official Python 1.13.0 checkpoint upgrade guide states that a pending-request checkpoint and a response-entry checkpoint can share an iteration count. Recovery selection should use lineage or the storage API rather than simply maximizing that count. The execution-model documentation describes message routing and advancement at synchronized superstep boundaries.

These are source-reported contracts; Microsoft was not executed in this experiment. They contrast a different recovery unit with conversation-state methods, rather than establish a performance or reliability ranking. Both contracts need a separate account of what local persistence records and what additional information establishes external effects. Documentation snapshots are not assumed to match the other framework's pinned release revision.

Evidence and sources ​

The experimental observations are internal evidence from this research process, not independent third-party reproduction. Pinned source supplies primary implementation material. The conversation-persistence guide and Microsoft documents supply their respective public contract statements. Our interpretation is not presented as a capability those documents already promise.

The isolated experiment date is 2026-10-23. Its complete record identifies the save spy, model doubles, minimal event classes, verification spy and replacement lock; lock fairness was not tested. Successful execution does not establish general validity. Publication and citability do not validate recovery guarantees.

Guarantees still outside the experiment ​

The complete caller may coordinate through event logs, tools or storage. The experiment did not test process crashes, disk durability, secret encryption, real branch rebuilding, restored current authority or real external actions. It does not establish that the entire framework lacks those safeguards.

The next useful evidence would show how the complete caller reconciles an action whose effect may have occurred without a persisted observation, and what storage guarantees connect base state with events. The present bounded result is narrower: these methods provide save batching and identity checks; they do not themselves roll back body exceptions or receive enough information to distinguish external histories behind identical local logs.