Skip to content

Python: get_latest timestamp ties return a checkpoint chosen by save order, can restore stale state #8513

Description

Description

InMemoryCheckpointStorage.get_latest picks max() by timestamp alone. Checkpoints at the same superstep boundary legitimately carry identical timestamps (the WorkflowCheckpoint docstring on iteration_count says so explicitly), and datetime.now() resolution means even distinct boundaries can collide. When timestamps tie, max() returns whichever checkpoint the dict iterates first, so the result depends on save order:

storage = InMemoryCheckpointStorage()
parent = WorkflowCheckpoint(workflow_name="w", graph_signature_hash="h", checkpoint_id="parent", timestamp=ts)
child = WorkflowCheckpoint(workflow_name="w", graph_signature_hash="h", checkpoint_id="child", timestamp=ts, previous_checkpoint_id="parent")
# save parent then child  -> get_latest returns parent
# save child then parent  -> get_latest returns child

A workflow resuming via get_latest can therefore restore the stale checkpoint, with no error anywhere.

FileCheckpointStorage.get_latest has the same timestamp-only max(); it happens to mask the issue via list ordering, but the same identical-timestamp input can pick the wrong one.

The checkpoint docstring itself says ordering is defined by the previous_checkpoint_id lineage chain, not timestamps alone.

Expected behavior

Ties on timestamp resolve through the lineage chain: the checkpoint that no other checkpoint supersedes is the latest, regardless of save order.

Environment

agent-framework python main (astryx-era clone from this week), Python 3.12

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    pythonUsage: [Issues, PRs], Target: PythontriageUsage: [Issues], Target: All issues that still need to be triaged

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions