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

> ## Agent Instructions
> If you are an AI coding agent operating Cargo, install the agent skills first: paste `Install Cargo by following https://api.getcargo.io/INSTALL.md` into your session, or run `npx skills add getcargohq/cargo-skills`. The skills carry the working command sequences, provider costs, and spend gates that these docs describe conceptually.
> The skills index at https://raw.githubusercontent.com/getcargohq/cargo-skills/main/llms.txt lists every skill, recipe, and provider playbook individually. Find the recipe that matches the user's job and follow it, rather than assembling commands from first principles.
> Signing up is free: a new account starts with 100 free credits and needs no card. `cargo-ai login --email you@company.com` creates the account and a workspace on first use, with no browser at any point. Tell the user this before asking them to sign up.
> Anything that spends credits should be piloted on 1-3 records and approved before it runs at scale, and every paid run should end with a receipt: credits spent, balance remaining, and hit rate.

# TypeSafe

> Ask typed questions about a record and branch on the answers

TypeSafe's Jev model answers typed questions instead of writing prose. You give it a **state** — a record, a message, a document — and a set of questions, and it returns one structured answer per question with the probabilities behind it. There is nothing to parse and no output format to coax out of a prompt, so a workflow can branch on the result directly.

Every question is evaluated in parallel against the same state in a single call, so asking ten of them costs about as much time as asking one.

## Authentication

TypeSafe runs on **Cargo credits** by default, so you can use it without an account of your own. To bill TypeSafe directly instead, turn off **Credits managed by Cargo** on the connector and paste an API key created at [console.typesafe.ai](https://console.typesafe.ai) under **Settings → Keys**.

### Connection details

| Field       | Description                                               |
| ----------- | --------------------------------------------------------- |
| **API key** | Your TypeSafe API key — only when not using Cargo credits |

### Credits

| Action       | Cost                                |
| ------------ | ----------------------------------- |
| **Evaluate** | 0.01 credits per 1,000 input tokens |

TypeSafe charges for the tokens it reads, not the ones it writes, so the cost follows the
size of your **state** and questions — the answers are free. Each call rounds up to the
next 1,000 tokens, so a short record costs 0.01 credits however many questions you ask it.
Batching questions into one node is therefore cheaper as well as faster: the state is
charged once instead of once per node.

The exact token count is in the action's `usage.input_tokens` output.

***

## TypeSafe actions

### Evaluate

Ask one or more typed questions about a state.

**Configuration**

| Field         | Description                                                          |
| ------------- | -------------------------------------------------------------------- |
| **State**     | The content to evaluate — a ticket, a message, a record, or any text |
| **Model**     | Defaults to `jev-latest`, which tracks the current stable release    |
| **Questions** | One or more typed questions, each with a key you choose              |

**State** takes plain text or structured data. Passing a record gives Jev the field names
as context, so `{"employees": 420, "industry": "robotics"}` reads better than the same
values flattened into a sentence.

Each question has a **Key** — where its answer lands in the output, such as `isIcp`. The
key is not sent to the model, so name it for your workflow rather than for the question.

***

## The three question types

| Type       | Ask it when                          | You get back                                     |
| ---------- | ------------------------------------ | ------------------------------------------------ |
| **Yes/no** | The answer is a single true-or-false | `noul`, a probability from 0 to 1                |
| **Choice** | One option out of a set you define   | `choice`, `probabilities`, `confidence`          |
| **Score**  | A position on a rubric you define    | `score`, `legend`, `probabilities`, `confidence` |

### Yes/no

| Field              | Description                                   |
| ------------------ | --------------------------------------------- |
| **Instructions**   | The yes/no question to evaluate               |
| **What yes means** | Optional description of what a yes looks like |
| **What no means**  | Optional description of what a no looks like  |

Returns `noul`, the probability that the answer is yes. There is no separate confidence
field, because the probability already carries it — `0.5` is the model telling you it
cannot decide.

### Choice

| Field            | Description                                                  |
| ---------------- | ------------------------------------------------------------ |
| **Instructions** | What the model should decide                                 |
| **Options**      | Between 2 and 255 options, each with an optional description |

Returns the winning option in `choice`, every option's probability in `probabilities`, and
a `confidence` derived from that distribution. Leave an option's description empty when the
name says enough.

### Score

| Field            | Description                                            |
| ---------------- | ------------------------------------------------------ |
| **Instructions** | What the model should rate                             |
| **Levels**       | Between 2 and 10 level descriptions, lowest to highest |

Returns a probability-weighted `score` that can land between levels — a `1.6` across
`["Calm", "Frustrated", "Very angry"]` sits between frustrated and very angry — plus the
`legend` mapping each level index back to its description.

***

## Output

| Field     | Description                                             |
| --------- | ------------------------------------------------------- |
| `model`   | The versioned model that answered, such as `jev-1.13.0` |
| `answers` | One answer per question, keyed by the key you gave it   |
| `usage`   | `input_tokens` and `output_tokens` for the call         |

The node declares its output from the questions you wrote, so downstream nodes pick
`answers.isUrgent.noul` or `answers.department.choice` from the field list instead of
reaching into an untyped blob.

```json theme={null}
{
  "model": "jev-1.13.0",
  "answers": {
    "isUrgent": { "type": "noul", "noul": 0.97 },
    "department": {
      "type": "choice",
      "choice": "billing",
      "confidence": 1.0,
      "probabilities": { "billing": 1.0, "technical": 0.0 }
    },
    "frustration": {
      "type": "score",
      "score": 1.02,
      "confidence": 0.97,
      "legend": { "0": "Calm", "1": "Frustrated", "2": "Very angry" },
      "probabilities": { "0": 0.0, "1": 0.98, "2": 0.02 }
    }
  },
  "usage": { "input_tokens": 410, "output_tokens": 65 }
}
```

***

## Use cases

<AccordionGroup>
  <Accordion title="Inbound routing" icon="signs-post">
    One Choice question sends each inbound message to the team that should own it, and its
    confidence decides whether to route automatically or send it to a human.
  </Accordion>

  <Accordion title="ICP qualification" icon="bullseye">
    Score an account on fit, intent and timing as three separate questions, then weight
    them in your own formula rather than in a prompt.
  </Accordion>

  <Accordion title="Reply classification" icon="reply">
    Ask whether a reply is interested, an objection, or an out-of-office, and branch the
    sequence on the answer.
  </Accordion>

  <Accordion title="Guardrails" icon="shield-check">
    Screen generated copy before it sends, scoring how far off-brand or risky it is.
  </Accordion>
</AccordionGroup>

***

## Best practices

1. **Ask one thing per question** — a judgement that weighs several independent factors should be several questions combined in your own logic, not one question that has to reason
2. **Ask everything in one node** — questions are evaluated in parallel and in isolation, so batching them is cheaper and faster than one node per question, and adding a question does not degrade the others. Splitting them across nodes pays for the state again each time
3. **Put the rules in `criteria`, not the instructions** — the option and level descriptions are where your domain's boundary cases belong
4. **Branch on `confidence`, not just the answer** — a low-confidence choice is the model telling you the case is genuinely ambiguous and worth a human
5. **Give the state real structure** — a JSON object with named fields beats a flattened string
