A Postgres Backend for a LangGraph Booking Agent

Le brief IA que les pros lisent chaque soir
Les 7 actus IA du jour, décryptées en 5 min. Gratuit.
Inclus dès l'inscription : notre sélection des meilleurs guides & comparatifs IA.
Choisis ton rythme
Gratuit · Pas de spam · Désabonnement en 1 clic
The reservation engine built on LangGraph now relies on a Postgres database while maintaining a conversation state managed by a checkpointer. Only two steps in the flow—proposal generation and confirmation—interact with the database; the rest resides in the agent's state. The startup automatically chooses between memory and Postgres based on the configuration, enabling multi-interface usage.
Two nodes access the data, the state persists between turns
In the reservation flow, access to storage is limited to two steps. The node responsible for generating proposals reads the reservations and technicians, while the confirmation writes the validated reservation. The other steps only update the internal state without querying the reservations table. The conversation takes place in AgentState, used as a working memory. At each step, the partial updates from the nodes are integrated, and the state is recorded between turns thanks to the checkpointer backed by Postgres. To propose appointments, the dedicated node calls an engine that consults existing reservations and the list of technicians via the repository, applies deterministic rules over the next 7 days excluding Sunday, fixed departure times, a duration, and a travel score, then returns the 3 best options. The returned message outlines these numbered slots. Once the confirmation is accepted, the reservation ID, confirmed status, and summary message are integrated into the state, and a snapshot is recorded for the conversation thread.
Why in-memory is not enough for real-world usage
In-memory persistence shows its limits as soon as one leaves a single process: upon restart, conversation states and reservations disappear. Sessions do not share availability, with each process having its own calendar. The same slot can be proposed and then confirmed based on an outdated view, even though it has already been taken elsewhere. While this minimalist configuration allowed for the validation of routing and logic during demonstrations and initial tests, it does not meet the requirements of a product. The need for shared and durable storage becomes essential to eliminate these inconsistencies and sustain the experience.
Postgres activated by configuration, with two dedicated tables
The transition to Postgres introduces a minimal relational database, consisting of two distinct tables for technicians and reservations. The Postgres repository class implements the necessary operations, with the read and write functions defined in this implementation. The choice of backend occurs at startup. An initialization function opts for the Postgres database as soon as a connection URL is provided, directing both the reservation repository and the checkpointer to the database. Otherwise, both remain in memory. Regardless of the option, the instance conforming to the repository interface is passed to the graph constructor. In this architecture, AgentState remains the working memory of the graph, and its persistence is ensured in tandem by the checkpointer and the reservation engine. The result is an operational Postgres backend for the agent.
A unique persistence interface, connected to the graph
To isolate the graph and its engines from the storage technology, a BookingRepository interface defines three capabilities: exposing technicians by ID, listing confirmed reservations, and creating a reservation after checking for overlaps, with error reporting if the slot is taken. This abstraction allows for swapping the in-memory implementation and the one for Postgres at startup. In memory mode, no tables are created; reservations exist in a process list, and the methods never access the database. This mode remains useful for unit tests and local demonstrations, at the cost of total volatility upon restart. On the graph side, the construction relies on this interface and instantiates a StateGraph; if no instance is provided, the in-memory repository is used. The nodes consult or write via the interface: the confirmation uses the reservation creation with the price converted to a floating-point number and raises an error if no slot is selected, then returns the ID, confirmed status, and a formatted message. The state structure lists the necessary fields, and the graph can be compiled with an explicit checkpointer or a memory mechanism. In the in-memory implementation, the list of reservations is protected and returned by copy after locking, and writing checks for conflicts before insertion.
A complete agent, multi-interface, and public code
The reservation agent relies on a graph that drives the listening of needs, price calculation, acceptance or rejection, proposal of optimized slots, and then confirmation and recording of the appointment. It has been designed for a 15-minute journey and already offers a Streamlit interface. Replacing the in-memory adapters with Postgres paves the way for multiple interfaces, including Streamlit and WhatsApp, sharing the same server-side persistence. The project aims for transformation into a product capable of serving real activity, with a Postgres backend already in place and a public code repository. The announced next steps involve execution with Docker and connection to a hosted Postgres instance.
Brief IA — L'actualité IA en français
L'essentiel de l'actualité de l'intelligence artificielle, décrypté et expliqué chaque jour.