# Guardrails — three different things

TnsAI uses the word **guardrail** for three distinct APIs in three modules.
They are not interchangeable: different types, different call sites, different
imports. Pick by *when* you need to gate something.

| What you want | Type | Module | When it runs |
|---|---|---|---|
| Validate or sanitize an action's input/output | `@InputGuardrail` / `@OutputGuardrail` | `tnsai-core` (`com.tnsai.annotations`, enforced by `com.tnsai.guardrails.*Enforcer`) | Immediately before / after the action body |
| Allow or block an agent action in a multi-agent group | `com.tnsai.coordination.supervisor.Guardrail` | `tnsai-coordination` | Every action request routed through `SupervisorAgent` |
| Score traced text for PII, toxicity, off-topic | `com.tnsai.quality.tracing.guardrail.Guardrail` | `tnsai-quality` | Pre/post response on traced input+output (`GuardrailRegistry`) |

The two `Guardrail` interfaces share a name and nothing else. Import the FQN;
IDE auto-import will happily pick the wrong one.

This page is discovery only. It does not rename the types.

## Action I/O — `@InputGuardrail` / `@OutputGuardrail`

Per-action (or role-default) field checks: length bounds, deny/allow patterns,
validators, sanitizers. Wired today — see [runtime status](../reference/annotations/runtime-status.md).

```java
@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?" Not "is this *agent* allowed to call deploy?"

TnsAI 0.14.0 ([PR #168](https://github.com/TnsAI-Framework/TnsAI/pull/168)
(TAN-3016) adds `PiiInputValidator` / `PiiInputSanitizer` on this
annotation. That is action-input detection, not `PiiGuardrail` below.
See [PII input guardrails](pii-input-guardrails.md).

More on approvals and `@Security`: [Approvals and Annotations](approvals-and-annotations.md).

## Supervisor permission — `com.tnsai.coordination.supervisor.Guardrail`

`SupervisorAgent` asks each registered guardrail `check(agentId, action, context)`
before the action runs. The result is allow / warn / block (`GuardrailSeverity`).
Typical uses: read-only mode, budget caps, HITL on `deploy` / `delete`.

```java
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"));
```

Use this when the question is "may this *agent* perform this *action*?"
Worked example: [SupervisorAgent with Guardrails](../multi-agent/advanced.md#supervisoragent-with-guardrails).

## Content evaluation — `com.tnsai.quality.tracing.guardrail.Guardrail`

Observability SPI. Implementations (`PiiGuardrail`, custom toxicity checks)
register on `GuardrailRegistry` and `evaluate(input, output)` after (or before)
a traced response. This is content quality, not action authorization and not
`@InputGuardrail` field validation.

```java
GuardrailRegistry registry = new GuardrailRegistry();
registry.registerPostResponse(new PiiGuardrail());
List<GuardrailResult> results = registry.evaluatePostResponse(input, output);
```

Use this when the question is "does this *text* leak PII or fail a quality
check?" Full API: [Content Guardrails](../validation.md#advanced-content-guardrails).

## You might also be looking for

- [Approvals and Annotations](approvals-and-annotations.md) — `@ApprovalRequired`, `@Security`
- [Prompt Injection](prompt-injection.md) — detection, not the three Guardrail types
- [Redaction](redaction.md) — `Redactor` SPI for stripping secrets from output
- [Annotation catalog](../reference/annotations/catalog.md) — `@InputGuardrail` / `@OutputGuardrail` fields
