# Decisions

> Ask a model a fixed set of questions about a piece of text and get back typed answers with probabilities, instead of prose you have to parse.

- Canonical: https://tchavi.com/en/docs/decisions

---


<Endpoint method="POST" path="/v1/decisions" />

A decision model answers a **fixed set of questions** about a piece of text and returns typed answers with probabilities. Use it where you would otherwise ask a chat model for JSON and hope it complies: routing a ticket to a team, scoring urgency, flagging whether a conversation is blocked.

The difference from `/v1/chat/completions` is that the shape of the answer is guaranteed. You declare the questions, so there is nothing to parse and nothing to retry when the model wraps its JSON in an apology.

Decision models only work on this endpoint. Sending `jev-1.13` to `/v1/chat/completions` returns a `400`, and sending a chat model here returns a `400` as well.

## Questions

`state` is the text being judged. `questions` is a map of your own names to a question. Three types, and the `criteria` field differs between them:

| type     | ask it                       | `criteria`                        | you get back               |
| -------- | ---------------------------- | --------------------------------- | -------------------------- |
| `choice` | pick one of several labels   | a map of label → what it means    | `choice` + `probabilities` |
| `score`  | place it on an ordered scale | an **ordered** array, low to high | `score` + `legend`         |
| `noul`   | how likely is this true      | none                              | `noul`, between 0 and 1    |

The names are yours: `answers` comes back keyed by exactly the names you sent.

## Example

<CodeTabs>

```tchavi
import Tchavi from '@tchavi/sdk';

const client = new Tchavi({ apiKey: 'YOUR_API_KEY' });

const result = await client.decisions.create({
  model: 'jev-1.13',
  state: "Customer writes: 'My API key stopped working after I rotated it.'",
  questions: {
    team: {
      type: 'choice',
      instructions: 'Which team should handle this?',
      criteria: { billing: 'payments or credits', technical: 'API, keys' },
    },
    urgency: {
      type: 'score',
      instructions: 'How urgent is this?',
      criteria: ['not urgent', 'normal', 'urgent', 'critical'],
    },
    blocked: {
      type: 'noul',
      instructions: 'Is the customer unable to use the product?',
    },
  },
});

// Answers are discriminated on `type`.
if (result.answers.team.type === 'choice') {
  console.log(result.answers.team.choice, result.answers.team.probabilities);
}
if (result.answers.blocked.type === 'noul') {
  console.log('blocked likelihood:', result.answers.blocked.noul);
}
```

```javascript
const response = await fetch('https://tchavi.com/api/v1/decisions', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer YOUR_API_KEY',
  },
  body: JSON.stringify({
    model: 'jev-1.13',
    state: "Customer writes: 'My API key stopped working after I rotated it.'",
    questions: {
      team: {
        type: 'choice',
        instructions: 'Which team should handle this?',
        criteria: { billing: 'payments or credits', technical: 'API, keys' },
      },
      urgency: {
        type: 'score',
        instructions: 'How urgent is this?',
        criteria: ['not urgent', 'normal', 'urgent', 'critical'],
      },
      blocked: { type: 'noul', instructions: 'Is the customer unable to use the product?' },
    },
  }),
});

const result = await response.json();
console.log(result.answers);
console.log('credits used:', response.headers.get('x-credits-used'));
```

```python
import requests

response = requests.post(
    "https://tchavi.com/api/v1/decisions",
    headers={
        "Content-Type": "application/json",
        "Authorization": "Bearer YOUR_API_KEY",
    },
    json={
        "model": "jev-1.13",
        "state": "Customer writes: 'My API key stopped working after I rotated it.'",
        "questions": {
            "team": {
                "type": "choice",
                "instructions": "Which team should handle this?",
                "criteria": {"billing": "payments or credits", "technical": "API, keys"},
            },
            "urgency": {
                "type": "score",
                "instructions": "How urgent is this?",
                "criteria": ["not urgent", "normal", "urgent", "critical"],
            },
            "blocked": {
                "type": "noul",
                "instructions": "Is the customer unable to use the product?",
            },
        },
    },
)

result = response.json()
print(result["answers"])
print("credits used:", response.headers.get("x-credits-used"))
```

```curl
curl -X POST https://tchavi.com/api/v1/decisions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "jev-1.13",
    "state": "Customer writes: My API key stopped working after I rotated it.",
    "questions": {
      "team": {
        "type": "choice",
        "instructions": "Which team should handle this?",
        "criteria": { "billing": "payments or credits", "technical": "API, keys" }
      },
      "urgency": {
        "type": "score",
        "instructions": "How urgent is this?",
        "criteria": ["not urgent", "normal", "urgent", "critical"]
      },
      "blocked": {
        "type": "noul",
        "instructions": "Is the customer unable to use the product?"
      }
    }
  }'
```

</CodeTabs>

## The response

```json
{
  "model": "jev-1.13.0",
  "answers": {
    "team": {
      "type": "choice",
      "choice": "technical",
      "confidence": 1,
      "probabilities": { "billing": 0, "technical": 1 }
    },
    "urgency": {
      "type": "score",
      "score": 1.67,
      "confidence": 0.65,
      "legend": { "0": "not urgent", "1": "normal", "2": "urgent", "3": "critical" },
      "probabilities": { "0": 0, "1": 0.34, "2": 0.65, "3": 0.01 }
    },
    "blocked": { "type": "noul", "noul": 0.76 }
  },
  "usage": { "input_tokens": 382, "output_tokens": 62 }
}
```

A `score` is continuous, not an index: `1.67` sits between `normal` and `urgent` and leans urgent. `legend` maps the positions back to the labels you sent, so you can round or threshold however your workflow needs.

`confidence` is the model's own certainty. On `choice` it is the winning label's probability; a low one is your signal to escalate to a human rather than act on the answer.

## Credits

A decision response is the provider's own body, so the cost is in the headers rather than in the JSON:

```
X-Credits-Used: 0.001
X-Credits-Remaining: 115397.775
```

Decisions are priced per token like any other model, and they are cheap — the example above costs a thousandth of a credit. That is the point: a decision model is meant to run on every message, not on the ones you have already decided are worth a large model.

