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

# TypeSafe

> Meter and gate TypeSafe's Jev model: typed questions about your data, answered in one call.

[TypeSafe](https://typesafe.ai) makes **System One** models, starting with **Jev**, for fast, structured decisions inside software. You do not chat with Jev. You send it some **state**, such as a document, a support ticket or a user message, together with a set of **typed questions** about it, and get back typed answers your code can use directly:

* A **Noul** is a yes or no question, answered with the probability that the answer is yes.
* A **Choice** picks one option from a set you define.
* A **Score** rates the state on ordered levels you describe.

See TypeSafe's [introduction](https://docs.typesafe.ai/introduction) and [question types](https://docs.typesafe.ai/primitives).

## How it differs from a chat model

| | A chat model, such as Anthropic or OpenAI | TypeSafe |
| - | - | - |
| A call | One turn of a conversation | One state and any number of questions |
| The answer | Text, often streamed | Typed answers, returned all at once |
| Usage | Per turn, often with cache counters | One usage record for the whole call: input and output tokens |
| What drives the cost | Mostly the output | Mostly the input: the state is sent with every call |

That last row matters for budgets. Asking several questions in **one** call sends the state once. Asking them one call at a time sends the whole state again with every question. TypeSafe's own [fan-out pattern](https://docs.typesafe.ai/patterns/fan-out) recommends batching, and under a Stigg budget the difference is easy to see: thirteen questions about one document cost about one document's worth of input in a single call, and about thirteen when asked separately.

## Set up

Wrap a `TypeSafeClient` from `@typesafe-ai/sdk`. The SDK recognizes it automatically, and gates and meters its `systemOne` method.

```typescript theme={null}
import { TypeSafeClient, noul, choice } from '@typesafe-ai/sdk';

const typesafe = stigg.wrap(new TypeSafeClient({ apiKey: process.env.TYPESAFE_API_KEY }));

const { answers } = await typesafe.systemOne({
  model: 'jev-latest',
  state: { ticket },
  questions: {
    is_refund_request: noul('Is the customer asking for a refund?'),
    urgency: choice('How urgent is this ticket?', {
      Low: 'Can wait for the normal queue.',
      High: 'Needs a reply today.',
    }),
  },
  stiggContext: { customerId: 'customer-acme', entitlement: { currencyId: 'credits' } },
});
```

Every `systemOne` call is checked before it is sent and metered when the answers arrive. If access is denied, the questions are never sent, so they are never paid for. See [Handling denied access](/documentation/ai-agents/llm-wrappers/gating#handling-denied-access).

For the client itself, see TypeSafe's [JavaScript SDK docs](https://docs.typesafe.ai/sdk/javascript).

### Requested usage

Because the cost of a TypeSafe call is mostly its input, the best estimate of a call's usage is the size of the state, and you know it before the call. `estimateFromState(tokensPerUnit, charsPerToken)` estimates the input tokens from the state's length (4 characters per token by default) and uses that as the [requested usage](/documentation/ai-agents/llm-wrappers/gating#requested-usage) of the check, so a call the balance cannot cover is denied before it is sent:

```typescript theme={null}
import { typesafeRecipe, estimateFromState } from '@stigg/agent-sdk-js';

const recipe = {
  ...typesafeRecipe,
  methods: typesafeRecipe.methods.map((m) => ({ ...m, estimate: estimateFromState(1_000) })),
};
const typesafe = stigg.wrap(new TypeSafeClient({ apiKey }), { recipe });
```

The estimate is deliberately low rather than high, because an estimate that is too high denies calls the balance could have covered. The real usage is reported after the call either way.

## What is reported

Every `systemOne` response includes a `usage` object with the input and output tokens of the whole call. The wrapper reads it and reports these metrics:

| Method | Event name |
| - | - |
| `systemOne` | `typesafe.systemOne` |

| Metric | What it counts |
| - | - |
| `input_tokens` | Input tokens: the state and the questions |
| `output_tokens` | Output tokens: the answers |
| `total_tokens` | The sum of the two, added up by the SDK because TypeSafe does not report a total |

Price `total_tokens`, or the two parts, but never both. There are no cache counters, because a call is not part of a conversation, and no `cost`, because TypeSafe is not a gateway.

Every usage field TypeSafe returns is also included, with a `raw.` prefix. See [How usage is reported](/documentation/ai-agents/llm-wrappers/supported-providers#how-usage-is-reported).


## Related topics

- [Supported providers and gateways](/documentation/ai-agents/llm-wrappers/supported-providers.md)
- [Agent SDK](/api-and-sdks/references/sdk/backend/graphql/agent-sdk.md)
- [Gating calls](/documentation/ai-agents/llm-wrappers/gating.md)
- [JavaScript](/api-and-sdks/changelog/agent-sdk/javascript.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.