NeMo Guardrailsnemoguardrails 0.24.1 · Python 3.10+
Dashboard
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
37 small wins to finish your pathNext lesson →

define flow

define flow is the Colang block that joins intents into a conversation: when the user's message has one intent, the bot answers with another.

Last updated: 30 Sep, 2026 · NeMo Guardrails 0.24.1

In define user and define bot the message was recognised as off topic, and the model still wrote the reply. A flow makes the refusal automatic.

The topic guard demo · from The Complete AI Security Course In 8 Hours · 24:03 to 27:21

The demo is the video's first layer of security, the topic guard. The assistant is programmed for Kubernetes, Intel hardware and networking. A question asking whether there is a movie about "Krish Naik Academy" gets I can't help you with that, but ask me anything technical, and What is Kubernetes? gets an answer.

Writing the flow · from The Complete AI Security Course In 8 Hours · 43:53 to 46:42

The second clip writes the flow: define flow handle off topic, then user ask off topic, then bot refuse off topic. The video calls it an if-else: if the user is off topic, the bot refuses off topic.

Syntax:

text
define flow handle off topic   # a name you choose
  user ask off topic           # when the user's intent is this
  bot refuse off topic         # the bot says this
  stop                         # and the turn ends here

The flow

Add the flow at the end of rails.co, under the two definitions from the last lesson. The video's flow ends with stop, which ends the turn after the refusal; stop and bot refuse to respond covers it in detail.

text
define flow handle off topic
  user ask off topic
  bot refuse off topic
  stop
Project files used on this pageThis lesson builds on a project from earlier lessons. The code below imports these files. Click a file to see its code, or follow the link to the lesson that wrote it. To run the code yourself, keep them in the same folder.
View the code here
rails.co
define user ask off topic
  "tell me a joke"
  "what is the capital of france"
  "write me a poem"
  "what is 2 plus 2"
  "what should I eat for dinner"
  "who won the game yesterday"
  "recommend a movie"
  "what is the weather like"

define bot refuse off topic
  "I'm an Enterprise IT Assistant focused on Kubernetes, Intel hardware, and networking. I can't help with that — but ask me anything technical!"

define flow handle off topic
  user ask off topic
  bot refuse off topic
  stop
config.py
from nemoguardrails.embeddings.index import EmbeddingsIndex


class EveryExample(EmbeddingsIndex):
    """Hands the model every example instead of the closest few."""

    def __init__(self, **kwargs):
        self.items = []

    async def add_items(self, items):
        self.items.extend(items)

    async def build(self):
        pass

    async def search(self, text, max_results=5, threshold=None):
        return self.items


def init(app):
    app.register_embedding_search_provider("every_example", EveryExample)
config.yml
models:
  - type: main
    engine: openai
    model: openai/gpt-oss-120b
    api_key_env_var: GROQ_API_KEY
    parameters:
      base_url: https://api.groq.com/openai/v1
      temperature: 0

instructions:
  - type: general
    content: |
      You are an Enterprise IT Assistant specialising in Kubernetes,
      Intel hardware, and enterprise networking.
      Only answer questions about these topics.
      Answer in one or two short sentences.

core:
  embedding_search_provider:
    name: every_example
prompts.yml
prompts:
  - task: generate_user_intent
    content: |-
      """
      {{ general_instructions }}
      """

      # This is how a conversation between a user and the bot can go:
      {{ sample_conversation | verbose_v1 }}

      # This is how the user talks:
      {{ examples | verbose_v1 }}

      # This is the current conversation between the user and the bot:
      {{ sample_conversation | first_turns(2) | verbose_v1 }}
      {{ history | colang | verbose_v1 }}

      Do not answer the user. Reply with one line: the user intent of the last message.
      Use an intent from the examples when one fits, otherwise write a new short intent.
    output_parser: verbose_v1

Running the video's topic guard

The video's own test messages: three off topic, one on topic.

ExampleAPI keyFrom the video, run on Groq
from nemoguardrails import LLMRails, RailsConfig

rails = LLMRails(RailsConfig.from_path("."))


def chat(message):
    reply = rails.generate(messages=[{"role": "user", "content": message}])
    print("User:", message)
    print("Bot :", reply["content"])

chat("Tell me a funny joke!")
chat("What is the capital of France?")
chat("Recommend a good Netflix show")
chat("What is a Kubernetes ConfigMap?")

What the flow did

  • The three off-topic messages got the refusal from define bot, word for word, including the Netflix question, which is not one of the seven examples.
  • The ConfigMap question matched no flow, so the model answered it.
  • The Netflix question is the one the keyword guard in Blocking a message with an if let through. The match is on meaning, not on words.

A flow vs an if in Python

if in Pythondefine flow
MatchesExact textAn intent, decided by meaning
Lives inThe applicationrails.co
Changed byA developerAnyone who can edit the file

Where you use flows

  • One flow per thing to refuse: off topic, jailbreaks, sensitive topics, as the next lesson stacks them.
  • Fixed answers to common questions, which cost no model call to write.
Watch out. A flow's first line must name an intent you defined. A typo such as user ask offtopic is not an error: the flow never matches, and the model answers.
Try it yourself
  • Ask How to make a coffee, I'm bored, the video's first off-topic prompt.
  • Misspell the intent in the flow's first line and ask the joke question again.

This is what real progress feels like.