define user and define bot
define user names a user intent and lists example messages for it, and define bot names a bot intent and gives the exact words the bot says for it; both live in a Colang .co file.
Last updated: 30 Sep, 2026 · NeMo Guardrails 0.24.1
The model answered everything its instructions allowed, and rails.explain() showed a single general call. Colang is how you tell NeMo what users say and what the bot says back.
The clip calls Colang an expression language that sits between natural language and a programming language. A Colang file uses a few keywords: define, user, bot and flow. The video defines a user who goes off topic, with examples such as how to make a coffee and tell me a joke, and a bot that refuses off topic. The words after define user and define bot are names you choose.
Syntax:
define user ask off topic # a user intent: a name you choose
"tell me a joke" # example messages, one per line
"write me a poem"
define bot refuse off topic # a bot intent
"I'm an Enterprise IT ..." # the exact words the bot saysThe user intent from the video
Eight examples of going off topic, from the video's demo app, as they appear on screen in the clip.
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"The bot intent
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!"Two files the Colang lessons need
From here on, the folder has two more files. Both exist because of how this course runs NeMo, and each has a lesson of its own.
config.py: the example search
NeMo compares every message with your examples. By default it does that with a local embedding model that it downloads on first use. This config.py registers a search that hands the model every example instead, so nothing is downloaded. The Embedding model lesson explains it.
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)core:
embedding_search_provider:
name: every_exampleprompts.yml: the intent prompt
NeMo asks the model which intent a message has. gpt-oss-120b needs one extra line in that prompt, or it answers the user instead of naming the intent. The The prompt behind the intent lesson shows the bug and the fix.
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_v1View the code here
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
Sending an off-topic message
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!")
print(rails.explain().colang_history)User: Tell me a funny joke! Bot : I'm an Enterprise IT Assistant focused on Kubernetes, Intel hardware, and networking. I can't help with that — but ask me anything technical! user "Tell me a funny joke!" ask off topic bot general response "I'm an Enterprise IT Assistant focused on Kubernetes, Intel hardware, and networking. I can't help with that — but ask me anything technical!"
What the two definitions did
- The intent was recognised: the history shows
ask off topicunder the user's message. - The bot intent was not used. The next line is
bot general response: nothing says thatrefuse off topicfollowsask off topic, so the model wrote a reply itself, borrowing the words it had seen. - What joins them is a flow, the next lesson.
define user vs define bot
| define user | define bot | |
|---|---|---|
| Names | What the user means | What the bot says |
| Lines under it | Examples, matched by meaning | The exact reply, sent word for word |
| Used by | Intent detection | Flows |
Where you write these
- Every topic you want to refuse, every jailbreak pattern, every greeting: the video writes one pair for each.
- Questions your team answers the same way every time.
define user are indented by two spaces; without the indent they are read as new statements and the file fails to load.Related
- Previous: rails.explain()
- Next: define flow
- Reference: Colang 1.0 syntax guide
- Add
"how to make a coffee", the video's first example, toask off topic. - Remove the two-space indent from one example and read the load error.
Slow is fine. Stopping is the only problem.