How to
Persist and Resume Conversations
Give an agent a store and a session ID so conversations survive the process
- Making an agent resumable
- Adding branch, retry, or compaction to a conversation product
Pick a store, then keep the same session ID for the same conversation.
Choose a store
memory := session.NewMemoryStore() // tests and examples
disk, err := sessionfs.New(".pi-sessions") // survives a restartsession.Store is an interface. Implement it over your own database when a file
tree is not where your sessions belong.
Create a durable agent
chat, err := pi.DurableAgent(ctx, "openai-completions/gpt-5-mini", durable.WithStore(store), durable.WithSessionID("support-42"), pi.WithSystemPrompt("Help support agents answer customer questions."),)defer chat.Close()
messages, err := chat.Run(ctx, durable.Text("The customer asked about order order_1234."),).Wait()A durable agent persists the input before the run starts. It persists each produced message before it forwards the event for that message.
Resume after a restart
// Monday, in one process.chat, err := pi.DurableAgent(ctx, spec, durable.WithStore(store), durable.WithSessionID("user-42"),)chat.Run(ctx, durable.Text("My preferred name is Ravi.")).Wait()chat.Close()
// Thursday, in another process. The same ID gives the same conversation.resumed, err := pi.DurableAgent(ctx, spec, durable.WithStore(store), durable.WithSessionID("user-42"),)The store and the session ID define the memory boundary. Nothing else carries over, so the ID is the only thing your application must keep.
Branch and retry
e1 ─── e2 ─── e3 (refund reply) abandoned, still in the store └──── e4 (replacement reply) ← leaf after Branch(ctx, checkpoint)checkpoint := chat.LeafID()
chat.Run(ctx, durable.Text("Draft a refund reply.")).Wait()
err = chat.Branch(ctx, checkpoint)
chat.Run(ctx, durable.Text("Draft a replacement shipment reply.")).Wait()
entries, err := chat.Entries(ctx) // both paths are still hereroots := session.Tree(entries)A branch moves the leaf pointer to an earlier entry. The next run grows a sibling path, and the abandoned path stays in the store.
Compact when the context outgrows the window
err = chat.Compact(ctx, durable.KeepTurns(1), durable.CompactPrompt("Summarize the older turns for support handoff."),)Compaction appends a summary entry and removes nothing. The transcript tree still keeps the full history, so a branch to an earlier entry returns the uncompacted path.
Next: sessions.