Model or dataset
NVIDIA-NeMo/Guardrails avatar
NVIDIA-NeMo/Guardrails

NeMo Guardrails: Colang Rules Between Your App and the Model

NeMo Guardrails is an open-source toolkit for easily adding programmable guardrails to LLM-based conversational systems.

7,130 stars837 forksPythonNOASSERTION

At a glance

What is it?
NeMo Guardrails wraps an LLM call in a configurable rail layer written in Colang, so dialog paths, topic bans and tool calls are declared rather than prompted. It fits teams that need auditable conversation control, not teams that want a drop-in content filter.
Who is it for?
Adopt NeMo Guardrails if you are building a conversational assistant where specific dialog paths, topic restrictions and tool calls must be declared in files you can review, and you accept Python 3.10 to 3.13 plus a configuration directory as part of your deployment. Do not adopt it if you only need a single input or output classifier in front of a generic chat endpoint, because the rail layer and Colang configs add a vocabulary your team has to learn for little gain.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap NeMo Guardrails fills between prompt instructions and application code

A system prompt that says do not discuss politics is a request, not a control. The model can still drift into the topic, and nothing in your application can tell whether it did until after the response is already on its way to a user. NeMo Guardrails targets exactly that gap. The README describes the project as an open-source toolkit for adding programmable guardrails to LLM-based conversational applications, and it defines a rail as a specific way of controlling model output: refusing a topic, responding in a fixed way to a particular request, following a predefined dialog path, holding a language style, or extracting structured data. The word programmable is the operative one. Rails live in a configuration directory that you load at runtime, so the rules are artifacts a reviewer can read, not sentences buried inside a prompt template. The intended audience is narrow enough to state plainly: developers building question answering over documents, domain-specific assistants, custom LLM endpoints, and optionally LangChain chains. If your product is a single-turn text transformation with no conversation state, the machinery here is more than you need.

How a rail layer sits in the call path

The architecture in the README is a substitution. Instead of calling the model directly, your application calls an LLMRails instance, which loads a RailsConfig from a path on disk and mediates the exchange. The README frames this as requiring only minimal changes to the code base, and the sample confirms it: construct the config, construct the rails object, then call generate with a list of messages. The input and output shape for generate is described as similar to the OpenAI Chat Completions API, so the messages list carries role and content fields and the return value is a single assistant message. What happens inside that call is the rail evaluation, and the configuration directory is where you declare it. The README does not enumerate the internal stages in the excerpt available here, so the precise ordering of input rails, dialog rails and output rails is something to read in the documentation rather than assume. One design decision is stated outright and shapes everything else: the library is async-first, with the core mechanics implemented on the Python async model, and public methods offered in both sync and async form. That matters if your request handler is already async, because the rail layer will not force a thread hop; it matters less if your code is synchronous throughout, since the sync wrappers exist for that case.

Getting a minimal configuration running

The installation step is a single pip command, and the README lists Python 3.10, 3.11, 3.12 or 3.13 as the supported interpreters. There is no mention of a separate compiler toolchain or a GPU requirement in the material available, so the package itself installs as a normal Python dependency. The smallest working program loads a configuration directory and issues one call:

from nemoguardrails import LLMRails, RailsConfig

config = RailsConfig.from_path("PATH/TO/CONFIG") rails = LLMRails(config)

completion = rails.generate( messages=[{"role": "user", "content": "Hello world!"}] )

The README shows the corresponding output as a JSON object with role assistant and content "Hi! How can I help you?". The placeholder PATH/TO/CONFIG is the part that carries the work. Everything the rails do is defined in that directory, so a first integration is really two tasks: wiring the two Python calls, and authoring the configuration the path points at. For LangChain users there is an additional switch. The README states that setting the environment variable NEMOGUARDRAILS_LLM_FRAMEWORK=langchain, or calling set_default_framework("langchain"), enables the LangChain integration so a guardrails layer can wrap existing chains. That is a global default rather than a per-call argument, which is worth noting if one process serves more than one integration style.

What the rail layer does not decide for you

