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
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);
}.{
.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);
}zig build \
-Dnative="$PWD/thinkthen-c"
./zig-out/bin/first-callNot 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 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 | typesafe | TYPESAFE_API_KEY |
| Liquid d1 | liquid | LIQUIDAI_API_KEY, then LIQUID_API_KEY |
| Ollama | ollama | OLLAMA_API_KEY. A local address needs no key. |
export THINKTHEN_BACKEND=typesafe
export TYPESAFE_API_KEY=...export THINKTHEN_BACKEND=liquid
export LIQUIDAI_API_KEY=...export THINKTHEN_BACKEND=ollama
export THINKTHEN_BASE_URL=http://localhost:11535/v1The Zig project file names its sample, so this sample has its own.
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);
}.{
.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);
}zig build \
-Dnative="$PWD/thinkthen-c"
./zig-out/bin/backendsThe configuration file's backend names a default backend for every run. The Configuration page shows the file.
OpenAI Decisions API from Zig
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 Zig
linkNativein the build script links the C library.-Dnativenames the unpacked C archive.std.debug.assertchecks only in Debug and ReleaseSafe builds.
On GitHub: github.com/botassembly/thinkthen