# Ruby functions that answer questions about text

Any Enumerable goes in. Read the answer from `Call#value`.

## Install

| Channel |
| --- |
| `gem install thinkthen` |

Set `THINKTHEN_API_KEY` in the environment.

## A first call

```
require "thinkthen"

question = "Which line gives the refund deadline?"
policy = [
  "Returns need the original receipt.",
  "Refunds are issued within 30 days of purchase.",
  "Shipping is free on orders over $50.",
  "Gift cards cannot be exchanged for cash."
]
refund_deadline = ThinkThen.find(question, policy).value
raise unless refund_deadline.unit == policy[1]

question = "Which labels fit this message?"
labels = ["praise", "bug", "billing"]
message =
  "Love the new dashboard, but export crashes the app,\n" \
  "and I was charged twice.\n"
fitting_labels = ThinkThen.tag(
  question, message, labels:
).value
raise unless fitting_labels == ["praise", "bug", "billing"]
```

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

## Run facts

`Call#facts` counts this call.

## Errors

Every failure raises a `ThinkThen::Error`. Its subclass names the kind: `UsageError`, `BackendError`, `LocalError`, `DeadlineError`, `DefectError` or `CancelledError`.

## Settings and recording

`Engine.new` takes each setting as a keyword and reads the environment for the rest. `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 Ruby

Ruby 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
```

```
require "thinkthen"

question = "Does the customer ask for a refund?"
broken = "Please refund my order. It arrived broken."
thanks = "Thanks for the quick help yesterday!"
broken_is_refund = ThinkThen.decide(question, broken).value
thanks_is_refund = ThinkThen.decide(question, thanks).value
raise unless broken_is_refund == true
raise unless thanks_is_refund == 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 Ruby

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 Ruby

- Any Enumerable crosses to the engine once.

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