Reference
SDKs and CLI
The Python and TypeScript SDKs, the command line tool and the VS Code extension, with downloads, configuration, retries, idempotency and errors.
Dex has two SDKs, one for Python and one for TypeScript, a command line tool and a VS Code extension. They are thin clients over the same API contract: requests look like the JSON you would send with curl, and answers come back as typed objects.
The packages are coming soon to PyPI, npm and the VS Code Marketplace. Until then, install the interim builds from Downloads: they are built from the same code and work the same way.
Licence. The Python SDK, the TypeScript SDK, the CLI and the VS Code extension are open source under the Apache-2.0 licence. You can use them in commercial products, change them and ship them.
Install
Once the packages are published (coming soon), these are the commands. Until then, use Downloads.
Python 3.10 or newer:
pip install thinqit-dex
TypeScript and JavaScript, for Node.js 18 or newer, Deno, Bun and edge runtimes. The package has no runtime dependencies and ships both ES modules and CommonJS:
npm i @thinqit/dex
The command line tool:
npm i -g @thinqit/dex-cli
Downloads
The packages are not on PyPI, npm or the VS Code Marketplace yet. Until they are, install these interim builds from this site. They are built from the same commit as the site you are reading, so they match these docs.
| Client | File |
|---|---|
| Python SDK | thinqit_dex-0.1.1-py3-none-any.whl (wheel) and thinqit_dex-0.1.1.tar.gz (source) |
| TypeScript SDK | thinqit-dex-0.1.1.tgz |
| CLI | thinqit-dex-cli-0.1.1.tgz |
| VS Code extension | thinqit-dex-vscode-0.1.1.vsix |
The file names carry the version. When a new version is built, this page links the new files.
The Python SDK, for Python 3.10 or newer:
pip install https://thinqit.ai/downloads/thinqit_dex-0.1.1-py3-none-any.whl
The TypeScript SDK, in your project folder:
npm i https://thinqit.ai/downloads/thinqit-dex-0.1.1.tgz
The CLI, for Node.js 18 or newer. It gives you the dex command:
npm i -g https://thinqit.ai/downloads/thinqit-dex-cli-0.1.1.tgz
dex --version
The VS Code extension. Download the file, then install it:
curl -fLO https://thinqit.ai/downloads/thinqit-dex-vscode-0.1.1.vsix
code --install-extension thinqit-dex-vscode-0.1.1.vsix
You can also install the file from inside VS Code. Open the Extensions view, open the ... menu at the top, choose Install from VSIX... and pick the file.
Check a download
Every file has a .sha256 file next to it, and SHA256SUMS.txt lists them all. Put the file and its .sha256 in one folder and run the check there. This example checks the extension:
curl -fLO https://thinqit.ai/downloads/thinqit-dex-vscode-0.1.1.vsix.sha256
sha256sum -c thinqit-dex-vscode-0.1.1.vsix.sha256 # Linux
shasum -a 256 -c thinqit-dex-vscode-0.1.1.vsix.sha256 # macOS
Both print OK when the file is intact. In PowerShell on Windows, these two lines must print the same hash:
(Get-FileHash .\thinqit-dex-vscode-0.1.1.vsix -Algorithm SHA256).Hash.ToLower()
(Get-Content .\thinqit-dex-vscode-0.1.1.vsix.sha256).Split(" ")[0]
Licence and executables
All four clients are open source under the Apache-2.0 licence. Every package holds its LICENSE and NOTICE files, and both are also here: LICENSE.txt and NOTICE.txt.
The CLI's single executables are not offered for download, because each one is about 100 MB. Use the npm package with Node.js 18 or newer instead.
Configuration
| Setting | Python | TypeScript | Environment variable | Default |
|---|---|---|---|---|
| API key | api_key |
apiKey |
DEX_API_KEY |
None: required |
| Base URL | base_url |
baseUrl |
DEX_BASE_URL |
https://api.thinqit.ai |
| Timeout per attempt | timeout (seconds) |
timeout (milliseconds) |
30 seconds | |
| Retries | max_retries |
maxRetries |
3 | |
| Extra headers | default_headers |
defaultHeaders |
None |
A value passed to the constructor wins over the environment variable. To run against the mock server, set DEX_BASE_URL=http://127.0.0.1:4010. The base URL must use https://, so your key is never sent in clear text; http:// is accepted only for localhost, 127.0.0.1 and [::1], and the SDKs, the CLI and the VS Code extension refuse any other http:// address before sending a request.
A first call
This sends the support ticket from the Quickstart and acts only on an answer that did not abstain.
from thinqit_dex import Client, pick, rate, check
client = Client() # reads DEX_API_KEY
decision = client.decide(
state={
"ticket": {
"channel": "email",
"subject": "Charged twice, still no answer",
"body": "This is the third time I am writing. You charged my card twice "
"for order 4471 and nobody replies. Fix it today or I cancel my subscription.",
}
},
questions={
"team": pick(
"Which team should handle {{ticket.body}}?",
{
"billing": "Payments, refunds and invoices",
"technical": "Bugs, outages and sign-in problems",
"shipping": "Delivery and returns",
"other": None,
},
min_confidence=0.5,
),
"urgency": rate(
"How fast must we reply to {{ticket.body}}?",
["Can wait", "This week", "Within two working days", "Today"],
),
"angry": check("Is the writer of {{ticket.body}} angry?", min_confidence=0.6),
},
)
team = decision.pick("team")
if not team.abstained:
print(team.choice)import { Client, pick, rate, check } from "@thinqit/dex";
const client = new Client(); // reads DEX_API_KEY
const decision = await client.decide({
state: {
ticket: {
channel: "email",
subject: "Charged twice, still no answer",
body: "This is the third time I am writing. You charged my card twice for order 4471 and nobody replies. Fix it today or I cancel my subscription.",
},
},
questions: {
team: pick(
"Which team should handle {{ticket.body}}?",
{
billing: "Payments, refunds and invoices",
technical: "Bugs, outages and sign-in problems",
shipping: "Delivery and returns",
other: null,
},
{ min_confidence: 0.5 },
),
urgency: rate("How fast must we reply to {{ticket.body}}?", [
"Can wait",
"This week",
"Within two working days",
"Today",
]),
angry: check("Is the writer of {{ticket.body}} angry?", { min_confidence: 0.6 }),
},
});
if (!decision.answers.team.abstained) {
console.log(decision.answers.team.choice);
}What the SDKs cover
| Operation | Python | TypeScript |
|---|---|---|
| decide | client.decide(state, questions, *, model=None, fallback=None, idempotency_key=None, ...) |
client.decide(request, options?) |
| listModels | client.list_models() |
client.listModels() |
| getCurrentKey | client.get_key() |
client.getKey() |
| getUsage | client.get_usage(start, end, *, granularity=None, key_id=None) |
client.getUsage({ start, end, granularity?, key_id? }) |
| getBalance | client.get_balance() |
client.getBalance() |
Every method takes a client request id (client_request_id in Python, clientRequestId in TypeScript), which the API echoes in x-client-request-id. See Headers.
The console routes are not part of the SDKs. Python also has AsyncClient, with the same arguments and await-able methods:
from thinqit_dex import AsyncClient
async with AsyncClient() as client:
decision = await client.decide(state=state, questions=questions)
Builders and typed answers
pick(instructions, options, ...),rate(instructions, levels, ...)andcheck(instructions, ...)return plain question objects.rateis in beta: see Questions. Each also takescriteriaandmin_confidence: as keyword arguments in Python, and in a final{ criteria, min_confidence }object in TypeScript.- In Python,
decision.pick(id),decision.rate(id)anddecision.check(id)return typed answers. A wrong id raisesKeyError, and a wrong type raisesTypeError. - In TypeScript,
decision.answers.<id>is typed from your request. The labels of a pick become a union type forchoiceandprobabilities. - Every answer type lists
abstainedfirst. Check it before you use an answer. See Abstention. ref(...)andescape_braces(escapeBracesin TypeScript) build field references.
Response details
Every result has an http property with the status, the request id, your client request id, the idempotency key, whether it was a replay, the rate limit headers, how many retries it took, and all headers. Python uses snake_case names, such as result.http.request_id, and TypeScript uses camelCase, such as result.http.requestId.
Retries and idempotency
The SDKs retry for you:
- What they retry: HTTP 429, 500, 502, 503 and 504, 409
idempotency_in_progress, connection errors and timeouts. Never any other 4xx, and never 429test_daily_quota, which lasts until 00:00 UTC. A load balancer can return 502 or 504 during a restart, which is why those are retried although the API itself does not send them. - How often: up to
max_retriesretries (3 by default), so at most 4 attempts. - How long they wait: the
retry-afterheader when there is one. Otherwise a random delay between 0 andmin(8, 0.25 * 2^n)seconds before retryn, counting from 0. - No double charges: every
decidecall sends anidempotency-key, yours or a new UUID v4, and reuses it on every retry. A retry can never charge twice. Read-only calls send none. See Idempotency.
Set max_retries=0 (or maxRetries: 0) on one call to turn retries off for it.
Errors
Each error type has its own class, such as RateLimitError for a 429 and RequestValidationError for a 422. All of them carry status, type, code, message, param, request_id and retry_after. The full table is in Errors.
The SDKs are built and tested never to write your API key to logs, error messages or object representations.
The CLI
Install the CLI from Downloads until it is on npm. The command is dex.
dex login # checks the key's checksum, then stores it in the OS keychain
dex whoami # which key and account you are using (GET /v1/key)
dex decide --file request.json # sends a request file, such as the one from the Quickstart
dex models # lists models
dex usage --since 7d # shows your usage
dex balance # shows your balance
dex decidealso takes inline flags for quick checks, such as--state @ticket.txtfor a state read from a file.- Output is a table by default, or JSON with
--json. - The exit code tells scripts what happened: 0 success, 2 validation, 3 authentication, 4 balance, 5 rate limit, 6 unavailable.
dex loginreads the key from standard input, so it never appears in your shell history. It refuses a mistyped key offline, from the key's checksum.dex decide --filekeeps the key order of your file exactly, rejects duplicate keys, and removes a top-level$schemaline before sending.
VS Code extension
The VS Code extension validates request files against the contract, runs them from the editor and shows the answers inline. Its status bar shows which key you use, from GET /v1/key. Install it from Downloads until it is on the Marketplace.
JSON schema for request files
The request schema is published at https://thinqit.ai/schemas/dex-request.schema.json, generated from the API contract. Add "$schema": "https://thinqit.ai/schemas/dex-request.schema.json" at the top of a request file to get completion and validation in any editor that reads JSON schemas. The CLI and the VS Code extension remove $schema before sending. The API itself rejects it as an unknown field, so leave it out of bodies you send with curl or an SDK.