Python SDK and CLI for direct Thalovant hub data-plane clients and agents
Project description
Thalovant Python SDK
Python SDK for connecting apps, services, kiosks, and agents to Thalovant hubs.
The control API is used to discover hubs and provision a client identity. After that, the SDK talks directly to the hub data plane over HTTPS, WSS, or MQTTS.
Thalovant API -> discover hubs, create client identity
Python SDK -> connect to the hub data plane
Hub runtime -> skills, events, replies
Full docs: https://docs.thalovant.com/developers/sdks/python/
What You Need
- A Thalovant account with API access for authenticated control-plane actions.
- A hub id or slug.
- A client identity for that hub. You can create one through the API or use one downloaded from the dashboard.
Install
pip install thalovant
For local SDK development:
pip install -e ".[dev]"
Quick Start
This is the normal first integration flow.
from thalovant import ThalovantClient, ThalovantControlPlane
api = ThalovantControlPlane()
# Public hub discovery does not require auth.
public_hubs = api.list_public_hubs(limit=12)
for hub in public_hubs["data"]:
print(hub["id"], hub["slug"], hub["title"])
# Auth is required when creating a client identity.
api.login("you@example.com", "password")
result = api.create_client_identity(
"hub-id",
name="python-demo-client",
preferred_protocols=("wss", "https", "mqtt"),
)
with ThalovantClient(result.identity, protocol="wss") as client:
reply = client.ask("Tell me a short clean joke.")
print(reply.text)
ThalovantControlPlane() uses https://api.thalovant.com by default. Pass a
different URL only for local development or a self-hosted control plane.
Keep result.identity secret. It contains the client credentials used by the
hub. Do not log result.identity.as_dict(include_secrets=True).
List Your Hubs
Authenticated accounts can list owned or visible hubs:
api = ThalovantControlPlane()
api.login("you@example.com", "password")
page = api.list_hubs(limit=50)
for hub in page["data"]:
print(hub["id"], hub["slug"], hub["title"])
Use An Existing Identity
For local development, store one or more identities in the protected SDK config:
mkdir -p ~/.config/thalovant
chmod 700 ~/.config/thalovant
$EDITOR ~/.config/thalovant/config.yaml
chmod 600 ~/.config/thalovant/config.yaml
profile: prod
profiles:
prod:
identity:
access_key: ...
password: ...
site_id: demo-agent
default_master: https://jokes.thalovant.io
data_plane_endpoints:
wss: wss://jokes.thalovant.io/public
https: https://jokes.thalovant.io/public
mqtt: mqtts://mqtt.thalovant.com:8883
mqtt:
endpoint: mqtts://mqtt.thalovant.com:8883
username: ...
password: ...
topic_prefix: hubs/hub-id/clients/client-id
tls: true
from thalovant import ThalovantClient
with ThalovantClient.from_config(profile="prod") as client:
reply = client.ask("What can this hub do?")
print(reply.text)
SDKs reject config files that are readable or writable by other users on Linux and macOS. Keep this file out of git.
Raw identity files are supported too:
from thalovant import ThalovantClient
with ThalovantClient.from_identity_file("_identity.json") as client:
reply = client.ask("What can this hub do?")
print(reply.text)
Environment variables are supported too:
export THALOVANT_ACCESS_KEY=...
export THALOVANT_PASSWORD=...
export THALOVANT_CRYPTO_KEY=...
export THALOVANT_SITE_ID=...
export THALOVANT_HUB_HTTPS_HOST=https://hub.example.com
export THALOVANT_HUB_WSS_HOST=wss://hub.example.com
export THALOVANT_HUB_MQTT_HOST=mqtts://mqtt.thalovant.com:8883
export THALOVANT_MQTT_USERNAME=...
export THALOVANT_MQTT_PASSWORD=...
export THALOVANT_MQTT_TOPIC_PREFIX=hivemind/hub-id/client-id
from thalovant import ThalovantClient
with ThalovantClient.from_env(protocol="https") as client:
print(client.ask("Say hello.").text)
Save A Provisioned Identity
Only save identities in a secret store or local developer file that is ignored by git.
import json
from pathlib import Path
Path("_identity.json").write_text(
json.dumps(result.identity.as_dict(include_secrets=True), indent=2),
encoding="utf-8",
)
Protocols
Hubs may expose one or more public data-plane protocols:
wss: secure realtime WebSocket, the default public path and SDK preference.https: request/response HTTP protocol exposed as HTTPS.mqtt: broker-mediated MQTT over TLS. Requires per-client broker credentials.
Inspect what an identity supports:
identity = result.identity
print(identity.enabled_protocols())
print(identity.endpoint_for("wss"))
print(identity.endpoint_for("https"))
print(identity.endpoint_for("mqtt"))
print(identity.mqtt.endpoint if identity.mqtt else None)
Connect with a specific protocol:
from thalovant import ThalovantClient
for protocol in ("wss", "https", "mqtt"):
if not result.identity.supports_protocol(protocol):
continue
if protocol == "mqtt" and result.identity.mqtt is None:
continue
with ThalovantClient(result.identity, protocol=protocol) as client:
print(protocol, client.ask(f"Reply over {protocol}.").text)
MQTT identities include a broker endpoint, username, password, TLS flag, and
topic prefix. The broker credentials are scoped to that client and should be
treated like a password. Public identities should use mqtts://; the SDK also
honors an explicit tls: true flag from the identity.
Conversations
Use a conversation when several turns should share one session.
from thalovant import ThalovantClient
with ThalovantClient.from_identity_file("_identity.json") as client:
with client.conversation(lang="en-us") as convo:
print(convo.ask("Remember that my favorite color is blue.").text)
print(convo.ask("What color did I mention?").text)
Events
You can wait for, stream, or subscribe to hub events.
from thalovant import EVENT_SPEAK, ThalovantClient
with ThalovantClient.from_identity_file("_identity.json") as client:
for event in client.listen(EVENT_SPEAK, timeout=30, max_events=1):
print(event.text)
Use timeouts in scripts so they do not wait forever.
Client Context
Context lets skills know which app, device, user, or channel made the request.
from thalovant import ThalovantClient, build_client_context
context = build_client_context(
user_id="user-42",
user_name="Ada",
auth_provider="oidc",
roles=["member"],
platform="kiosk",
source="checkout-kiosk",
channel="chat",
)
with ThalovantClient.from_identity_file("_identity.json") as client:
reply = client.ask("Show the next instruction.", context=context)
print(reply.text)
Actions And Exact Inputs
Use actions for button payloads and codes for exact typed or scanned values.
with client.conversation(session_id="work-session") as convo:
convo.send_action('/choose{"id":"42"}', title="Choose item")
convo.send_code("SN-001-XYZ", kind="qr", label="serial")
Rich Responses
Replies can include text, choices, tables, images, or attachments.
reply = client.ask("Show matching parts.")
for item in reply.display_items(max_text_chars=600):
if item.kind == "text":
print(item.text)
elif item.kind == "choices":
print([choice["title"] for choice in item.data])
Async Apps
import asyncio
from thalovant import AsyncThalovantClient
async def main():
async with AsyncThalovantClient.from_config(profile="prod") as client:
reply = await client.ask("What time is it?")
print(reply.text)
asyncio.run(main())
CLI Diagnostics
thalovant --identity _identity.json doctor
The doctor command checks identity shape, endpoint selection, authentication, handshake, and transport health.
Common Issues
Missing Thalovant API access token: callapi.login(...)before private control-plane actions, or passaccess_token=toThalovantControlPlane.API access requires a paid plan: upgrade the workspace before using the SDK control-plane API to provision private resources.Unsupported protocol: the hub does not expose that protocol, or the identity was created before that protocol was enabled.- MQTT fails immediately: create or download a fresh client identity after MQTT
is enabled. MQTT needs the per-client
identity.mqttcredentials. - A request times out: increase
timeoutonask(...)or checkdoctor().
API Shape
ThalovantControlPlane()ThalovantControlPlane(api_url, access_token=...)for local or self-hosted control planescontrol.login(email, password, scope=None)control.list_public_hubs(limit=...)control.get_public_hub(hub_ref)control.list_hubs(limit=..., owner_id=...)control.get_hub(hub_id)control.create_client_identity(hub_id, ...)ThalovantIdentity.from_config(path=None, profile=None)ThalovantIdentity.from_file(path)ThalovantClient.from_config(path=None, profile=None)ThalovantClient.from_identity_file(path)ThalovantClient.from_env()ThalovantClient(identity, protocol="wss")client.ask(text, context=...)client.send_utterance(text, context=...)client.send_action(payload, ...)client.send_code(value, ...)client.listen(event_name, ...)client.conversation(...)
Development
pip install -e ".[dev]"
pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file thalovant-0.4.13.tar.gz.
File metadata
- Download URL: thalovant-0.4.13.tar.gz
- Upload date:
- Size: 49.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
91cad586f560934a461367baf50f705c1fabfdc23bc2986c194fbf7d70a8adcc
|
|
| MD5 |
7f825eed99919e7f4c46d5ded1be1b59
|
|
| BLAKE2b-256 |
f9b5be195e30fbd5feb76c8c695a6af007585f5a14fc54024577ff3dab158a0c
|
File details
Details for the file thalovant-0.4.13-py3-none-any.whl.
File metadata
- Download URL: thalovant-0.4.13-py3-none-any.whl
- Upload date:
- Size: 42.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa26ad52a34c9787be1a941168927828f9f131b39753715941ef509969634423
|
|
| MD5 |
31cfb22be94ffe60e90b2f530cb779b0
|
|
| BLAKE2b-256 |
5040933b3b3613122580f08085c2b2080b5359b4e343e5d80395cfdeb2c574c4
|