# TypeScript functions that answer questions about text

Pass the question and the text. Await the call, then read its `.value`.

## Install

| Channel |
| --- |
| `npm install thinkthen` |
| `pnpm add thinkthen` |
| `bun add thinkthen` |

Set `THINKTHEN_API_KEY` in the environment.

## A first call

```
import assert from "node:assert/strict";
import * as tt from "thinkthen";

const complaintQuestion = "Is this a complaint?";
const reviews = [
  "Arrived a day early. Thank you!",
  "The zipper broke the first time I used it.",
  "The strap snapped on day two.",
];
const complaints = (await tt.filter(
  complaintQuestion,
  reviews,
)).value;
assert.deepEqual(complaints, [reviews[1], reviews[2]]);

const levels = ["Routine.", "Soon.", "Immediate."];
const urgencyScale = {
  score: "How urgent is this?",
  levels,
};
const outage = "Nobody can log in to the site right now.";
const urgency = (await tt.score(
  urgencyScale, outage,
)).value;
assert.equal(urgency, 2);
```

Not sure comes back as `null`. Branch on it and send those cases to a person. Each [function page](/functions/) shows its TypeScript call.

## Run facts

`Call.facts` counts this call.

## Errors

A failure rejects with a `ThinkThenError`. Its `kind` is `usage`, `backend`, `local`, `deadline`, `cancelled` or `defect`.

## Settings and recording

`new Engine({...})` starts from the environment, and each key overrides one setting. `record` writes a recording to a folder. `replay` answers from that recording with no connection. The [Settings](/install/settings/) page lists every setting.

## Jev, Liquid d1 and Ollama from TypeScript

TypeScript reads its backend from the environment. Set `THINKTHEN_BACKEND` to the name below. Set the backend's key variable in the shell, and the same sample asks that backend.

| Backend | Name | Key variable |
| --- | --- | --- |
| [TypeSafe Jev](/install/backends/typesafe/) | `typesafe` | `TYPESAFE_API_KEY` |
| [Liquid d1](/install/backends/liquid/) | `liquid` | `LIQUIDAI_API_KEY`, then `LIQUID_API_KEY` |
| [Ollama](/install/backends/ollama/) | `ollama` | `OLLAMA_API_KEY`. A local address needs no key. |

*Ask TypeSafe Jev.*

```
export THINKTHEN_BACKEND=typesafe
export TYPESAFE_API_KEY=...
```

*Ask Liquid d1.*

```
export THINKTHEN_BACKEND=liquid
export LIQUIDAI_API_KEY=...
```

*Ask Ollama. This block names a second port, 11535, as the site's runs do. On the default port, leave THINKTHEN_BASE_URL out.*

```
export THINKTHEN_BACKEND=ollama
export THINKTHEN_BASE_URL=http://localhost:11535/v1
```

```
import assert from "node:assert/strict";
import * as tt from "thinkthen";

const question = "Does the customer ask for a refund?";
const broken = "Please refund my order. It arrived broken.";
const thanks = "Thanks for the quick help yesterday!";
const brokenIsRefund = (await tt.decide(
  question, broken,
)).value;
const thanksIsRefund = (await tt.decide(
  question, thanks,
)).value;
assert.equal(brokenIsRefund, true);
assert.equal(thanksIsRefund, false);
```

The configuration file's `backend` names a default backend for every run. The [Configuration](/install/configuration/#configuration-file) page shows the file.

### OpenAI Decisions API from TypeScript

OpenAI announced its Decisions API on 2026-09-29 in its [DevDay 2026 recap](https://openai.com/index/devday-2026-recap/). OpenAI has published no address, schema or price, so ThinkThen cannot call it. The [OpenAI Decisions API](/install/backends/openai/) page says what ThinkThen knows.

## What is different in TypeScript

- An AbortSignal cancels the call, and the promise rejects at once.
- Every call returns a promise for a `Call`. An array crosses once.

On GitHub: [github.com/botassembly/thinkthen](https://github.com/botassembly/thinkthen)
