How to implement message editing and response regeneration features with langchain or langgraph?

I’m working on a chatbot application and currently using PostgreSQL async storage to manage conversation threads. The basic chat functionality works perfectly fine so far.

However, I’m stuck trying to figure out how to add two important features that users expect from modern chat interfaces:

  1. The ability to edit previously sent messages
  2. A regenerate button to get alternative responses

I’ve seen these features in popular AI chat applications and want to implement something similar in my project. Has anyone successfully built this kind of functionality? What’s the best approach to handle message editing and response regeneration when using persistent thread storage?

Any guidance or code examples would be really helpful!

totally get it! editing can be a pain, but saving old messages in db helps. for regeneratin responses, just hit your model again with the same context. play around with temperature for varied results, works like a charm! good luck!

LangGraph’s checkpointing is exactly what you need here. Save conversation states anywhere, rollback when things go wrong. Create custom nodes for edit/regen and the graph handles all the state management for you.

I built something similar in my chatbot project last year. For message editing, I used a versioning system - each message gets a version number and keeps track of the original content. When someone edits a message, I just add a new record with the next version number but keep the original for auditing. Works great for maintaining conversation history. For response regeneration, I save the conversation state right before the AI generates its response. When regenerating, I roll back to that exact state and call the language model again. The trick is keeping that exact context from before the original response. One thing I’d recommend - store multiple response variants in your database so users can cycle through them without hitting the API every time. Saves money and makes everything faster.

I handle this exact problem differently in my production systems.

Treat this as workflow orchestration, not just database ops. You’re managing state transitions, API calls, and data persistence all at once.

When users edit messages, you’re triggering a cascade - update the message, invalidate responses, recalculate context windows, potentially regenerate multiple downstream responses. Same with regeneration - you’re managing rollbacks, API retries, and response caching.

I built this using Latenode since it handles orchestration logic visually. Set up workflows that automatically manage message versioning, trigger LangChain calls with proper context, handle API failures gracefully, and update PostgreSQL storage atomically.

You can see the entire flow - from user action to database update - in one visual workflow. No more scattered code trying to coordinate async operations.

For response variants, I cache them in the workflow and only hit the language model when cache is empty. Latenode makes adding conditional logic and loops dead simple.

Check it out: https://latenode.com

Been wrestling with this exact issue in my current project. What worked for me was a branch-based approach instead of simple versioning. When a user edits a message, I create a new conversation branch from that point and mark the old one inactive. You keep multiple conversation paths without losing data integrity. For regeneration, I store the exact prompt config and model parameters with each response in PostgreSQL. This lets me reproduce the same conditions when regenerating while still allowing natural variation. The key insight? Both features are basically creating alternate timelines in your conversation history. Your async storage should handle this naturally if you design the schema for branching conversations rather than linear threads.