Docs / Contact / sdks/nano-agent/getting-started
Nano Agent: Getting Started
Send data to Contact from any language in 3 lines. The Nano Agent is a lightweight binary that runs on your device, exposes a Unix socket, and handles all the heavy lifting: batching, retry, heartbeats, and HTTP communication. Your application just writes JSON to a socket.
Use the Nano Agent when:
- Your language doesn't have a Tendrl SDK (C, Rust, Ruby, shell scripts, anything)
- You want a single process managing all Tendrl communication
- You want multiple local applications sharing one authenticated connection
- You need high throughput with minimal application overhead
Requirements: Linux, macOS, or Windows 10 1803+
Install#
One command on any platform. The installer detects your OS and architecture, verifies checksums, and puts tendrl-agent (plus the tendrl CLI, when the release includes it) on your PATH. It downloads with curl, so macOS Gatekeeper and Windows SmartScreen never flag the binaries.
macOS / Linux#
curl -fsSL https://app.tendrl.com/api/public/tools/nano-agent/v1/latest/install.sh | sh
Windows#
powershell -c "irm https://app.tendrl.com/api/public/tools/nano-agent/v1/latest/install.ps1 | iex"
Set TENDRL_BIN_DIR to override the install directory. To pin a build, swap latest for a version tag; direct per-platform downloads and checksums are listed at /api/public/tools/nano-agent/v1/meta.
Linux: socket directory#
The agent serves its socket from /var/lib/tendrl by default, so create that directory (and a group for the local users allowed to talk to it) once:
sudo mkdir -p /var/lib/tendrl
sudo groupadd tendrl
sudo chown :tendrl /var/lib/tendrl
sudo chmod 770 /var/lib/tendrl
sudo usermod -aG tendrl $(whoami)
On macOS, or to run without root on Linux, point the agent (and its clients) at a user-writable path instead with TENDRL_SOCKET=/tmp/tendrl_agent.sock or the -socket flag.
Start the Agent#
The agent authenticates with an entity API key. If you haven't created one yet, create your first entity and copy its API key from the Connection Instructions dialog.
export TENDRL_KEY=your_api_key
tendrl-agent
The agent creates a socket and starts listening. That's the entire setup.
| Platform | Socket Path |
|---|---|
| Linux/macOS | /var/lib/tendrl/tendrl_agent.sock |
| Windows | C:\ProgramData\tendrl\tendrl_agent.sock |
Send Your First Message#
The fastest way to send a message is the tendrl CLI client. For production code, write JSON directly to the socket in any language.
CLI (Recommended)#
Install tendrl from the platform's tool downloads (see CLI Client), then:
tendrl ping
tendrl publish -data '{"temperature": 22.5, "humidity": 65}' -tags sensor
Bash (Raw Socket)#
echo '{"msg_type":"publish","data":{"temperature":22.5},"context":{"tags":["sensor"]}}' | \
nc -U /var/lib/tendrl/tendrl_agent.sock
On Windows, prefer the tendrl CLI, because nc -U is not always available.
Python (No SDK Needed)#
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect("/var/lib/tendrl/tendrl_agent.sock")
sock.sendall(json.dumps({
"msg_type": "publish",
"data": {"temperature": 22.5, "humidity": 65},
"context": {"tags": ["sensor"]}
}).encode())
sock.close()
C#
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un addr = { .sun_family = AF_UNIX };
strncpy(addr.sun_path, "/var/lib/tendrl/tendrl_agent.sock", sizeof(addr.sun_path) - 1);
connect(fd, (struct sockaddr *)&addr, sizeof(addr));
write(fd, "{\"msg_type\":\"publish\",\"data\":{\"temp\":22.5}}", 43);
close(fd);
Rust#
let mut stream = UnixStream::connect("/var/lib/tendrl/tendrl_agent.sock")?;
stream.write_all(br#"{"msg_type":"publish","data":{"temp":22.5},"context":{"tags":["sensor"]}}"#)?;
That's it. The agent queues your message, batches it with others, and delivers it to Contact. You get dynamic batching, retry with backoff, and heartbeats without writing a single line of infrastructure code.
Track Device State#
Store and retrieve persistent state through the socket:
{"msg_type": "state_update", "data": {"firmware": "1.2.0", "status": "active"}}
{"msg_type": "state_read"}
Response: {"statusTable": {"firmware": "1.2.0", "status": "active"}}
Check for Commands#
Poll for incoming messages:
{"msg_type": "msg_check", "context": {"limit": 5}}
The agent returns an array of pending messages, or 204 if none are waiting.
What the Agent Handles for You#
The agent runs as a single process and automatically:
- Batches messages: groups socket writes into efficient bulk HTTP sends
- Adapts to load: dynamic batch sizing based on CPU and memory
- Retries with backoff: failed sends are retried automatically
- Sends heartbeats: reports system metrics to Contact
- Manages authentication: one API key, shared by all local applications
Your application code stays simple: just open a socket and write JSON.
What's Next#
- CLI Client:
tendrlcommand reference for debugging and shell scripts - Configuration: Flags, tuning, running as a systemd/launchd service
- Examples: All message types, full Python helper, shell scripts
- API Reference: Complete socket protocol reference
Tendrl