Skip to content

Human Message Guardrail

The Human Message Guardrail node matches the current user message against a list of regex patterns (one per string in a string storage) and branches the graph on the result. Typical use: short-circuit disallowed, off-topic, or jailbreak-style inputs to a canned-response node before they reach a Generate node.

Patterns are compiled once at agent creation and matched with std::regex_search — i.e. a pattern hits if it matches anywhere in the message, case-insensitively.

NodeType: HumanMessageGuardrail.

Parameters

All parameters are optional. The node resolves its pattern source in the same priority order as Canned Response.

Source resolution (priority order)

Priority Key Mutable Description
1 string_storage Yes Name of a string storage whose strings are each a regex pattern. Can be rebound at runtime via ChangeParam; new patterns are recompiled immediately (rollback on failure).
2 pattern_0, pattern_1, ... No Inline patterns directly on the node params.
3 (none) The server default file (default_guardrail_patterns_path in server-config.json).

Patterns are matched case-insensitively. Any compilation error at agent-creation time fails graph validation with error 3003.

Exit routes

Route Fires when
triggered At least one pattern matched the user message.
not_triggered No patterns matched.

Both routes must be wired.

Side effects

None on the dialog. The node does not modify the current interaction, does not emit AnswerText frames, and does not touch the KV cache. It is pure routing.

Minimum working example

from tryll_client import GraphDescription, NodeType

client.create_string_storage(
    name="jailbreak_patterns",
    strings=[
        r"ignore\s+previous\s+instructions?",
        r"you\s+are\s+DAN",
    ],
)

graph = (
    GraphDescription()
    .add_node("guard",  NodeType.HumanMessageGuardrail,
              {"string_storage": "jailbreak_patterns"})
    .add_node("refuse", NodeType.CannedResponse)  # uses server default
    .add_node("answer", NodeType.Generate)
    .wire("guard",  "triggered",     "refuse")
    .wire("guard",  "not_triggered", "answer")
    .wire("refuse", "default",       "END")
    .wire("answer", "default",       "END")
    .set_start_node("guard")
    .set_default_model_name("My Local Model")
)

agent = client.create_agent(graph)
namespace TC = Tryll::Client;

client.CreateStringStorage("jailbreak_patterns", {
    R"(ignore\s+previous\s+instructions?)",
    R"(you\s+are\s+DAN)",
});

TC::GraphDescription graph;
graph.AddNode("guard",  TC::NodeType::HumanMessageGuardrail,
              {{"string_storage", "jailbreak_patterns"}})
     .AddNode("refuse", TC::NodeType::CannedResponse)  // uses server default
     .AddNode("answer", TC::NodeType::Generate)
     .Wire("guard",  "triggered",     "refuse")
     .Wire("guard",  "not_triggered", "answer")
     .Wire("refuse", "default",       "END")
     .Wire("answer", "default",       "END")
     .SetStartNode("guard")
     .SetDefaultModelName("My Local Model");

auto agent = client.CreateAgent(graph);
auto* subsystem = GetGameInstance()->GetSubsystem<UTryllSubsystem>();
subsystem->RequestCreateStringStorage(
    TEXT("jailbreak_patterns"),
    { TEXT(R"(ignore\s+previous\s+instructions?)"),
      TEXT(R"(you\s+are\s+DAN)") });

FTryllGraphDescription Graph = FTryllGraphBuilder()
    .AddNode(TEXT("guard"),  ETryllNodeType::HumanMessageGuardrail,
             {{TEXT("string_storage"), TEXT("jailbreak_patterns")}})
    .AddNode(TEXT("refuse"), ETryllNodeType::CannedResponse)
    .AddNode(TEXT("answer"), ETryllNodeType::Generate)
    .Wire(TEXT("guard"),  TEXT("triggered"),     TEXT("refuse"))
    .Wire(TEXT("guard"),  TEXT("not_triggered"), TEXT("answer"))
    .Wire(TEXT("refuse"), TEXT("default"),       TEXT("END"))
    .Wire(TEXT("answer"), TEXT("default"),       TEXT("END"))
    .SetStartNode(TEXT("guard"))
    .SetDefaultModelName(TEXT("My Local Model"))
    .Build();

See the full flow in How to use canned responses and guardrails.

Client bindings

  • C++: Tryll::Client::GraphDescription::AddNode(name, NodeType::HumanMessageGuardrail, params)GraphDescription.h
  • Python: tryll_client.GraphDescription.add_node(name, NodeType.HumanMessageGuardrail, params)graph.py
  • Unreal: add an FTryllNodeDesc with Type = HumanMessageGuardrail to FTryllGraphDescription.NodesTryllGraphDescription.h