MODULE 06 · LESSON 6.5
Resume sessions and handle lost work
Restore harness plans while reporting work that cannot be recovered.
Lesson 37 of 86 · FabrCore 2.0
Overview
Harness snapshots hold todos, modes and delegation records; chat messages remain in the history provider. In-flight tasks are live process objects and cannot simply be serialized back into execution. Restoring a plan and replaying a side effect are different operations.
A snapshot preserves state, not live tasks
A harness snapshot can retain todos, mode and delegation records across turns. Chat history is retained separately by its provider. A live Task object executing an external request cannot be recreated merely by deserializing a snapshot. After process loss, a delegation can be recorded as lost even while an external system already completed its effect.
Reconcile before replaying an uncertain effect
An interrupted “close request” operation is not equivalent to an operation that was never sent. Inspect its stable operation identifier or authoritative business record before retrying. A recovery response should name lost work and the next decision needed, rather than re-run every unfinished todo automatically. Durable storage is required to test process restart recovery meaningfully.
Resume a saved investigation
- Run through the wrapper and leave session persistence enabled. Inspect remaining todos before ending the turn.
- After enabling persistent Orleans storage, restart between turns and verify restored plan/session state. Include DescribeLostDelegations in the user-visible recovery report.
- Choose an explicit retry/reconciliation path for Lost work. For uncertain external effects, query the recorded operation/result before attempting anything again.
public override async Task<AgentMessage> OnMessage(AgentMessage message)
{
SetStatusMessage("Planning...");
var run = await harness.RunAsync(message);
var text = run.Text;
// Delegations stranded by a restart — see references/durability.md.
if (harness.DescribeLostDelegations() is { } lost)
{
text += $"{Environment.NewLine}{Environment.NewLine}{lost}";
}
var remaining = await harness.GetRemainingTodosAsync();
if (remaining.Count > 0)
{
text += $"{Environment.NewLine}{Environment.NewLine}Not completed within the iteration budget:{Environment.NewLine}"
+ string.Join(Environment.NewLine, remaining.Select(item => $"- {item.Title}"));
}
SetStatusMessage(string.Empty);
var response = message.Response();
response.Message = text;
return response;
}
Restart between turns, then during work
- With durable storage configured, complete one fixture step, leave another todo open and restart between turns. Read the restored todo/session state and continue without recreating the finished step.
- In a separate controlled run, interrupt a delegation while its result is outstanding. Inspect lost-delegation reporting after recovery.
- Check the external fixture's operation record before any retry. If it already completed, reconcile the result into the investigation; if its outcome is unknown, retain that uncertainty visibly.
You have tested state restoration and uncertain-execution handling separately. A restored todo list does not establish that all background work resumed safely.
If the result is different
Standalone process restart loses the backing state. Changing a thread ID selects a different snapshot; clearing/resetting/evicting affects different parts of the lifecycle.
Go deeper
Explore the related documentation.