C# functions that answer questions about text
An Engine over the C library, for .NET 8. Each call returns its answer and its run facts.
Install
| Channel | Note |
|---|---|
dotnet add package Botassembly.ThinkThen | The NuGet package. |
thinkthen-csharp-VERSION-TARGET.tar.gz | The package file, from each release. Its folder serves as a local feed. |
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
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Botassembly.ThinkThen"
Version="*" />
</ItemGroup>
</Project>using System.Diagnostics;
using ThinkThen;
using var tt = Engine.Open();
const string question =
"Does the customer ask for a refund?";
var isRefund = tt.Decide(
question,
"Please refund my order. It arrived broken.");
Trace.Assert(isRefund.Value.OutcomeKind == Outcome.Yes);
const string refund = """
{"decide": "Does the customer ask for a refund?",
"threshold": "0.2:0.8"}
""";
isRefund = tt.Decide(refund, "I want to send this back.");
Trace.Assert(isRefund.Value.OutcomeKind == Outcome.NotSure);dotnet build -o bin \
--source "$PWD/thinkthen-csharp"
LD_LIBRARY_PATH="$PWD/thinkthen-c/lib" \
dotnet bin/first-call.dllNot sure comes back as Outcome.NotSure. Branch on it and send those cases to a person.
Run facts
Decide returns a TypedResult. .Value holds the answer, and .Facts holds this call's run facts as a JsonElement.
Errors
A failed call throws a Failure. Its Kind names one of six FailureKind values, and Retryable says whether a retry may help.
Settings and recording
Engine.Open(settingsJson) 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.
| 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/v1using System.Diagnostics;
using ThinkThen;
using var tt = Engine.Open();
const string question =
"Does the customer ask for a refund?";
var brokenIsRefund = tt.Decide(
question,
"Please refund my order. It arrived broken.");
var thanksIsRefund = tt.Decide(
question,
"Thanks for the quick help yesterday!");
var broken = brokenIsRefund.Value.OutcomeKind;
var thanks = thanksIsRefund.Value.OutcomeKind;
Trace.Assert(broken == Outcome.Yes);
Trace.Assert(thanks == Outcome.No);dotnet build -o bin \
--source "$PWD/thinkthen-csharp"
LD_LIBRARY_PATH="$PWD/thinkthen-c/lib" \
dotnet bin/first-call.dllThe 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#
- The package finds the C library by name.
LD_LIBRARY_PATHnames its folder. Trace.Assertruns in a Release build.Debug.Assertdoes not.
On GitHub: github.com/botassembly/thinkthen