The toolkit gives you a place to declare behavior. It does not tell you what the behavior should be, and it does not ship a universal policy that makes an application safe. The README points to an LLM vulnerability scanning page and to a sample protection overview for the ABC Bot example, covering jailbreaks and prompt injections, but that material is presented as an evaluation of specific guardrails configurations rather than a guarantee that any configuration resists any attack. Treat the rail layer as an enforcement point you populate, not as a shield. There is a second limitation in the shape of the integration itself. Because the rails object replaces the model call, an application that talks to several providers through different clients now has one more component to keep in sync with each provider's message format. The README says the format is similar to Chat Completions, and similar is not identical. Teams that have already standardized on a provider-specific SDK with its own tool-calling and streaming semantics should expect to reconcile those semantics at the rail boundary. Finally, the async-first design is stated as a property of the core mechanics, which means synchronous callers are going through a wrapper rather than a native path. For a low-volume internal tool that is irrelevant. For a high-concurrency service, confirm how the sync wrapper behaves under load before you build on it.

Where a plain classifier or a hosted filter fits better

The obvious alternative for many teams is a content moderation endpoint or a small classifier model placed in front of the LLM. The difference in approach is structural. A classifier scores an input or an output and returns a label; you then decide, in your own code, what to do about it. NeMo Guardrails moves that decision into the rail configuration, and it also covers cases a classifier cannot express at all: following a predefined dialog path, enforcing an authentication or support procedure, and extracting structured data from a conversation. If your requirement is "block toxic inputs and toxic outputs", a classifier is a smaller dependency with a simpler failure mode, and the rail layer earns its cost only when the rules are about conversation flow rather than content labels. The LangChain integration is not really a competing alternative so much as an on-ramp, since the README presents it as a way to add a guardrails layer around existing chains rather than a replacement for them. The honest comparison is between declaring dialog rules in a configuration directory and hand-writing the same checks as conditionals around each model call. The toolkit wins when the rule set grows and more than one person has to review it. It loses when there are three rules and one developer.

Version cadence, licence metadata and the cost of staying current

The release history in the repository shows v0.22.0, v0.23.0 and v0.24.0 arriving at roughly six to ten week intervals, with v0.24.0 dated 2026-08-26. A pre-1.0 version number at that cadence means minor releases can carry behavior changes, and the README reinforces this by distinguishing the develop branch, which tracks top of tree development, from the latest released version. The practical consequence is that pinning a version is not optional for a production deployment, and the upgrade cost is the cost of reading release notes before each bump rather than a one-time setup fee. There is a licence wrinkle worth flagging without offering legal advice: the repository metadata supplied here reports the licence as NOASSERTION, while the README displays an Apache 2.0 badge linking to opensource.org. Those two signals disagree, and the discrepancy is the kind of thing that matters if your organization runs automated licence checks or has a policy about which identifiers it accepts. Confirm the actual licence text in the repository and in the specific release you intend to depend on before that dependency reaches a compliance review, because the metadata alone will not settle it.

Who should wire this in, and what to check before committing

The toolkit is aimed at teams whose conversational product has rules that outlive any single prompt: a support flow with an authentication step, an assistant that must stay inside a domain, a question answering service that needs output moderation on top of retrieval. For those teams the configuration directory is the point, because it turns conversation policy into reviewable files and gives the application a defined place to intervene. For a team shipping a general-purpose chat surface with no domain constraints, the rail layer adds a concept, a config format and a dependency without changing much about the output. The first thing to verify is behavioral, not architectural: write the smallest config that expresses one rule you actually care about, load it through RailsConfig.from_path, and check that generate enforces it on the inputs and outputs you expect, including the ones you expect it to let through. The second is the licence question described above, since the repository metadata and the README badge point at different answers. The third is version pinning, given a pre-1.0 project that ships minor releases every couple of months and maintains a separate develop branch. If those three checks pass, the integration itself is two Python calls and a directory.

Editorial conclusion

Adopt NeMo Guardrails if you are building a conversational assistant where specific dialog paths, topic restrictions and tool calls must be declared in files you can review, and you accept Python 3.10 to 3.13 plus a configuration directory as part of your deployment. Do not adopt it if you only need a single input or output classifier in front of a generic chat endpoint, because the rail layer and Colang configs add a vocabulary your team has to learn for little gain. Verify first that the configs you write behave as intended in your own environment, and confirm the licence terms for the version you pin, since the repository metadata reports NOASSERTION while the README displays an Apache 2.0 badge.

Official sources

  1. Issues
  2. NVIDIA-NeMo/Guardrails on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes