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

# Drex (Decision Model)

> Drex, NDI's decision model, answers typed questions about a state in one System One call

**Drex** is NDI's decision model. **System One** is the topology it runs in:
one synchronous call in which Drex answers every question about a state, with no
agent loop, job or workspace. The endpoint, SDK resource, CLI command and MCP
tool are named `systemone` after it.

`systemone.evaluate` answers typed questions about a state — text, or any JSON
value — in one synchronous call. There is no workspace and no job: the answers
are the response. Each question is keyed by a name you choose, and its answer
comes back under the same name.

| Question `type` | Answer |
| - | - |
| `noul` | `noul`: the probability that the question is true |
| `choice` | `choice`: the likeliest option, with `confidence` and every option's `probabilities` |
| `score` | `score`: the expected level index on your scale (`0` is the lowest), with `legend`, `probabilities` per level index, and `confidence` |

***

## Evaluate a state

```ts theme={"dark"}
import { NdiClient, UnknownAnswer } from "ndi-sdk";

const client = new NdiClient();
const result = await client.systemone.evaluate({
  state: { vendor: "Acme Freight", amount: 1200, purchase_order: "PO-4411" },
  questions: {
    approve: {
      type: "noul",
      criteria: { true: "The invoice matches an open purchase order", false: "No purchase order covers it" },
    },
    risk: {
      type: "choice",
      instructions: "How risky is paying this invoice?",
      criteria: { low: null, high: "Unusual vendor, amount, or terms" },
    },
    urgency: { type: "score", criteria: ["not urgent", "this week", "today"] },
  },
});

for (const [name, answer] of Object.entries(result.answers)) {
  if (answer instanceof UnknownAnswer) {
    console.log(name, answer.type, answer.data);
  } else if (answer.type === "noul") {
    console.log(name, answer.noul);
  } else if (answer.type === "choice") {
    console.log(name, answer.choice, answer.probabilities);
  } else {
    console.log(name, answer.legend[Math.round(answer.score)], answer.probabilities);
  }
}
```

A `noul` question needs `instructions` or at least one criterion. A `choice`
question lists its options as `criteria` keys; a `null` value means the option
name says enough. A `score` question lists its levels lowest first.

`confidence` is Drex's average confidence in the answer. It tracks
the highest probability but is a different number; do not derive one from the
other. `legend[Math.round(score)]` names the level nearest the expected score,
which is not always the most likely level; for that, take the highest entry in
`probabilities`. Limits and input rules are on [Drex (Decision Model)](/api-reference/systemone#limits-and-input-rules).

A refused request raises `InvalidRequestError`. Its `body.detail.issues` lists
each problem by path, such as `questions.risk.criteria`. A missing or invalid
API key raises `AuthenticationError` (`401`), and a deployment without a
decision model answers `501` (`NotImplementedByServerError`). The SDK does not
retry `evaluate` on its own: `RateLimitError` (`429`) and `ServerError`
(`503 upstream_unavailable`, including a model that did not answer within 45
seconds) are safe to retry yourself, since nothing is stored.

***

## Method signature

```text theme={"dark"}
evaluate(
  opts: {
    state: SystemOneState;
    questions: Record<string, Question>;
  },
): Promise<SystemOneResponse>
```

### Parameters

| Parameter | Type | Required | Description |
| - | - | - | - |
| `opts.state` | `SystemOneState` | Yes | The situation to decide about: text, or any JSON value |
| `opts.questions` | `Record<string, Question>` | Yes | Questions keyed by a name of your choice; each is a `NoulQuestion`, `ChoiceQuestion`, or `ScoreQuestion` |

### Returns

A `SystemOneResponse`: `answers` keyed as the questions were, the `model` that
answered, token `usage`, `evaluation_time_ms`, and `request_id`. An answer type
newer than this SDK arrives as an `UnknownAnswer` carrying the raw answer in
`data`.


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