Dialogue Management & Agents
We are witnessing a shift from rigid Finite State Machines (FSM) to dynamic, graph-based orchestration. Frameworks like LangGraph and Rasa CALM allow building stateful agents that can loop, branch, and reason.
From DAGs to Graphs
The Problem with Chains (DAGs)
Simple chains (like LangChain's basic chains) are **Direct Acyclic Graphs**. They move one way. Real conversation requires Cycles: asking clarifying questions, re-trying a failed tool call, or looping back to a previous state.
The Graph Solution
LangGraph allows you to define nodes (agents/functions) and edges (conditional jumps). This enables "Agentic Loops" where the LLM decides the next step (or loop) dynamically based on the state.
LangGraph: Cyclic Agent Flow
Rasa CALM (Conversational AI with LMs)
Enterprises cannot rely on pure "Black Box" LLM agents due to hallucinations. Rasa CALM introduces a hybrid approach:
- LLM for NLU: The LLM understands the user intent and extracts entities (slots).
- Logic for Flow: The dialogue flow is strictly controlled by explicit business logic (Flows).
- Policy for Repair: If the user goes off-script, the LLM generates a "repair" to bring them back to the flow.
Building a Graph w/ LangGraph
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
# 1. Define State
class AgentState(TypedDict):
messages: list[str]
next_step: str
# 2. Define Nodes (Functions)
def chatbot(state: AgentState):
# Call LLM logic here
return {"messages": ["Message processed"], "next_step": "tools"}
def tool_executor(state: AgentState):
# Execute python/api tool
return {"messages": ["Tool Result: 42"], "next_step": END}
# 3. Build Graph
graph = StateGraph(AgentState)
graph.add_node("bot", chatbot)
graph.add_node("tools", tool_executor)
graph.set_entry_point("bot")
graph.add_conditional_edges(
"bot",
lambda x: x["next_step"],
{"tools": "tools", END: END}
)
app = graph.compile()
# app.invoke({"messages": ["Hello"]})