# SDKs

> Choose a Thalovant SDK and connect an app, service, device, or agent to a hub.

Source: https://docs.thalovant.com/developers/sdks/

---
{/* Last Edit: Codex (model identifier unavailable) - 2026-10-26 - Motive: Align only the MCP compatibility row with published 0.6.6. */}

Use an SDK when your code should talk directly to a Thalovant hub.

The Thalovant API is the control plane at `https://api.thalovant.com`. It discovers hubs and creates client identities. The SDK is the data plane. It sends runtime traffic to the hub over WSS, HTTPS, or MQTT over TLS.

## Best First Path

1. **Pick the SDK for your runtime.** Python, Node.js, Go, Rust, Kotlin, Swift, and .NET expose the same core behavior. Embedded C is a protocol library for devices that bring their own transport.
2. **Use the hosted API.** Start with `https://api.thalovant.com`.
3. **Create one client identity per app, device, or agent.** Store the returned identity in a secret store or protected SDK config file.
4. **Connect with WSS first.** It's the default realtime path for public clients, and it's the only data-plane protocol in the Kotlin, Swift, and .NET SDKs.
5. **Add HTTPS, MQTT, or browser origin access only when needed.** Create a fresh identity after enabling a new protocol on the hub, and request an approved SDK origin before calling the API from a customer-owned browser app.

## Choose A Language

