Stateframe uses a portable local JSON file named task.ledger.json. It is not an official standard or protocol; it is an experimental file format for preserving task state across long-running agent sessions.
The file contains three top-level keys:
{
"task": {},
"commits": [],
"state_items": []
}taskdescribes the durable objective.commitsrecord append-only changes to state.state_itemscontain discrete facts, decisions, questions, blockers, rejected options, artifacts, and next steps.
Each state change is recorded by a new commit. A commit points to its parent commit, making the ledger easy to inspect and replay.
State items are not deleted in normal operation. If state becomes obsolete, a later item can supersede it and the older item can be marked deprecated.
Candidate state. Useful, but not yet trusted as canonical.
Trusted state. Locked items are the only state items included in the locked-state section of handoff packets.
Historical state that has been superseded or should no longer guide the agent.
Agents are good at producing candidate summaries, but not every candidate deserves to guide future work. Handoffs use locked state so a human or trusted workflow can decide what becomes canonical.
This keeps handoff packets compact and reduces the chance that speculative or low-quality extraction becomes future instruction.
Long-running agent work often fails by retrying approaches that were already ruled out. A rejected_option preserves:
- What was considered
- Why it was rejected
- When that rejection entered the ledger
This is especially useful for deferred features, scope cuts, integrations, and implementation paths that look tempting to a fresh agent.
Raw transcripts are noisy, large, and often contain irrelevant conversation. The ledger stores extracted state, not chat history.
If a system wants to retain transcripts, it should store them separately and reference them from commits. The default file-first workflow does not store raw transcripts in task.ledger.json.