Docs / Contact / sdks/python/configuration
Python SDK: Configuration
All configuration is passed to the Client constructor. Every parameter has a sensible default; only api_key is required (unless using the TENDRL_KEY environment variable or agent mode).
Client defines __slots__, so the tables below are exhaustive: a keyword that does not appear in them raises TypeError at construction rather than being silently ignored.
Constructor Parameters#
Core#
| Parameter | Type | Default | Description |
|---|---|---|---|
mode |
str | "api" |
"api" for direct HTTPS or "agent" for Nano Agent socket |
api_key |
str | None |
Entity API key. Falls back to TENDRL_KEY env var |
app_url |
str | None |
Server to talk to. Falls back to TENDRL_APP_URL, then https://app.tendrl.com. Accepts a bare origin or a base URL ending in /api. |
headless |
bool | False |
Disable background threads (synchronous only) |
debug |
bool | False |
Print send activity to stdout |
Batching & Performance#
| Parameter | Type | Default | Description |
|---|---|---|---|
min_batch_size |
int | 10 |
Minimum messages per batch |
max_batch_size |
int | 100 |
Maximum messages per batch |
min_batch_interval |
float | 0.1 |
Minimum seconds between batch sends |
max_batch_interval |
float | 1.0 |
Maximum seconds before forced send |
max_queue_size |
int | 1000 |
Maximum messages in the queue |
target_cpu_percent |
float | 65.0 |
Target CPU % for dynamic batch sizing |
target_mem_percent |
float | 75.0 |
Target memory % for dynamic batch sizing |
The SDK dynamically adjusts batch size based on CPU and memory usage. When system load is high, batch sizes shrink to reduce pressure. When load is low, batches grow for efficiency.
Offline Storage#
| Parameter | Type | Default | Description |
|---|---|---|---|
offline_storage |
bool | False |
Enable SQLite message persistence |
db_path |
str | "tendrl_offline.db" |
Path to the SQLite database file |
When enabled, messages that can't be sent (network down) are stored in SQLite with a TTL. They're automatically retried when connectivity returns.
Message Polling#
| Parameter | Type | Default | Description |
|---|---|---|---|
callback |
Callable | None |
Called with every inbound message. Polling only runs when this is set. |
check_msg_rate |
float | 3.0 |
Seconds between message polls |
check_msg_limit |
int | 1 |
Maximum messages retrieved per poll |
There is no tag-based routing in this SDK — no @client.on(), @client.on_default or @client.on_state(), and no state_callback argument. One callback receives everything; branch on message["tags"] yourself. See Getting Started.
Heartbeat#
There is none. The Python SDK sends no heartbeats and exposes no heartbeat method. send_heartbeat and heartbeat_interval are not valid arguments and raise TypeError:
Client(api_key="k", send_heartbeat=False)
# TypeError: __init__() got an unexpected keyword argument 'send_heartbeat'
Environment Variables#
| Variable | Purpose |
|---|---|
TENDRL_KEY |
API key (used when api_key is not passed to the constructor) |
TENDRL_APP_URL |
Server URL (used when app_url is not passed to the constructor). See Testing against a local or staging stack. |
The agent-mode socket path is fixed and cannot be overridden by an environment variable; see Socket Paths below.
Undelivered-Message Warnings#
publish() returns before the message is sent, so a delivery failure cannot come back through the return value. The SDK reports it on a standard logging logger named tendrl instead, at most once per minute:
| Warning | Meaning |
|---|---|
Tendrl: DROPPED n message(s) that could not be delivered to <url> |
Data lost. Enable offline_storage to hold it instead. |
Tendrl: could not deliver n message(s) … held in offline storage |
Data safe in SQLite, retried when the connection returns. |
Tendrl: the sender thread did not stop within 10.0s |
stop() timed out; up to one batch may not have been sent. |
Route them wherever your other logs go:
logging.getLogger("tendrl").addHandler(logging.FileHandler("/var/log/myapp.log"))
With no logging configured at all, Python's last-resort handler still writes these warnings to stderr. That is deliberate: a client that cannot deliver must not look like a healthy one.
Example Configurations#
Development (Verbose, No Offline)#
client = Client(
api_key="dev_key",
app_url="http://localhost:8000",
debug=True
)
Production IoT Device#
client = Client(
api_key="device_key",
offline_storage=True,
db_path="/var/lib/myapp/tendrl.db",
max_batch_size=200
)
High-Throughput Service#
client = Client(
mode="agent", # Use Nano Agent for better performance
min_batch_size=50,
max_batch_size=500,
max_queue_size=5000,
target_cpu_percent=80.0
)
Simple Script (Headless)#
client = Client(
api_key="script_key",
headless=True
)
# No start() needed; publish() sends directly
response = client.publish({"event": "deploy_complete"}, wait_response=True)
Socket Paths (Agent Mode)#
When using mode="agent", the SDK connects to the Nano Agent's Unix socket at a fixed, hardcoded path. There is no constructor argument or environment variable to change it, so the Nano Agent must be left on its own default -socket path:
| Platform | Socket Path |
|---|---|
| Linux/macOS | /var/lib/tendrl/tendrl_agent.sock |
| Windows | C:\ProgramData\tendrl\tendrl_agent.sock |
Ensure the Nano Agent is running and your user is in the tendrl group.
Tendrl