# Go functions that answer questions about text

A cgo package over the C library. Each call that sends takes a `context.Context` and returns a `Result` and an `error`.

## Install

| Channel | Note |
| --- | --- |
| `go get github.com/botassembly/thinkthen/libraries/go` |  |
| `thinkthen-go-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

```
package main

import (
	"context"
	"log"

	thinkthen "github.com/botassembly/thinkthen/libraries/go"
)

func main() {
	tt, err := thinkthen.New()
	if err != nil {
		log.Fatal(err)
	}
	defer tt.Close()
	ctx := context.Background()

	question := "Does the customer ask for a refund?"
	isRefund, err := tt.Decide(
		ctx,
		question,
		"Please refund my order. It arrived broken.",
	)
	if err != nil {
		log.Fatal(err)
	}
	if isRefund.Value.Outcome != thinkthen.Yes {
		log.Fatal("expected yes")
	}

	refund := {"decide": " + question + ",  +
		"threshold": "0.2:0.8"}
	isRefund, err = tt.Decide(
		ctx,
		refund,
		"I want to send this back.",
	)
	if err != nil {
		log.Fatal(err)
	}
	if isRefund.Value.Outcome != thinkthen.Unsure {
		log.Fatal("expected not sure")
	}
}
```

*Build and run it beside the unpacked archives, thinkthen-c/ and thinkthen-go/, in a folder with no other.go file*

```
go mod init first-call
go mod edit \
    -replace=github.com/botassembly/thinkthen/libraries/go=./thinkthen-go
go mod tidy
PKG_CONFIG_PATH="$PWD/thinkthen-c/lib/pkgconfig" \
    go build -o first-call .
LD_LIBRARY_PATH="$PWD/thinkthen-c/lib" \
    ./first-call
```

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

## Run facts

`Decide` returns a `Result`. `.Value` holds the answer, and `.Facts` holds this call's run facts as `json.RawMessage`.

## Errors

A failed native call returns an `*Error`. Its `Kind` runs from `KindUsage` to `KindDefect`, and it carries `Retryable` and `Message`. `ErrEmbeddedNUL` and allocation failures come back as plain errors.

## Settings and recording

`NewWith(settingsJSON)` takes 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 Go

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

```
package main

import (
	"context"
	"log"

	thinkthen "github.com/botassembly/thinkthen/libraries/go"
)

func main() {
	tt, err := thinkthen.New()
	if err != nil {
		log.Fatal(err)
	}
	defer tt.Close()
	ctx := context.Background()

	question := "Does the customer ask for a refund?"
	brokenIsRefund, err := tt.Decide(
		ctx,
		question,
		"Please refund my order. It arrived broken.",
	)
	if err != nil {
		log.Fatal(err)
	}
	thanksIsRefund, err := tt.Decide(
		ctx,
		question,
		"Thanks for the quick help yesterday!",
	)
	if err != nil {
		log.Fatal(err)
	}
	if brokenIsRefund.Value.Outcome != thinkthen.Yes {
		log.Fatal("expected yes")
	}
	if thanksIsRefund.Value.Outcome != thinkthen.No {
		log.Fatal("expected no")
	}
}
```

*Build and run it beside the unpacked archives, thinkthen-c/ and thinkthen-go/, in a folder with no other.go file*

```
go mod init backends
go mod edit \
    -replace=github.com/botassembly/thinkthen/libraries/go=./thinkthen-go
go mod tidy
PKG_CONFIG_PATH="$PWD/thinkthen-c/lib/pkgconfig" \
    go build -o backends .
LD_LIBRARY_PATH="$PWD/thinkthen-c/lib" \
    ./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 Go

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 Go

- The package finds the C library through `pkg-config`. `PKG_CONFIG_PATH` names the C archive's `lib/pkgconfig`.
- A deadline on the context reaches the call as its deadline.

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