NVIDIANVIDIA-Certified Professional: Agentic AI2026-107.1 Integrate NVIDIA NeMo Guardrails for compliance and safety enforcement.
Wire Guardrails from YAML to Colang
Completed by the knowledge check
Learning objective
Configure rails with config.yml, prompts, and Colang flows.
Core idea
A policy sentence, a rail activation, and a flow implementation are different configuration objects. The policy tells a model what to judge. The activation list tells the runtime when to run a check. The flow interprets the check’s result and determines whether processing continues, changes, or stops.
Keep those connections explicit. A detailed policy in a prompt does not activate a rail, and activating the self-check rail without its required prompt raises an exception when the configuration loads. See 7.1.1 for choosing the enforcement stage; here the decision is how to turn that choice into a coherent executable configuration.
How it works
Give each file one responsibility
The configuration directory contains a required config.yml. Its models section identifies model roles and providers; its rails section activates checks and supplies their settings. General instructions and sample conversations can also live there. Optional .co files implement Colang behavior and are loaded recursively from the configuration directory.
Task prompts can live under prompts in config.yml or in a separate prompts.yml. Optional actions.py or an actions/ package supplies Python functions decorated with @action(). Optional config.py performs startup registration and initializes shared resources. These files form one configuration, rather than independently deployed policy fragments.
Load a directory with RailsConfig.from_path("./config"), then pass the result to LLMRails. That explicit runtime is useful when the configuration needs Colang behavior. Keep the model’s actual provider configuration alongside the policy files so that a test exercises the intended checking model rather than a remembered default.
Connect the flow name to the prompt task
The following excerpts illustrate input self-check wiring; they supplement a configuration that already declares its main model. In config.yml, activate the built-in flow:
rails:
input:
flows:
- self check inputIn prompts.yml, supply the task-specific decision prompt:
prompts:
- task: self_check_input
content: |
Policy: block requests to impersonate another employee.
User message: "{{ user_input }}"
Should the message be blocked? Answer yes or no.The spaces and underscores distinguish two identifiers. self check input is a flow name; self_check_input is the prompt task and action name. The prompt’s answer is yes when the message should be blocked, but the action returns True when it should be allowed. Do not invert that polarity when implementing custom behavior.
The documented Colang 1.0 built-in flow makes the control decision explicit:
define flow self check input
$allowed = execute self_check_input
if not $allowed
bot refuse to respond
stopThis is the built-in behavior to understand, not a second definition to copy over it. You can customize the refusal by defining bot refuse to respond in a .co file. That changes the refusal text; it does not alter what the checking action considers safe.
Keep prompt selection and language selection deliberate
Prompt templates support Jinja2 variables. {{ user_input }} supplies the incoming user message, while {{ bot_response }} supplies the proposed response for output checking. A prompt can use content or chat-style messages; these are mutually exclusive. A models selector restricts a prompt to an engine or an engine/model pair.
The top-level prompting_mode selects prompt variants whose mode matches it. If no matching mode exists, selection falls back to standard. Therefore, changing prompting_mode to compact does not establish that a compact prompt actually ran. Verify the selected task and behavior, especially when reducing context to meet latency targets.
The prompt’s max_length limits prompt characters; max_tokens controls completion tokens. These are different budgets. Self-check actions fall back to 1,024 completion tokens when max_tokens is unset. With a reasoning checker, internal reasoning can consume that budget before a visible verdict appears. The documented default input/output self-check parser treats an empty verdict as unsafe; the remedy is an explicit task max_tokens sufficient for reasoning plus the verdict, followed by measurement.
Set the language with colang_version in config.yml; LLMRails selects its runtime from config.colang_version. The Colang Guide describes 1.0 as the default while 2.0 completes beta. The 1.0 forms used here include define flow and execute. Colang 2.0 changes syntax and mechanics, including an explicit main entry flow and explicit activation, while keeping the same event-driven interaction model.
Engine Feature Support limits IORails to Colang 1.0 configurations; Colang 2.x configurations route to LLMRails. The Colang Guide also lists incomplete usability of the Guardrails Library from Colang 2.0 as a 2.0-beta limitation. Treat migration as a tested configuration change: support for the language runtime does not establish complete built-in-library compatibility.
Key distinctions and trade-offs
Choose the configuration object according to the change you need:
| Desired change | Object to edit | Consequence to verify |
|---|---|---|
| Run an input policy check | rails.input.flows | The check executes before main generation |
| Change what the checker rejects | prompts task self_check_input | Benign and prohibited examples retain the intended verdict polarity |
| Change refusal wording | Colang define bot refuse to respond | A rejected request returns the intended message |
| Change permitted conversation behavior | Colang define flow | The next interaction follows the intended sequence |
| Reduce checking prompt size | Matching prompting_mode and prompt mode | The intended variant runs without losing needed policy detail |
A longer self-check prompt can encode more precise distinctions but consumes more tokens and adds latency. A shorter prompt can omit the exception that allows a legitimate request. Choose from observed behavior on your policy examples, not from file length. Purpose-built detector integration is the separate decision in 7.1.3.
Architecture / decision scenario
An insurance company builds a claims-drafting assistant for employees. Its application target allows 400 ms of checking overhead. In a scenario replay of 600 requests, a broad self-check prompt rejects 42 legitimate drafting requests because they quote impersonation attempts as incident material. A revised prompt distinguishes reporting an attempt from requesting one and rejects 6 legitimate requests, while still blocking all 60 labeled impersonation requests in that replay.
The tempting alternative edits only the bot’s general instructions: “Never impersonate an employee.” The application owner rejects that proposal because the required behavior is a separate input decision before drafting. The team keeps self check input activated and edits the self_check_input task, preserving its yes-means-block convention. A .co bot definition supplies a refusal that tells employees how to reformulate a prohibited request.
The revised configuration adds 310 ms at the measured tail, while a more verbose variant adds 470 ms. The owner chooses the revised prompt provisionally because it meets the 400 ms budget and reduces observed overblocking. These numbers are scenario measurements, not NVIDIA guarantees. A held-out set must confirm that the clearer exception does not also permit disguised impersonation requests.
Before promotion, the team loads the complete directory with RailsConfig.from_path, checks that missing required prompts fail visibly, and exercises benign, prohibited, and quoted-incident cases. It also verifies the refusal path and the runtime selected by colang_version. Editing the prompt without testing the activated flow would miss a naming mismatch that leaves the intended task unused.
Common exam traps
- Treating general instructions as activation of a self-check rail.
- Confusing the flow
self check inputwith the taskself_check_input. - Interpreting an action’s allowed Boolean as the prompt’s blocked answer.
- Supplying both
contentandmessagesfor one prompt. - Treating
max_lengthcharacters as completion tokens. - Assuming Colang 1.0 and 2.0 examples are interchangeable.
What to remember
Connect three objects: activation in config.yml, a prompt for the checking task, and flow behavior that interprets the result. Load and test them together. Preserve verdict polarity, verify prompt selection, and budget completion tokens separately from prompt length.
Knowledge check
A team adds “Never draft messages that impersonate another employee” to the bot’s general instructions and writes a self_check_input prompt task in prompts.yml. The configuration loads without errors, but traces show that no input check runs before generation. What is missing?
define bot refuse to respond block in a .co fileself check input flow listed under rails.input.flowsdefine flow self check input in a .co fileprompting_mode value that matches the prompt’s modeself check input under rails.input.flows runs the built-in flow, which executes the self_check_input task. A bot definition changes only the refusal wording, the built-in flow is meant to be understood rather than copied over, and when no prompt matches prompting_mode the standard prompt is used anyway.A team replaces the built-in input check with a custom action registered with @action(). Its self_check_input prompt asks “Should the message be blocked? Answer yes or no.”, and the action returns True when the model answers yes and False otherwise. The flow treats True as allowed and refuses on False, as the built-in flow does. If the checking model judges every request correctly, what will a replay of labeled requests show?
yes means block, while the action returns True when the input should be allowed. Returning True for yes inverts the check, so every message the model judges prohibited is allowed and every message it judges acceptable is refused. The fix is in the action’s mapping, not in the prompt wording or the refusal text.A team switches its input self-check to a reasoning model. Benign requests start being refused, and the logs show warnings with finish_reason="length" and empty content. The prompt task does not set max_tokens. What should the team change first?
max_tokens to cover the reasoning and the verdictmax_length so the prompt can hold more textprompting_mode to compact so the prompt becomes shortermax_tokens unset, self-check actions fall back to 1,024 completion tokens, and a reasoning model can spend them before writing a verdict; the default parser treats that empty verdict as unsafe and blocks. Setting an explicit task max_tokens large enough for reasoning plus the verdict, then measuring again, addresses that cause. max_length limits prompt characters rather than completion tokens, a compact prompt does not enlarge the completion budget, and the empty output shows the refusals do not come from the policy wording.To cut checking latency, a team sets the top-level prompting_mode: compact. The configuration’s only self_check_input prompt declares mode: standard. The measured checking overhead does not change. What explains the result?
IORails enginestandard prompt variantprompting_mode selects the prompt whose mode matches it, and when no prompt matches, selection falls back to standard . With no compact variant written, the same standard prompt runs, so changing the setting alone proves nothing about what executed. The team has to add a mode: compact prompt for the task and verify that it ran without losing policy detail it needs.References
- NVIDIA, NeMo Guardrails Library Configuration Overview
- NVIDIA, LLM Self-Check
- NVIDIA, Prompt Configuration for the NVIDIA NeMo Guardrails Library
- NVIDIA, Colang Guide
- NVIDIA, Colang 1.0 Language Syntax
- NVIDIA, About Running Guardrailed Inference
- NVIDIA, Engine Feature Support