# Zig functions that answer questions about text

A Zig 0.15.2 module over the C library. Each call returns `.ok` or `.failed`.

## Install

| Channel | Note |
| --- | --- |
| `thinkthen-zig-VERSION-TARGET.tar.gz` | The module source, from each release. |
| `thinkthen-c-VERSION-TARGET.tar.gz` | The C library it calls, from the same release. |

Set `THINKTHEN_API_KEY` in the environment.

## A first call

*build.zig, a project file beside the sample*

```
const std = @import("std");
const thinkthen = @import("thinkthen");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});
    const native = b.option(
        []const u8,
        "native",
        "The unpacked C archive",
    ) orelse @panic("give -Dnative");
    const dep = b.dependency("thinkthen", .{
        .target = target,
        .optimize = optimize,
    });
    const module = dep.module("thinkthen");
    const exe = b.addExecutable(.{
        .name = "first-call",
        .root_module = b.createModule(.{
            .root_source_file = b.path("first-call.zig"),
            .target = target,
            .optimize = optimize,
        }),
    });
    exe.root_module.addImport("thinkthen", module);
    thinkthen.linkNative(b, exe, module, native, .shared);
    b.installArtifact(exe);
}
```

*build.zig.zon, a project file beside the sample*

```
.{
    .name = .first_call,
    .version = "0.0.0",
    .fingerprint = 0x3b7c900a11fafa61,
    .minimum_zig_version = "0.15.2",
    .dependencies = .{
        .thinkthen = .{ .path = "thinkthen-zig" },
    },
    .paths = .{""},
}
```

```
const std = @import("std");
const thinkthen = @import("thinkthen");

pub fn main() !void {
    const allocator = std.heap.page_allocator;
    var tt = switch (try thinkthen.Engine.init(allocator)) {
        .ok => |engine| engine,
        .failed => |failure| {
            thinkthen.releaseFailure(allocator, failure);
            return error.NoEngine;
        },
    };
    defer tt.deinit();

    const question = "Does the customer ask for a refund?";
    const broken =
        "Please refund my order. It arrived broken.";
    const asked = try tt.decide(question, broken, .{});
    const is_refund = switch (asked) {
        .ok => |answer| answer,
        .failed => |failure| {
            tt.freeFailure(failure);
            return error.Failed;
        },
    };
    defer is_refund.deinit(allocator);
    std.debug.assert(is_refund.value.outcome == .yes);

    const refund = "{\"decide\": \"" ++ question ++
        "\", \"threshold\": \"0.2:0.8\"}";
    const back = "I want to send this back.";
    const back_call = try tt.decide(refund, back, .{});
    const back_is_refund = switch (back_call) {
        .ok => |answer| answer,
        .failed => |failure| {
            tt.freeFailure(failure);
            return error.Failed;
        },
    };
    defer back_is_refund.deinit(allocator);
    const outcome = back_is_refund.value.outcome;
    std.debug.assert(outcome == .unsure);
}
```

*Build and run it beside the unpacked archives, thinkthen-c/ and thinkthen-zig/*

```
zig build \
    -Dnative="$PWD/thinkthen-c"
./zig-out/bin/first-call
```

Not sure comes back as `.unsure`. Branch on it and send those cases to a person.

## Run facts

An `.ok` holds a `CallResult`. `.value` holds the answer, and `.facts` holds this call's run facts as parsed JSON. Free it with `deinit`.

## Errors

A `.failed` holds one of six `kind` values and a message. Free it with `engine.freeFailure`.

## Settings and recording

`Engine.initWithSettings` takes an allocator and the settings as JSON. `"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 Zig

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

The Zig project file names its sample, so this sample has its own.

*build.zig, a project file beside the sample*

```
const std = @import("std");
const thinkthen = @import("thinkthen");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});
    const native = b.option(
        []const u8,
        "native",
        "The unpacked C archive",
    ) orelse @panic("give -Dnative");
    const dep = b.dependency("thinkthen", .{
        .target = target,
        .optimize = optimize,
    });
    const module = dep.module("thinkthen");
    const exe = b.addExecutable(.{
        .name = "backends",
        .root_module = b.createModule(.{
            .root_source_file = b.path("backends.zig"),
            .target = target,
            .optimize = optimize,
        }),
    });
    exe.root_module.addImport("thinkthen", module);
    thinkthen.linkNative(b, exe, module, native, .shared);
    b.installArtifact(exe);
}
```

*build.zig.zon, a project file beside the sample*

```
.{
    .name = .backends,
    .version = "0.0.0",
    .fingerprint = 0x3c836b68ae394830,
    .minimum_zig_version = "0.15.2",
    .dependencies = .{
        .thinkthen = .{ .path = "thinkthen-zig" },
    },
    .paths = .{""},
}
```

```
const std = @import("std");
const thinkthen = @import("thinkthen");

fn decide(
    tt: *thinkthen.Engine,
    question: [:0]const u8,
    text: []const u8,
) !thinkthen.Outcome {
    const asked = try tt.decide(question, text, .{});
    const answer = switch (asked) {
        .ok => |answer| answer,
        .failed => |failure| {
            tt.freeFailure(failure);
            return error.Failed;
        },
    };
    defer answer.deinit(std.heap.page_allocator);
    return answer.value.outcome;
}

pub fn main() !void {
    const allocator = std.heap.page_allocator;
    var tt = switch (try thinkthen.Engine.init(allocator)) {
        .ok => |engine| engine,
        .failed => |failure| {
            thinkthen.releaseFailure(allocator, failure);
            return error.NoEngine;
        },
    };
    defer tt.deinit();

    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 broken_is_refund =
        try decide(&tt, question, broken);
    const thanks_is_refund =
        try decide(&tt, question, thanks);
    std.debug.assert(broken_is_refund == .yes);
    std.debug.assert(thanks_is_refund == .no);
}
```

*Build and run it beside the unpacked archives, thinkthen-c/ and thinkthen-zig/*

```
zig build \
    -Dnative="$PWD/thinkthen-c"
./zig-out/bin/backends
```

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 Zig

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 Zig

- `linkNative` in the build script links the C library. `-Dnative` names the unpacked C archive.
- `std.debug.assert` checks only in Debug and ReleaseSafe builds.

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