Skip to navigation

nemoguardrails.guardrails.rails_manager

View as Markdown

Rails manager for IORails: runs input/output checks through compiled, manifest-driven rails.

Module Contents

Classes

NameDescription
RailsManagerCompiles a manifest-driven rail per configured flow and runs them sequentially or in parallel.

Functions

NameDescription
_checked_textReturn the text this direction’s rails check, which is the text a rewrite replaces.
_merge_llm_call_infoMerge a captured model call’s usage, naming and timing into record.
_model_free_recordBuild the per-rail GenerationLog record for a rail that reached no model.
_rail_call_recordBuild the per-rail GenerationLog record from a rail’s result and the calls it made.
_rail_resultMap an engine-neutral rail verdict onto IORails’ rail result.
_refuse_concurrent_rewriteRefuse a rewrite from a concurrent rail: peers read the arriving text, so it cannot compose.
_result_after_rewritesReport the text that survived every rail, so a rewrite undone by a later rail is no rewrite.
_rewriting_flowsThe configured flows whose surface declares they may rewrite the text they check.
_rewritten_textReturn what a rail rewrote this direction’s variable to, ignoring any it also named.
_tool_rail_resultMap a tool rail’s verdict, refusing a rewrite it has nowhere to apply.
_transforms_firstOrder rails that may rewrite ahead of rails that only judge, so a mask reaches the check.

Data

_REWRITABLE_TARGET

_SURFACE_DIRECTIONS

_TOOL_ACTION_CLASSES

_ToolActionT

log

API

class nemoguardrails.guardrails.rails_manager.RailsManager(
input_flows: list[str],
output_flows: list[str],
input_parallel: bool = False,
output_parallel: bool = False,
tool_call_flows: typing.Optional[list[str]] = None,
tool_result_flows: typing.Optional[list[str]] = None,
tracer: typing.Optional[opentelemetry.trace.Tracer] = None,
content_capture_enabled: bool = False
)

Compiles a manifest-driven rail per configured flow and runs them sequentially or in parallel.

