Reconstruct the message state by loading the stored messages as a list of BaseMessage objects (using convert_to_messages if stored as dicts) and then resuming the graph with the same thread_id in the config, which will restore the full checkpoint state including messages.
LangGraph's checkpointing system is designed for exactly this purpose. If you have previously stored the conversation using a persistent checkpointer (e.g., PostgresSaver), you can simply resume with the same thread_id. The graph will load the last checkpoint, including all messages. If you need to reconstruct from raw message data (e.g., from a database that doesn't use LangGraph checkpoints), you can create a list of BaseMessage objects using convert_to_messages from stored dictionaries, then start a new graph invocation with that initial state. For the latter approach, you must ensure the message IDs are preserved or generated consistently to avoid duplication.
For production, always use LangGraph's built-in checkpointer with a persistent store. It automatically handles serialization, versioning, and ID preservation, and is more efficient than manual reconstruction.