What CALM Replaces

Classic Rasa used stories (example conversation paths) and rules (strict if-then conditions) to define dialogue management. Training required hundreds of story examples to handle variations. Edge cases required more stories. The system was powerful but labour-intensive to maintain.

CALM (Conversational AI with Language Models) replaces this with:

  • Flows -- structured definitions of what the bot should accomplish, written in YAML
  • An LLM that interprets user messages and decides which flow step to execute next
  • Slot filling backed by the LLM -- no more extensive NLU training for entity extraction

The result: less training data required, more graceful handling of unexpected inputs, and better performance on out-of-distribution user messages.

Flows: The Core CALM Concept

A flow defines a conversation goal and the steps to achieve it. The LLM decides which step is appropriate given the user's current message and conversation context.

flows:
  book_appointment:
    description: Book a medical appointment for the user.
    steps:
      - id: ask_appointment_type
        collect: appointment_type
        ask_before_filling: true
        description: Ask the user what type of appointment they need
        next:
          - if: slots.appointment_type == 'urgent'
            then: check_urgent_availability
          - else: ask_preferred_date
 
      - id: ask_preferred_date
        collect: preferred_date
        ask_before_filling: true
        description: Ask the user for their preferred appointment date
        next: confirm_booking
 
      - id: check_urgent_availability
        action: action_check_urgent_slots
        next: confirm_booking
 
      - id: confirm_booking
        action: action_create_appointment
        next: END
 

The LLM reads the flow descriptions and slot definitions to understand the intent. It does not need story examples -- it reasons from the YAML definition.

Slot Collection With CALM

CALM's LLM automatically extracts slots from user messages during a flow. You define what to collect; the LLM handles the extraction.

slots:
  appointment_type:
    type: categorical
    values:
      - general
      - specialist
      - urgent
    mappings:
      - type: from_llm
 
  preferred_date:
    type: text
    mappings:
      - type: from_llm
 
Use type: from_llm for most slot extraction in CALM. The LLM handles variation ('I need to see someone urgently' -> appointment_type = 'urgent') without requiring NLU training examples for each variation.

Custom Actions Still Use Python

Business logic (database lookups, API calls, custom validations) still lives in a Python action server. The interface is the same as classic Rasa.

from rasa_sdk import Action, Tracker
from rasa_sdk.executor import CollectingDispatcher
from typing import Dict, Text, Any, List
 
class ActionCreateAppointment(Action):
    def name(self) -> Text:
        return 'action_create_appointment'
 
    def run(
        self,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any],
    ) -> List[Dict[Text, Any]]:
        appointment_type = tracker.get_slot('appointment_type')
        preferred_date = tracker.get_slot('preferred_date')
 
        # Your booking logic here
        booking_id = create_booking_in_crm(appointment_type, preferred_date)
 
        dispatcher.utter_message(
            text=f'Your {appointment_type} appointment has been booked. '
                 f'Reference: {booking_id}'
        )
        return []
 

Migrating From Classic Rasa to CALM

There is no automated migration path. CALM is a different architecture. The migration approach:

  1. Identify your highest-traffic stories and convert them to CALM flows (one flow per user goal)
  2. Replace intent-based NLU with flow descriptions the LLM can reason from
  3. Keep your action server code -- it is unchanged
  4. Convert slot mappings to from_llm type where applicable
  5. Run CALM alongside classic Rasa in parallel during transition (enterprise feature)
  6. Retrain and test iteratively -- CALM requires testing for LLM reasoning quality, not story coverage
CALM is part of Rasa Pro (the classic Rasa Open Source framework is now in maintenance mode). You can run Rasa Pro with CALM for free via the Rasa Developer Edition -- a free license valid for up to 1,000 conversations/month and usable in production -- with paid Enterprise licensing for larger-scale deployments. Before planning a migration, evaluate whether your use case justifies this over a cloud chatbot builder that has already integrated LLMs natively.

CALM Limitations to Know

  • LLM dependency: CALM requires an LLM call for each dialogue step. This adds latency (~200-500ms per turn) and cost compared to classic Rasa's deterministic rules.
  • Determinism: LLM-backed dialogue is less deterministic than rules. Two identical inputs may take slightly different paths. This matters for compliance-sensitive scenarios.
  • Debugging: classic Rasa showed exactly which story matched. CALM's LLM reasoning is less transparent -- you see the outcome, not the full reasoning chain.