Skip to content
tnsaiDocs
GitHub

Guardrails: three different things

TnsAI uses the word guardrail for three different APIs in three modules. They have different types, call sites and imports, so pick by what you need to gate.

What you wantTypeModuleWhen it runs
Validate or sanitize an action's input or output@InputGuardrail / @OutputGuardrailtnsai-core (com.tnsai.annotations, enforced by com.tnsai.guardrails.*Enforcer)Immediately before or after the action body
Allow or block an agent action in a multi-agent groupcom.tnsai.coordination.supervisor.Guardrailtnsai-coordinationWhen your code calls SupervisorAgent.checkAction
Check traced text for PII or other content rulescom.tnsai.quality.tracing.guardrail.Guardrailtnsai-qualityWhen your code evaluates a GuardrailRegistry

The two Guardrail interfaces share a name and nothing else. Import the fully qualified name, because IDE auto-import can pick the wrong one.

Action input and output

@InputGuardrail and @OutputGuardrail check an action's parameters and result: length bounds, deny and allow patterns, validators and sanitizers. They apply per action or as a role default.

@ActionSpec(type = ActionType.LOCAL, description = "Process user message")
@InputGuardrail(maxLength = 10_000, blockPatterns = {"ignore previous"})
@OutputGuardrail(maxLength = 8_000)
public String processMessage(String message) {
    return message;
}

Use this when the question is "is this payload safe to enter or leave this method?"

Warning: @InputGuardrail(detectInjection) defaults to true, but nothing reads it at runtime. The same holds for jsonSchema, moderateContent and blockCategories. Setting them gives no protection. For injection detection, call PromptInjectionDetector yourself; see Prompt injection. Runtime status lists which fields are enforced.

PiiInputValidator and PiiInputSanitizer in tnsai-core plug into this annotation to reject or mask PII in action input. See PII input guardrails.

Supervisor permission

SupervisorAgent.checkAction(agentId, action, context) asks each registered guardrail in order. It returns the first block, or the last guardrail's result when none blocks. A guardrail that throws counts as a block. Nothing intercepts actions for you: call checkAction before you run the action and act on the result.

SupervisorAgent supervisor = new SupervisorAgent(group, List.of(
    new HITLApproval(Set.of("deploy", "delete"), approvalCallback)));

Guardrail.GuardrailResult result =
    supervisor.checkAction("agent-1", "deploy", Map.of("target", "production"));
if (!result.allowed()) {
    throw new IllegalStateException(result.reason());
}

A result carries allowed, reason and a GuardrailSeverity of INFO, WARNING or BLOCK. Use this when the question is "may this agent perform this action?"

Content checks on traced text

The tnsai-quality guardrail scores text after (or before) a response. PiiGuardrail is a regex detector for email addresses, phone numbers and SSN-like numbers. GuardrailResult is a record of passed, score and reason.

package com.example.tnsai.docs;

import com.tnsai.quality.tracing.guardrail.GuardrailResult;
import com.tnsai.quality.tracing.guardrail.PiiGuardrail;

public final class ObservabilityPiiGuardrailExample {
    private ObservabilityPiiGuardrailExample() {}

    public static GuardrailResult scan(String input, String output) {
        PiiGuardrail piiGuard = new PiiGuardrail();
        GuardrailResult result = piiGuard.evaluate(input, output);
        if (!result.passed()) {
            System.out.println("PII detected: " + result.reason());
        }
        return result;
    }
}

To run several checks, register them on a GuardrailRegistry with registerPreResponse or registerPostResponse, then call evaluatePostResponse(input, output) or allPostResponsePass(input, output). AgentBuilder does not wire these guardrails in; your code runs them.

Use this when the question is "does this text leak PII or fail a content rule?"