Streamlit Revolutionizes AI Booking Interface with LangGraph

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
A New Dimension for the LangGraph AI Agent
In a previous article, it was described how an AI agent, based on LangGraph technology, was developed to automate customer service booking sessions in just 15 minutes. This agent is designed to handle the entire booking process, effectively mimicking the role of a real customer service representative.
The agent, built on LangGraph, is capable of performing several essential tasks. It answers customer questions, understands their specific needs, calculates the cost of the service, and informs the customer of that amount. Additionally, it manages the customer's acceptance or refusal, proposes optimized time slots, and finally confirms and records the appointment.
From Command Line Interface to Streamlit
In its initial version, the agent operated via a Python command line interface, primarily used for testing its functionalities. While this method was effective for testing, it did not represent the best way to demonstrate a customer-oriented user experience.
For those interested in exploring the complete source code of this project, it is available on GitHub under the name customer-service-agent. Users are encouraged to clone the repository and test the agent themselves.
This article focuses on creating a clean and interactive Streamlit interface that will integrate with the existing LangGraph agent.
Streamlit: An Enhanced User Interface
In terms of implementation, Streamlit is not much different from a Python command line interface. Both serve as a framework for the LangGraph agent. However, Streamlit stands out for its user-friendliness and visually appealing design.
The command line interface collected inputs, invoked the graph, and displayed responses. The Streamlit page, on the other hand, performs the same operations while displaying structured information extracted from the graph's state, such as current booking details, quotes, and acceptance buttons.
The application's architecture remains unchanged. Streamlit simply presents the state to the user and returns user actions to the agent.
Setting Up Streamlit with Poetry
To manage dependencies, poetry is used, allowing for easy installation of Streamlit with the following command:
poetry add streamlit
This command updates the pyproject.toml and poetry.lock files. Then, a new file streamlit_app.py is created.
The process begins with importing the graph builder, models, and observability utilities.
from __future__ import annotations
from datetime import datetime
from typing import Any
from uuid import uuid4
import streamlit as st
from dotenv import load_dotenv
from langchain_core.messages import AIMessage, HumanMessage
from langchain_openai import ChatOpenAI
from customer_service_agent.graph import build_graph
from customer_service_agent.models import (
from customer_service_agent.observability import (
create_langfuse_handler,
Logical Separation and State Initialization
The agent's graph contains no Streamlit-specific logic, which is crucial for allowing its execution from different interfaces, whether it be a command line, an API, WhatsApp, or another frontend.
The graph requires the initialization of an Agent State. Thus, in streamlit_app.py, the initial state is defined as follows:
INITIAL_STATE: AgentState = {
"booking_details": BookingDetails(),
"calculated_price": None,
"time_options": [],
"selected_slot": None,
"status": "gathering_info",
After the first message from the customer, the LangGraph checkpointer retains the state. Streamlit restarts the entire Python script with each user interaction, preventing the use of local variables. To preserve the conversation, session_state is used.
Session Initialization
The session is initialized as follows:
def initialize_session() -> None:
if "graph" in st.session_state:
llm = ChatOpenAI(
model=os.getenv("OPENAI_MODEL", "[gpt-4o](/dossier/openai)-mini"),
handler = create_langfuse_handler()
st.session_state.graph = build_graph(llm)
st.session_state.handler = handler
st.session_state.config = graph_config(
st.session_state.agent_state = INITIAL_STATE.copy()
st.session_state.started = False
This function checks if the graph has already been created for the current browser session. Without this check, each execution of Streamlit would replace the graph.
The graph_config function generates a UUID used as a thread_id, essential for LangGraph to identify a conversation. If a new UUID were generated with each execution, LangGraph would consider each message as a new conversation.
User Input Management
The _invoke function handles user input:
def _invoke(customer_text: str) -> None:
"""Submit a customer turn to the graph and retain its last state."""
graph_input: dict[str, Any] = {"messages": [HumanMessage(content=customer_text)]}
if not st.session_state.started:
graph_input.update(INITIAL_STATE)
graph_input["messages"] = [HumanMessage(content=customer_text)]
st.session_state.started = True
result = st.session_state.graph.invoke(graph_input, config=st.session_state.config)
st.session_state.agent_state = result
flush_langfuse(st.session_state.handler)
except Exception:
st.session_state.started = bool(st.session_state.agent_state.get("messages"))
st.error("The assistant was unable to process this request. Please try again.")
This function sends the customer's action to the LangGraph agent and records the resulting state for the Streamlit interface. The action can be a chat input or a button click.
The customer's message is transformed into a HumanMessage from LangChain. Messages utilize LangGraph's add_messages reducer, allowing new messages to be added to the existing conversation.
For the first message, the graph is initialized with the previously defined INITIAL_STATE, including empty booking details, scheduling options, a price, and the initial status.
Execution and State Update
Each new customer action triggers the invocation of the graph and updates its state with the result:
result = st.session_state.graph.invoke(graph_input, config=st.session_state.config)
st.session_state.agent_state = result
This allows the customer's message to be processed through the graph. The returned state is stored in the Streamlit session so that the page can display the latest message details, booking summary, price, appointment options, and status.
Rendering Visual Components
Finally, several rendering functions (_render...()) are defined in streamlit_app.py to convert the current state of LangGraph into visible Streamlit components.
def _render_messages(state: AgentState) -> None:
if not state.get("messages"):
with st.chat_message("assistant"):
"Hello! I can help you book a house or sofa cleaning."
"Let me know what you need, including the size and address of the service."
for message in state["messages"]:
if isinstance(message, HumanMessage):
elif isinstance(message, AIMessage):
role = "assistant"
with st.chat_message(role):
st.write(str(message.content))
For example, the _render_messages function displays the conversation history as Streamlit chat bubbles. It receives the conversation through the latest state of LangGraph using state["messages"]. If the conversation has no messages yet, the function displays an initial welcome message.
Implementation and Testing of the Interface
After going through streamlit_app.py to understand the page structure, it's time to see it in action. To test the agent locally, the following command is used:
poetry run streamlit run customer_service_agent/streamlit_app.py
This opens a page at http://localhost:8501/. The page presents an interactive and intuitive user interface.
To test the agent, an OPENAI_API_KEY is required. This incurs minimal costs for testing.
Example Conversation
In a chat example, the agent asks for the address if it is not provided in the first message. If the address is included from the start, the agent does not need to ask for it again. After accepting the quote, the agent proposes three appointment options and completes the booking.
Improvement Perspectives
Although the current interface is functional and pleasant, there are still many opportunities for improvement to make it more user-friendly. Additional features, such as integration with WhatsApp, are being considered. This project could even evolve into a marketable product for certain local businesses.
Stay tuned for future developments, and thank you for reading!
Brief IA — L'actualité IA en français
L'essentiel de l'actualité de l'intelligence artificielle, décrypté et expliqué chaque jour.