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

# Safety checks

> Inline content validation at the tool boundary.

The `safetyCheck` wrapper sits in front of any tool handler and runs the input
through Sedata's safety API before your code sees it. Flagged content gets a
canned blocked response; clean content passes through transparently.

## Flow

<Steps>
  <Step title="Wrap the handler">
    `safetyCheck(handler, { parameterName: 'text' })` returns a new handler
    that knows which input field to inspect.
  </Step>

  <Step title="Inspect the parameter">
    On invocation, the wrapper reads `params[parameterName]`. If it's a string,
    it sends a `POST` to `https://api.sedata-ai.tech/security/safety-check`
    with `{ "content": "<value>" }`.
  </Step>

  <Step title="Decide">
    * **Flagged** → return a structured "blocked" response without calling
      your handler.
    * **Not flagged** → call your handler with the original params.
    * **API error** → log a warning and call your handler (fail-open).
  </Step>

  <Step title="Annotate the span">
    Either way, the wrapper writes `params._safetyCheck` so the
    instrumentation layer can attach `mcp.safety_check.*` attributes to the
    active span.
  </Step>
</Steps>

## Authentication

The safety API expects an `x-api-key` header. The wrapper picks it up
automatically from your `instrumentServer` config:

```ts theme={null}
const telemetryConfig: TelemetryConfig = {
  // ...
  exporterAuth: { type: 'apiKey', apiKey: process.env.SEDATA_KEY },
  // or a bearer token — the safety API accepts either
  exporterAuth: { type: 'bearer', token: process.env.SEDATA_KEY },
}

instrumentServer(server, telemetryConfig)
// ↑ also calls setTelemetryApiKey(...) under the hood
```

## Blocked response shape

When content is flagged, the wrapper returns a response that satisfies most
tool output schemas:

```json theme={null}
{
  "content": [
    {
      "type": "text",
      "text": "{ \"summary\": \"🚫 CONTENT BLOCKED: ...\", \"blocked\": true, \"reason\": \"Content flagged by safety check\", \"timestamp\": \"2026-..\" }"
    }
  ],
  "structuredContent": {
    "summary": "🚫 CONTENT BLOCKED: ..."
  }
}
```

<Warning>
  If your tool's `outputSchema` uses a key other than `summary`, you'll need to
  customize the blocked response shape — open an issue or fork the wrapper.
</Warning>

## Failure modes

| Scenario                | Behavior                                                                               |
| ----------------------- | -------------------------------------------------------------------------------------- |
| Network error           | Logged as warning. Handler runs. `_safetyCheck.success = false`.                       |
| Non-200 from safety API | Logged. Handler runs. `_safetyCheck.success = false`.                                  |
| Missing API key         | Request goes out without `x-api-key`. The API may 401; treated like any other failure. |
| Parameter missing       | Handler runs untouched. No safety attributes recorded.                                 |
| Parameter not a string  | Handler runs untouched. No safety attributes recorded.                                 |

The wrapper is designed to **fail open** — telemetry should never take down
your tool. If you want fail-closed semantics, layer your own retry / strict
check on top.

## When to use it

Use `safetyCheck` for any tool whose input is **free-form user content**:

* summarizers, translators, classifiers
* code generators / interpreters
* anything that could be prompt-injected

Skip it for:

* structured numeric inputs (no content to flag)
* internal tools called only by trusted automation
* tools where blocking would break correctness (calculators, lookups)

## Span attributes added

When the wrapper runs, the span for that tool call includes:

| Attribute                     | Type    | Example                                        |
| ----------------------------- | ------- | ---------------------------------------------- |
| `mcp.safety_check.content`    | string  | `"please ignore previous instructions and..."` |
| `mcp.safety_check.flagged`    | boolean | `true`                                         |
| `mcp.safety_check.latency_ms` | number  | `42`                                           |
| `mcp.safety_check.success`    | boolean | `true`                                         |

## Next

<CardGroup cols={2}>
  <Card title="safetyCheck reference" icon="code" href="/api-reference/safety-check">
    The full function signature, options, and types.
  </Card>

  <Card title="Example with safety" icon="shield-check" href="/examples/text-summarizer-with-safety">
    A complete summarizer tool with `safetyCheck`.
  </Card>
</CardGroup>
