I Replaced a 15-Minute Booking Process with a LangGraph AI Agent
I Replaced a 15-Minute Booking Process with a LangGraph AI Agent
我用 LangGraph AI 智能体取代了耗时 15 分钟的预订流程
A step-by-step guide to building, running, and monitoring a stateful customer support agent using Python, LangGraph, and Langfuse. 这是一份使用 Python、LangGraph 和 Langfuse 构建、运行及监控有状态客户支持智能体的分步指南。
I recently contacted a cleaning company to request a quote for cleaning a couch. They asked about its size and material and requested a picture of it. They also needed my address because travel time varies significantly across the city and therefore affects the price. After receiving the quote for the couch, I asked about apartment cleaning. This started another exchange of messages about the apartment’s size, the desired cleaning depth, and optional services. Once we agreed on a price, we chatted a little more to find a suitable appointment. The entire booking process took around 15 minutes. 最近,我联系了一家清洁公司询问沙发清洁的报价。他们询问了沙发的尺寸和材质,并要求提供照片。他们还需要我的地址,因为城市各地的交通时间差异很大,这会影响价格。在收到沙发清洁报价后,我又询问了公寓清洁的相关事宜。这又引发了一连串关于公寓面积、清洁深度和可选服务的沟通。在商定价格后,我们又聊了一会儿才确定了合适的预约时间。整个预订过程大约花了 15 分钟。
This sounds like a problem worth handing to an AI agent. In this article, we’ll build this agent using Python, LangGraph, and LangChain. We’ll create a demo for testing the complete booking flow and integrate Langfuse for observability. The AI agent will not only speed up the process but also work 24/7 when deployed into production. 这听起来是一个值得交给 AI 智能体解决的问题。在本文中,我们将使用 Python、LangGraph 和 LangChain 来构建这个智能体。我们将创建一个演示程序来测试完整的预订流程,并集成 Langfuse 以实现可观测性。该 AI 智能体不仅能加快流程,在部署到生产环境后还能实现 24/7 全天候工作。
Please note that this is not a simple chatbot. It is a stateful AI agent capable of managing a multi-step business process by combining conversational intelligence with deterministic business rules. The source code of the agent is available on GitHub at customer-service-agent. Feel free to clone and test it yourself. 请注意,这不仅仅是一个简单的聊天机器人。它是一个有状态的 AI 智能体,能够通过结合对话智能与确定性的业务规则来管理多步骤的业务流程。该智能体的源代码已在 GitHub 上的 customer-service-agent 仓库中提供。欢迎克隆并自行测试。
What does this agent do?
这个智能体能做什么?
The agent does everything the customer-service representative of this business does: 该智能体可以完成该业务客户服务代表所做的一切工作:
- Responds to customer queries and understands their needs.
- 回应客户咨询并理解其需求。
- Calculates the price for the service and informs the customer.
- 计算服务价格并告知客户。
- Handles the customer’s acceptance or rejection.
- 处理客户的接受或拒绝。
- Proposes optimized time slots.
- 推荐优化的时间段。
- Confirms and records the appointment.
- 确认并记录预约。
Why an AI agent for this task?
为什么这项任务需要 AI 智能体?
We could build a quotation tool that asks customers a predefined set of questions. Once they approve the price, the system could automatically schedule an appointment. This would work, but every customer would have to follow the same process. An AI agent provides a more natural and flexible experience. For example, a customer can write: “Hey! I need a cleaning service for my 2 bedroom apartment in this address. I also want you to clean inside of my refrigerator. I’m available on Tuesday and Wednesday.”. 我们可以构建一个报价工具,向客户提出预设的一系列问题。一旦客户认可价格,系统就可以自动安排预约。这确实可行,但每个客户都必须遵循相同的流程。而 AI 智能体能提供更自然、更灵活的体验。例如,客户可以写道:“嘿!我需要为我位于此地址的两居室公寓提供清洁服务。我还想请你们清洁冰箱内部。我周二和周三有空。”
This query includes all the required details so there is no need to ask any other question or make the customer enter the same information again through a form. The AI agent can understand if all required information is already present and proceed directly to calculating and presenting a quote. The AI agent can also handle the orchestration of any subsequent steps such as price calculation, handling customer’s decision, searching for optimized appointment times, and booking confirmation. It also has the potential to support additional operations, such as notifying cleaners about new appointments or contacting nearby cleaners to find someone available for an urgent request. 这个查询包含了所有必要的细节,因此无需再询问其他问题,也不必让客户通过表单重复输入相同的信息。AI 智能体可以判断所有必要信息是否齐全,并直接进行报价计算和展示。AI 智能体还可以处理后续步骤的编排,例如价格计算、处理客户决策、搜索优化的预约时间以及确认预订。它还有潜力支持其他操作,例如通知清洁人员新的预约,或联系附近的清洁人员以寻找能够处理紧急请求的人员。
Structure of the agent
智能体的结构
I created the drawing below to demonstrate the structure of our AI agent. The starting point is the interaction between a customer and AI agent. Chatting with the customer, AI agent tries to get all the information needed for the service. The output of the first chat is booking or service details and the agent converts this to a structured output so that it can be used later on by the price and booking engines. 我制作了下图来展示我们 AI 智能体的结构。起点是客户与 AI 智能体之间的互动。在与客户聊天时,AI 智能体会尝试获取服务所需的所有信息。首次聊天的输出是预订或服务详情,智能体会将其转换为结构化输出,以便后续供价格和预订引擎使用。
The BookingDetails I used in the first version is as follows:
我在第一个版本中使用的 BookingDetails 如下:
class BookingDetails(BaseModel):
"""Information extracted from the conversation. ``size_info`` is square footage for a house and seat count for a couch. Fields are optional because this model also represents partial extraction. """
service_type: ServiceType | None = Field(default=None)
size_info: float | None = Field(default=None, gt=0)
cleaning_depth: CleaningDepth | None = Field(default=None)
add_ons: list[str] = Field(default_factory=list)
address: str | None = Field(default=None)
is_complete: bool = False
next_question: str | None = Field(
default=None, exclude=True, description="A concise question asking only for information still missing.",
)
The agent only asks a new question if there is some missing details. Thus, the agent decides what happens next, which is a key point that separates an AI agent from a workflow. 只有在缺少某些细节时,智能体才会提出新问题。因此,智能体决定了下一步做什么,这是区分 AI 智能体与普通工作流的关键点。
LangGraph
LangGraph
We use LangGraph because the booking workflow needs shared state and must resume across multiple customer messages. Thus, we need a stateful agent. The state is a TypedDict as shown below:
我们使用 LangGraph,因为预订工作流需要共享状态,并且必须在多个客户消息之间保持连贯。因此,我们需要一个有状态的智能体。状态是一个 TypedDict,如下所示:
class AgentState(TypedDict):
messages: Annotated[list[AnyMessage], add_messages]
booking_details: BookingDetails
calculated_price: NotRequired[float | None]
time_options: NotRequired[list[TimeOption]]
selected_slot: NotRequired[TimeOption | None]
status: BookingStatus
booking_id: NotRequired[str | None]
LangGraph manages state during graph execution. Nodes read the current state and return partial updates. Conditional routing functions inspect that state to decide which node runs next. We can create the graph builder using this state schema: LangGraph 在图执行期间管理状态。节点读取当前状态并返回部分更新。条件路由函数检查该状态以决定下一个运行的节点。我们可以使用此状态模式创建图构建器:
from langgraph.graph import StateGraph
graph = StateGraph(AgentState)
Then, we start adding nodes and edges. For example, the following code snippet shows how we can create the price calculation node. 然后,我们开始添加节点和边。例如,以下代码片段展示了我们如何创建价格计算节点。
from customer_service_agent.engines import calculate_price
def calculate_price_node(state: AgentState) -> dict[str, Any]:
return {
"calculated_price": calculate_price(
state["booking_details"]
)
}
graph.add_node("calculate_price", calculate_price_node)
The price calculation node reads the extracted booking details and returns a partial state update. The calculate_price is a function that calculates the price using the BookingDetails available in the AgentState. After the information-gathering node runs, a conditional routing function determines whether enough information is available.
价格计算节点读取提取的预订详情并返回部分状态更新。calculate_price 是一个使用 AgentState 中可用的 BookingDetails 来计算价格的函数。在信息收集节点运行后,条件路由函数会判断信息是否足够。