GenAIHub
Back to Technical
Agent Orchestration

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

graph TD Start --> Agent Agent -->|Calls Tool| Tools Tools -->|Output| Agent Agent -->|Final Answer| End Agent -->|Ambiguous| HumanInTheLoop HumanInTheLoop -->|Feedback| Agent style Agent stroke:#6366f1,stroke-width:2px style Tools stroke:#ec4899,stroke-width:2px

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.
Hybrid Structure + Creativity

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"]})