ThinkThen

C++ functions that answer questions about text

One C++17 header over the C library. Calls return CallResult values. The engine frees itself when it goes out of scope.

Install

ChannelNote
thinkthen-cpp-VERSION-TARGET.tar.gzThe header and a CMake package, from each release.
thinkthen-c-VERSION-TARGET.tar.gzThe C library it calls, from the same release.

Set THINKTHEN_API_KEY in the environment.

A first call

#include <cassert>
#include <thinkthen/door.hpp>

int main() {
    auto engine = tt::create();

    const char *question =
        "Does the customer ask for a refund?";
    auto is_refund = tt::decide(
        engine,
        question,
        "Please refund my order. It arrived broken.");
    assert(is_refund.value.outcome == tt::Outcome::yes);

    const char *refund = R"({
        "decide": "Does the customer ask for a refund?",
        "threshold": "0.2:0.8"
    })";
    is_refund = tt::decide(
        engine,
        refund,
        "I want to send this back.");
    assert(is_refund.value.outcome == tt::Outcome::notSure);
}
Build and run it beside the unpacked archives, thinkthen-c/ and thinkthen-cpp/
cp thinkthen-c/include/thinkthen.h \
    thinkthen-cpp/include/thinkthen/
c++ -std=c++17 \
    -I thinkthen-cpp/include \
    first-call.cpp -o first-call \
    -L thinkthen-c/lib -lthinkthen \
    -Wl,-rpath,"$PWD/thinkthen-c/lib"
./first-call

Not sure comes back as tt::Outcome::notSure. Branch on it and send those cases to a person.

Run facts

decide returns a CallResult. Its .value holds the answer, and its .facts holds this call's run facts as tt::Json.

Errors

A failed call throws a tt::Failure. Its tt::ErrorKind names one of six kinds, with the message and the retry flag.

Settings and recording

tt::create(settings) takes the settings as JSON. "record" writes a recording to a folder. "replay" answers from that recording with no connection. The Settings page lists every setting.

Jev, Liquid d1 and Ollama from C++

C++ 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.

BackendNameKey variable
TypeSafe JevtypesafeTYPESAFE_API_KEY
Liquid d1liquidLIQUIDAI_API_KEY, then LIQUID_API_KEY
OllamaollamaOLLAMA_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
#include <cassert>
#include <thinkthen/door.hpp>

int main() {
    auto engine = tt::create();

    const char *question =
        "Does the customer ask for a refund?";
    auto broken_is_refund = tt::decide(
        engine,
        question,
        "Please refund my order. It arrived broken.");
    auto thanks_is_refund = tt::decide(
        engine,
        question,
        "Thanks for the quick help yesterday!");
    assert(broken_is_refund.value.outcome
        == tt::Outcome::yes);
    assert(thanks_is_refund.value.outcome
        == tt::Outcome::no);
}
Build and run it beside the unpacked archives, thinkthen-c/ and thinkthen-cpp/
cp thinkthen-c/include/thinkthen.h \
    thinkthen-cpp/include/thinkthen/
c++ -std=c++17 \
    -I thinkthen-cpp/include \
    backends.cpp -o backends \
    -L thinkthen-c/lib -lthinkthen \
    -Wl,-rpath,"$PWD/thinkthen-c/lib"
./backends

The configuration file's backend names a default backend for every run. The Configuration page shows the file.

OpenAI Decisions API from C++

OpenAI announced its Decisions API on 2026-09-29 in its DevDay 2026 recap. OpenAI has published no address, schema or price, so ThinkThen cannot call it. The OpenAI Decisions API page says what ThinkThen knows.

What is different in C++