On iOS, watch scene phase. When the scene leaves the foreground, cancel a long respond if you must, then write the checkpoint. Apple's default on a tool error or a cancel is to revert the transcript. If you want to keep partial work, set transcriptErrorHandlingPolicy to preserveTranscript, then put the transcript into a good state yourself. That policy is in WWDC26 session 242.
import SwiftUI
import BackgroundTasks
@main
struct WorkflowApp: App {
@Environment(\.scenePhase) private var scenePhase
@State private var engine = WorkflowEngine()
var body: some Scene {
WindowGroup {
WorkflowView(engine: engine)
}
.onChange(of: scenePhase) { _, phase in
if phase != .active {
Task { await engine.persistAndPause() }
}
}
}
}
func registerBackgroundRefresh() {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "dev.edgefde.workflow", using: nil) { task in
guard let process = task as? BGProcessingTask else { return }
process.expirationHandler = { process.setTaskCompleted(success: false) }
Task {
do {
_ = try await WorkflowEngine.shared.resumeFromDisk()
process.setTaskCompleted(success: true)
} catch {
process.setTaskCompleted(success: false)
}
}
}
}
A BGProcessingTask is a chance to resume, not a promise. iOS may delay or skip it. The user may have to open the app. Say that to stakeholders. On macOS you have more room to keep a process alive, but you should still write the same checkpoint. Do not build two designs.
If you cancel mid-response and you used preserveTranscript, wait until isResponding is false, then save. If you used the default revert, save the last completed step only. Do not save a half sentence as a finished plan.
Read Make several agents agree first, Talk to tools with MCP, and Stop prompt attacks and leaks if the background resume would call a side-effect tool. That tool still needs a gate.
Next, put these parts in a small engine you can ship.
Key concepts
- On leave foreground, cancel a long respond if needed, then save the checkpoint.
preserveTranscriptkeeps partial work. You must repair the transcript yourself.- Register a background processing task if you want a chance to continue.
- iOS background resume is a chance, not a promise.
Takeaways
- Save on the way out.
- Use
preserveTranscriptonly if you will repair the transcript. - Do not save a half sentence as a finished plan.