_http_client
= create_http_client()
_rails
dict[tuple[RailDirection, str], CompiledRail]
_tool_call_actions
_tool_result_actions
input_flows
list[str] = list(input_flows)
output_flows
list[str] = list(output_flows)
tool_call_flows
list[str] = list(tool_call_flows or [])
tool_result_flows
list[str] = list(tool_result_flows or [])
transform_flows
dict[RailDirection, tuple[str, ...]]
nemoguardrails.guardrails.rails_manager.RailsManager._build_tool_actions(
flows: list[str],

Instantiate the tool rails for flows, checking each resolves to expected_cls.

Raises RuntimeError on a duplicate flow, an unknown flow, or a flow that resolves to the wrong direction. Duplicates are rejected because the dispatch keys its coroutine map by flow, so a repeated flow would silently drop a run.

nemoguardrails.guardrails.rails_manager.RailsManager._disable_parallel_execution() -> None

Turn both directions sequential, because concurrent rails cannot carry a rewrite.

nemoguardrails.guardrails.rails_manager.RailsManager._enabled_flows(
configured: list[str],
enabled: typing.Union[bool, list[str]]
) -> list[str]
staticmethod

Resolve the per-request toggle into the configured flows to run: True all, False none.

nemoguardrails.guardrails.rails_manager.RailsManager._flows_to_run(
configured: list[str],
enabled: typing.Union[bool, list[str]]
) -> list[str]

The flows this request runs, in the order it runs them: rewriting rails first.

nemoguardrails.guardrails.rails_manager.RailsManager._rail_dependencies() -> nemoguardrails.guardrails.compiled_rail.RailDependencies

Bundle the collaborators a compiled rail’s action may declare as parameters.

nemoguardrails.guardrails.rails_manager.RailsManager._run_rail(
flow: str,
messages: list[dict],
bot_response: typing.Optional[str] = None
async

Dispatch a single rail flow to its compiled rail and record what it did.

nemoguardrails.guardrails.rails_manager.RailsManager._run_rails_parallel(
rails: collections.abc.Mapping[str, collections.abc.Coroutine[typing.Any, typing.Any, nemoguardrails.guardrails.guardrails_types.RailResult]],
async

Run rail coroutines concurrently; on the first unsafe result, finish draining its completion batch (so rails that finished alongside it still contribute their records) before cancelling the rest.

nemoguardrails.guardrails.rails_manager.RailsManager._run_rails_sequential(
flows: collections.abc.Sequence[str],
messages: list[dict],
bot_response: typing.Optional[str] = None
async

Run a direction’s rails in turn, threading each rewrite into the rails behind it.

nemoguardrails.guardrails.rails_manager.RailsManager._run_tool_call_rail(
flow: str,
tool_calls: list[nemoguardrails.types.ToolCall],
async

Dispatch a single tool-call rail to its action, wrapped in an OUTPUT rail span.

nemoguardrails.guardrails.rails_manager.RailsManager._run_tool_rails_sequential(
rails: collections.abc.Mapping[str, collections.abc.Coroutine[typing.Any, typing.Any, nemoguardrails.guardrails.guardrails_types.RailResult]],
async

Run tool rail coroutines in turn, short-circuiting on the first unsafe result.

Separate from the input/output loop because tool rails carry no text between them, so their coroutines are built up front and the unreached ones need closing.

nemoguardrails.guardrails.rails_manager.RailsManager._run_tool_result_rail(
flow: str,
async

Validate each turn’s results against that turn’s calls, wrapped in an INPUT rail span.

Each exchange is validated independently so call_id linkage stays turn-local; the first unsafe exchange short-circuits.

nemoguardrails.guardrails.rails_manager.RailsManager.are_tool_calls_safe(
tool_calls: list[nemoguardrails.types.ToolCall],
llm_params: typing.Optional[dict],
enabled: typing.Union[bool, list[str]] = True,
model_type: str = 'main'
async

Validate the model’s emitted tool calls (OUTPUT-direction tool rail).

The tool-call counterpart to :meth:is_output_safe: takes the model’s output (tool_calls) plus the request’s declared tools (llm_params) and returns a RailResult.

nemoguardrails.guardrails.rails_manager.RailsManager.are_tool_results_safe(
messages: list[dict],
enabled: typing.Union[bool, list[str]] = True,
model_type: str = 'main'
async

Validate incoming tool results (INPUT-direction tool rail).

The tool-result counterpart to :meth:is_input_safe: takes the conversation messages and returns a RailResult. Groups the conversation into per-turn (calls, results) exchanges via the engine adapter and validates each result against its own turn’s calls, so call ids reused across turns (spec-allowed) are not flagged as ambiguous duplicates.

nemoguardrails.guardrails.rails_manager.RailsManager.is_input_safe(
messages: list[dict],
enabled: typing.Union[bool, list[str]] = True
async

Run the enabled input rails, short-circuiting on the first failure.

The per-request enabled toggle selects which configured input rails run: True (the default) runs all, False runs none, and a list runs only the named flows (matched on the normalized flow name). When parallel mode is enabled, all selected rails run concurrently and the first unsafe result cancels the rest.

nemoguardrails.guardrails.rails_manager.RailsManager.is_output_safe(
messages: list[dict],
response: str,
enabled: typing.Union[bool, list[str]] = True
async

Run the enabled output rails, short-circuiting on the first failure.

The per-request enabled toggle selects which configured output rails run: True (the default) runs all, False runs none, and a list runs only the named flows (matched on the normalized flow name). When parallel mode is enabled, all selected rails run concurrently and the first unsafe result cancels the rest.

nemoguardrails.guardrails.rails_manager.RailsManager.stop() -> None
async

Close the runtime-owned pooled HTTP client.

nemoguardrails.guardrails.rails_manager._checked_text(
messages: list[dict],
bot_response: typing.Optional[str]
) -> str

Return the text this direction’s rails check, which is the text a rewrite replaces.

Merge a captured model call’s usage, naming and timing into record.

nemoguardrails.guardrails.rails_manager._model_free_record(
flow: str,
rail_type: str,

Build the per-rail GenerationLog record for a rail that reached no model.

nemoguardrails.guardrails.rails_manager._rail_call_record(
flow: str,
rail_type: str,
calls: collections.abc.Sequence[nemoguardrails.logging.explain.LLMCallInfo] = ()

Build the per-rail GenerationLog record from a rail’s result and the calls it made.

nemoguardrails.guardrails.rails_manager._rail_result(

Map an engine-neutral rail verdict onto IORails’ rail result.

nemoguardrails.guardrails.rails_manager._refuse_concurrent_rewrite(
flow: str
) -> None

Refuse a rewrite from a concurrent rail: peers read the arriving text, so it cannot compose.

nemoguardrails.guardrails.rails_manager._result_after_rewrites(
original_text: str,
final_text: str,

Report the text that survived every rail, so a rewrite undone by a later rail is no rewrite.

nemoguardrails.guardrails.rails_manager._rewriting_flows(
flows: collections.abc.Sequence[str]
) -> tuple[str, ...]

The configured flows whose surface declares they may rewrite the text they check.

nemoguardrails.guardrails.rails_manager._rewritten_text(
flow: str
) -> str

Return what a rail rewrote this direction’s variable to, ignoring any it also named.

A rail guarding both sides of a turn names both, and each direction takes its own, as the Colang flows do with the same verdict.

nemoguardrails.guardrails.rails_manager._tool_rail_result(
flow: str

Map a tool rail’s verdict, refusing a rewrite it has nowhere to apply.

nemoguardrails.guardrails.rails_manager._transforms_first(
rewriting: collections.abc.Sequence[str],
flows: collections.abc.Sequence[str]
) -> list[str]

Order rails that may rewrite ahead of rails that only judge, so a mask reaches the check.

nemoguardrails.guardrails.rails_manager._REWRITABLE_TARGET = {RailDirection.INPUT: TransformTarget.USER_MESSAGE, RailDirection.OUTPUT: Transf...
nemoguardrails.guardrails.rails_manager._SURFACE_DIRECTIONS = {RailDirection.INPUT: SurfaceDirection.INPUT, RailDirection.OUTPUT: SurfaceDirec...
nemoguardrails.guardrails.rails_manager._TOOL_ACTION_CLASSES: dict[str, type[ToolRailAction]] = {(cls.action_name): cls for cls in [ToolCallRailAction, ToolResultRailAction]}
nemoguardrails.guardrails.rails_manager._ToolActionT = TypeVar('_ToolActionT', bound=ToolRailAction)
nemoguardrails.guardrails.rails_manager.log = logging.getLogger(__name__)