| Language | Install | Best fit |
| --- | --- | --- |
| Python | `pip install thalovant` | Agents, tools, notebooks, tests, and service workers. |
| Node.js | `npm install @thalovant/sdk` | TypeScript services, bots, scripts, web backends, and bundled browser apps. |
| Go | `go get github.com/thalovant/thalovant-go-sdk` | Gateways, CLIs, small services, and long-running workers. |
| Rust | `cargo add thalovant` | Strict clients, embedded work, and reliability-focused services. |
| Kotlin | `implementation("com.thalovant:thalovant-sdk")` — see [Supported Versions](#supported-versions) | JVM services and Android apps. |
| Swift | SwiftPM package from the GitHub repository | iOS and macOS apps; Linux requires a WebSocket-capable Foundation runtime. |
| C# / .NET | `dotnet add package Thalovant.Sdk` | Enterprise .NET services and Unity apps. |
| C | Vendored source pinned to a release tag | Microcontroller and embedded devices that bring their own MQTT or WebSocket client. |

  
  
  
  
  
  
  
  

## Capability Tiers

Not every SDK covers every protocol yet. Pick the tier that matches your runtime needs.

| Tier | SDKs | Data plane | Control plane |
| --- | --- | --- | --- |
| Full | Python, Node.js, Go, Rust | WSS, HTTPS, and MQTT over TLS | MFA sign-in, device login, API token auth, provisioning, and typed operation polling |
| WSS-only | Kotlin, Swift, .NET | WSS only; requesting HTTPS or MQTT raises a clear unsupported-protocol error | MFA sign-in, device login, API token auth, provisioning, and typed operation polling |
| Protocol library | Embedded C | None built in; you bring the MQTT or WebSocket client and the library supplies identity parsing, topics, encryption, and wire framing | None |

Browser apps use the Node SDK behind a bundler: the control plane and the WSS and HTTPS data plane work in web bundles, while MQTT and identity file helpers stay Node-only. See [Browser usage in the Node SDK](/developers/sdks/node/#use-the-sdk-in-a-browser).

## Shared Runtime Features

The seven high-level SDKs provide these features within their supported transports. Embedded C exposes the corresponding wire building and parsing primitives; the application owns the connection, scheduling, collection, and cancellation.

| Feature | Python, Node.js, Go, Rust | Kotlin, Swift, .NET | Embedded C |
| --- | --- | --- | --- |
| Sign-in, MFA, device login, tokens, provisioning, operation polling | Supported | Supported | Application supplies control plane |
| Hub-addressed skill management and history | Supported; affects the attached shared runtime group | Supported; affects the attached shared runtime group | Application supplies control plane |
| Ask, scoped query/cascade replies, raw events, action/code inputs | Supported | Supported over WSS | Frame builders and reply classification |
| Conversations, event waits and streams | Supported; Node streams use callback subscriptions | Supported; streams buffer at most 64 events | Application owns collection and session state |
| Intent listing, describes and names-only fallback | Supported | Supported | Request builders and response readers |
| Fallback handlers and conservative language availability | Inventory fields in Python/Node; additive capability wrapper in Go/Rust | Inventory fields with `mayAnswer` in Kotlin/Swift and `MayAnswer` in .NET | Fallback frames and response classification; application computes availability |
| Recognized language, ordered pipeline and request location hints | Native request options/helpers | Native request helpers | Payload/frame builders with hints and location builder |
| Embedded skill audio and reported language | Ordered speech/audio, 4 MiB clip / 16 MiB reply bounds | Same bounds and ordered media within WSS replies | Correlation-aware decoder and caller-owned budget/collection |
| Speakable intent examples | Optional rendering and source-priority ranking | Optional rendering and source-priority ranking | Pattern renderer; application ranks and deduplicates |
| Guarded runtime configuration merge | Revision GET/PUT; at most three attempts, only 412 retries | Same guarded merge and explicit replacement | Application supplies control plane |
| Connection information, health and diagnostics | Supported; details differ by SDK | Local authenticated transport state | Application supplies diagnostics |
| Saved keys and reconnecting | SDK-owned, configurable storage | SDK-owned, configurable storage | Caller-owned storage and buffers |

An intent miss can precede delayed speech. By default, Ask starts a fixed 250 ms settlement window on first nonempty speech, or a fixed five-second empty wait on first handled/soft-miss without speech. Callers may override these durations. Later fragments don't restart settlement. Both windows are clipped to the original request deadline; collected speech is returned when it expires. A query collector waits for `hive.query.complete` or its deadline. Policy denial and explicit query timeout freeze any partial reply immediately, including while a send is retiring. Reconnection never replays an application request automatically. See [runtime recipes](/developers/sdk-functions/talking-to-a-hub/#runtime-helper-names) and [intent discovery](/concepts/hub-intents/).

## Platform Limits

Each SDK is tested on the runtimes listed under [Supported Versions](#supported-versions). That doesn't include Android or Unity devices, or every Linux Foundation build: Swift on Linux needs a Foundation runtime with WebSocket support, described on the [Swift page](/developers/sdks/swift/#where-the-sdk-keeps-its-keys). A local `healthcheck` or `doctor` result describes the connection; it doesn't say whether every skill behind the hub is healthy.

## API Credential Security

Configure the final API URL: SDK control-plane requests refuse redirects, including redirects that would resend a login password. Authenticated requests and request bodies require HTTPS. These calls can use HTTP only on explicit `localhost`, `127.0.0.1`, and `[::1]` development endpoints; a hostname that merely resolves to a private address doesn't qualify. API URLs can't embed userinfo. Device login validates both verification URLs before showing a prompt, invoking a browser callback, or polling. URLs must use HTTP(S), include a host, and contain no userinfo, raw whitespace, or control characters.

The .NET security patch changes custom HTTP integration: credential-bearing calls can't use an arbitrary injected `HttpClient`. Use the SDK-owned client or the supported handler injection described in the [.NET guide](/developers/sdks/dotnet/). Preserve private CA settings when configuring a custom transport.

## How The Connection Is Secured

Every SDK opens an encrypted, authenticated session with the hub before it sends anything, using the password already in the client identity. Nothing extra has to be provisioned. A connection that can't be authenticated is closed; there's no unencrypted fallback, and older SDK releases can't connect to current hubs.

On first contact the SDK records the hub's identity and checks it on every later connection, so a changed hub is an error rather than a silent redirect. Keep the SDK's saved keys in a private, persistent location and reuse them after a restart; each SDK page names the option. Use a distinct client identity for each client process that runs at the same time, and if a hub reports a changed identity, confirm it with the hub owner before accepting it.

Use fresh request and query IDs for each operation; a session ID can be reused for a conversation.

## Supported Versions

These are the current releases. Older releases can't connect to current hubs, so upgrade first.

| Consumer | Supported package version | Registry and runtime |
| --- | --- | --- |
| Python SDK | `thalovant 0.9.7` | PyPI; Python 3.10 or newer |
| Node.js SDK | `@thalovant/sdk 0.9.9` | npm; Node.js 20 or newer, or a supported browser bundle |
| Go SDK | `github.com/thalovant/thalovant-go-sdk v0.13.0` | Public Go module; Go 1.26 or newer |
| Rust SDK | `thalovant 0.15.0` | crates.io; Rust 1.88 or newer |
| Kotlin SDK | `com.thalovant:thalovant-sdk 0.9.0` | Maven Central; JVM 17 or a compatible Android toolchain |
| Swift SDK | `thalovant-swift-sdk 0.11.0` | Swift Package Manager; Swift 5.10 or newer; see the [Linux runtime requirement](/developers/sdks/swift/#where-the-sdk-keeps-its-keys) |
| .NET SDK | `Thalovant.Sdk 0.9.5` | NuGet; `net8.0` and `netstandard2.1`; Unity requires an explicit private state store |
| Embedded C library | `thalovant-embedded-c v0.8.0` | Immutable Git tag and release archives; C99, caller-owned transport and buffers |
| MCP server | `@thalovant/mcp-server 0.6.6` | npm, GHCR, and the MCP Registry; built on Node SDK 0.9.9 |

MCP runtime tools open hub connections through the Node SDK over WSS, HTTPS, or MQTT over TLS. The MCP server's stdio and Streamable HTTP options describe how an agent calls MCP tools; they are separate from the selected hub protocol.

All control-plane calls use the backward-compatible `/api/v1` boundary. Additive server fields are safe for older SDKs because clients ignore fields they don't understand. A client that needs a newly added capability must use the minimum version listed in that capability's release note.

The MCP server is built on the Node SDK and is released after the SDK version it needs, with aligned npm, OCI, and MCP Registry metadata. The table above gives the current pair.

SDKs with a control plane support signing in without a password through `login_with_browser` and its language-native equivalents. Each language guide also documents direct API token authentication. See [Sign In Without A Password](/developers/sdk-functions/signing-in/#sign-in-without-a-password).

SDKs with a control plane can also create hubs, runtime groups, and skill installs from code. Every SDK with a control plane ships the same provisioning and skill-discovery surface, and the MCP server exposes it as tools. See [Provision Hubs](/developers/provisioning/).

The hub intent inventory, which lists what a hub can be asked over the client's own session, is in every published SDK. The table below records the first version for each SDK. See [What Can My Hub Be Asked?](/concepts/hub-intents/).

| SDK | First version with the inventory |
| --- | --- |
| Python | `thalovant 0.4.36` |
| Node.js | `@thalovant/sdk 0.2.38` |
| Go | `github.com/thalovant/thalovant-go-sdk v0.3.13` |
| Rust | `thalovant 0.3.0` |
| Kotlin | `com.thalovant:thalovant-sdk 0.1.8` |
| Swift | `thalovant-swift-sdk 0.1.8` |
| .NET | `Thalovant.Sdk 0.1.12` |
| Embedded C | `thalovant-embedded-c v0.2.0` |

A hub that accepts the listing and answers it with an error was read as an empty hub in the first release of several ports. The first versions that report it as an error are: Python `0.4.40`, Node.js `0.2.39`, Go `v0.3.14`, Rust `0.3.1`, Kotlin `0.1.8`, Swift `0.1.9`, .NET `0.1.13`, and embedded C `v0.3.0`.

  Package artifacts and Git tags are immutable. If a release is withdrawn, use the replacement version in the release notes instead of pinning an unpublished or rewritten artifact.

## How SDK Access Works

1. **Discover a hub.** Public hub discovery can be used before sign-in.
2. **Sign in for private API actions.** Creating client identities requires API access on the workspace. Use a password login, a browser-approved device sign-in, or a scoped API token.
3. **Create a client identity.** The SDK stores the returned identity locally or in your secret store.
4. **Connect to the hub.** Runtime traffic goes directly to the hub endpoint.
5. **Send a request.** Start with one `ask` call, then add sessions, context, actions, or rich output.

## Browser Origins

Browser apps on customer-owned domains need an approved [SDK origin](/developers/sdk-origins/) before cross-origin SDK or API calls are accepted.

Approval is exact-origin based and non-credentialed. It allows requests from a reviewed origin, but it doesn't allow dashboard cookies, refresh-session headers, setup links, or long-lived client identities to be exposed in browser bundles.

## Protocols

| Protocol | Use it when | Notes |
| --- | --- | --- |
| WSS | You want the default public realtime path. | Best first choice for agents and clients that may listen for events. Supported by all client SDKs; embedded C requires your transport. |
| HTTPS | You want request-response calls, health checks, CLIs, or jobs. | Must be enabled on the hub before public clients can use it. Python, Node.js, Go, and Rust only. |
| MQTT over TLS | You want broker-mediated device or edge traffic. | Requires per-client broker credentials and topic access. Python, Node.js, Go, and Rust only; Node.js supports it outside browsers. |

  Start with WSS. Add HTTPS or MQTT only when the client has a real reason to use that path.

## What To Keep Secret

Every client identity is secret. Store it like a password.

Don't put identity files, access keys, passwords, broker passwords, setup links, or crypto keys in browser bundles, public repos, screenshots, logs, or support tickets.

## Production Checklist

| Check | Good default |
| --- | --- |
| API base URL | `https://api.thalovant.com` |
| First runtime protocol | WSS |
| Browser usage | Use [SDK origins](/developers/sdk-origins/) for reviewed browser domains. Keep secrets on a backend. |
| Identity storage | Use a secret manager, CI secret, mounted secret file, or `~/.config/thalovant/config.yaml` with mode `600`. |
| MQTT | Use `mqtts://`, per-client credentials, and SDK-managed topics. |
| Saved keys | Keep the SDK's saved keys in a private, persistent location across restarts. Use a distinct identity for each client process that runs at the same time. |
| Rotation | If a hub reports a changed identity, confirm it with the hub owner before accepting it. Replace client credentials by provisioning a new identity. |
| Logs | Redact identity JSON, broker passwords, API tokens, and crypto keys. |

## Skill-Management Coverage

Python, Node, Go, Rust, Kotlin, .NET and Swift provide hub-addressed skill list,
history, install, update and removal, alongside the existing runtime-group skill
upsert/removal and hub/runtime configuration and release helpers. MCP exposes the
corresponding tools. Embedded C remains a protocol library without a
provisioning client.

Hub-addressed skill calls change the attached runtime group and therefore affect
all hubs sharing it. See the language page for operation waiting and resumption.

## Managed Sessions And Presentable Inventories

Python, Node, Go, Rust, Kotlin, .NET, and Swift provide managed hub sessions,
presentable skill/intent inventories, and optional private caches. Sessions keep
subscriptions across connection replacement and never replay an accepted action
automatically. Application code owns connection-factory budgets and probe
scheduling. The [Python guide](/developers/sdks/python/#managed-sessions-and-inventory-caches)
and each language guide explain the API and migration details.

MCP exposes the presentation model in its inventory tool while keeping each
call's identity lease separate. Embedded C retains its caller-buffer,
transport-agnostic core; managed sessions, disk caches, and locale databases
belong to the host application. Transport support remains as listed above.

## Reply Claim Metadata

The current SDK releases expose ordered pipeline and skill IDs and an advisory claim result. This lets clients distinguish a fallback-only answer from a matched intent without discarding the answer. Older successful hubs without stamps remain compatible. See each SDK’s reply-claims section for its idiomatic API; embedded C keeps caller-owned storage and MCP exposes the fields in its runtime summary.
## Locale-Aware Sentence Listings

[Locale-aware sentence listings](/developers/sdks/python/#locale-aware-intent-listings) are in every managed SDK and in MCP; Python needs its listing extra. All of them bundle the same language rules. Raw examples stay the default, and sentence rendering adds locale samples, capitalization and punctuation on top. Embedded C keeps its caller-buffer pattern helper and bundles neither locale data nor regional matching tables.

## Next

If you already know your language, open the SDK page.

Use [SDK Functions](/developers/sdk-functions/) when you need method names across languages. Use [MQTT](/developers/mqtt/) when the client connects through the broker.
