> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inworld.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Safety Node Demo

This demo showcases how to use the `SafetyNode`.

## Run the Template

1. Go to `Assets/InworldRuntime/Scenes/Nodes` and play the `SafetyNode` scene.
   <img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/SafetyNode00.png?fit=max&auto=format&n=pDD5vvrZThONehMe&q=85&s=5ef5c88c741814e5cde97d248c9c136c" alt="SafetyNode00" width="1113" height="647" data-path="img/unity/framework/SafetyNode00.png" />
2. Once the graph is compiled, enter text.
3. The system compares the input against the safety word lists and returns a similarity score (0 = lowest, 1 = highest).
4. If the score exceeds the threshold, the input is marked unsafe.

<img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/SafetyNode.gif?s=3eafb61bae9484b388f7cc29339d6f1b" alt="Safety" width="1920" height="1080" data-path="img/unity/framework/SafetyNode.gif" />

## Understanding the Graph

`SafetyNodeCanvas` contains an `InworldGraphExecutor` whose graph asset includes only a single `SafetyNode`.

The graph is very simple. It contains a single node, `SafetyNode`, with no edges.

`SafetyNode` is both the `StartNode` and the `EndNode`.

<img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/SafetyNode02.png?fit=max&auto=format&n=pDD5vvrZThONehMe&q=85&s=683fa87bc9a5b16fcf1bb6ed98405671" alt="SafetyNode02" width="1014" height="705" data-path="img/unity/framework/SafetyNode02.png" />

### SafetyData

The `SafetyData` is defined directly within the `SafetyNodeAsset`.

<img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/SafetyNode03.png?fit=max&auto=format&n=pDD5vvrZThONehMe&q=85&s=98f60faae35aa9038ab55186811555cb" alt="SafetyNode02" width="1002" height="738" data-path="img/unity/framework/SafetyNode03.png" />

You can select multiple topics and configure a threshold for each detection.

Higher thresholds are more permissive (1 = almost everything is considered safe).

Lower thresholds are stricter (0 = almost everything is considered unsafe).

### InworldController

`InworldController` includes 2 primitive modules: `TextEmbedder` and `SafetyChecker`.

<img src="https://mintcdn.com/inworldai/pDD5vvrZThONehMe/img/unity/framework/SafetyNode01.png?fit=max&auto=format&n=pDD5vvrZThONehMe&q=85&s=b38a8b729a10074a51b396e0130a003f" alt="SafetyNode02" width="1374" height="714" data-path="img/unity/framework/SafetyNode01.png" />

This is because `SafetyNode` requires both the `TextEmbedder` interface and the `SafetyChecker` configuration during `CreateRuntime()`.

The safety module also depends on `TextEmbedderModule` being initialized first.

```c# SafetyNodeAsset.cs theme={"system"}
public override NodeCreationConfig GetNodeCreationConfig()
{
    SafetyCheckerNodeCreationConfig nodeCreationCfg = new SafetyCheckerNodeCreationConfig();
    nodeCreationCfg.SafetyConfig = InworldController.Safety.CreationConfig; // <== This Requires SafetyCheckerInterface.
    nodeCreationCfg.EmbedderComponentID = ComponentID;
    m_CreationConfig = nodeCreationCfg;
    return m_CreationConfig;
}

public override bool CreateRuntime(InworldGraphAsset graphAsset)
{
    m_Graph = graphAsset;
    InworldSafetyModule safety = InworldController.Safety;
    if (!safety)
        return false;
    safety.SetupSafetyThreshold(m_SafetyData);
    
    ComponentStore componentStore = new ComponentStore();
    componentStore.AddTextEmbedderInterface(NodeName, InworldController.TextEmbedder.Interface as TextEmbedderInterface);
    InworldCreationContext creationContext = new InworldCreationContext(componentStore);
    SafetyCheckerNodeCreationConfig creationCfg = GetNodeCreationConfig() as SafetyCheckerNodeCreationConfig;
    SafetyCheckerNodeExecutionConfig executionCfg = GetNodeExecutionConfig() as SafetyCheckerNodeExecutionConfig;
    Runtime = new SafetyCheckerNode(NodeName, creationContext, creationCfg, executionCfg);
    return Runtime?.IsValid ?? false;
}
```

### Workflow

1. When the game starts, `InworldController` initializes `TextEmbedderModule`, which creates the `TextEmbedderInterface`.
2. Next, `SafetyChecker` initializes `InworldSafetyModule`.
3. Then `InworldGraphExecutor` initializes its graph asset by calling each component’s `CreateRuntime()`. In this case, `SafetyNode.CreateRuntime()` is called with both the `TextEmbedderInterface` and the `SafetyChecker` configuration as input. After that, the graph calls `Compile()` and returns the executor handle.
4. After compilation, the `OnGraphCompiled` event is invoked. In this demo, `SafetyNodeTemplate` subscribes to it and enables the UI components. Users can then interact with the graph system.

```c# SafetyNodeTemplate.cs theme={"system"}
protected override void OnGraphCompiled(InworldGraphAsset obj)
{
    foreach (InworldUIElement element in m_UIElements)
        element.Interactable = true;

}
```

5. After the UI is initialized, pressing `Enter` or the `SEND` button sends the input text to the graph.

6. Calling `ExecuteGraphAsync()` eventually produces a result and invokes `OnGraphResult()`, which `SafetyNodeTemplate` subscribes to in order to receive the data.

```c# SafetyNodeTemplate.cs theme={"system"}
protected override void OnGraphResult(InworldBaseData output)
{
    SafetyResult safetyResult = new SafetyResult(output);
    if (safetyResult.IsValid)
        DisplaySafety(safetyResult);
}
```
