Docs / Contact / sdks/nano-agent/examples
Nano Agent: Examples
The Nano Agent accepts JSON messages over a Unix socket. Every message needs a msg_type field. This page covers all supported message types with examples.
For quick testing from the shell, use the tendrl CLI client instead of hand-writing JSON.
CLI Examples
# Publish sensor data
tendrl publish -data '{"temperature": 22.5, "unit": "celsius"}' -tags sensor,building-a
# Wait for server acknowledgment
tendrl publish -data '{"temperature": 22.5}' -wait
# Send to a specific entity
tendrl publish -data '{"command": "reboot"}' -dest control-panel-01
# Poll for commands
tendrl check -limit 5
# State table
tendrl state new -data '{"firmware": "1.2.0", "mode": "active"}'
tendrl state update -data '{"mode": "standby"}'
tendrl state read
# Heartbeat
tendrl heartbeat -data '{"mem_free": 1024.0, "mem_total": 4096.0}'
Publishing Data
Basic Publish
{
"msg_type": "publish",
"data": {
"temperature": 22.5,
"unit": "celsius"
},
"context": {
"tags": ["sensor", "building-a"]
}
}
Messages are queued and batched automatically for efficient delivery.
Publish with Response
Set "wait": true to block until the server acknowledges:
{
"msg_type": "publish",
"data": { "temperature": 22.5 },
"context": { "wait": true }
}
The socket returns the server response before closing.
Send to a Specific Entity
{
"msg_type": "publish",
"data": { "command": "reboot" },
"dest": "control-panel-01"
}
Heartbeats
Send system metrics directly (not batched):
{
"msg_type": "heartbeat",
"data": {
"mem_free": 1024.0,
"mem_total": 4096.0,
"disk_free": 50000.0,
"disk_size": 100000.0
}
}
State Table
Create or Replace State
{
"msg_type": "state_new",
"data": { "firmware": "1.2.0", "mode": "active" }
}
Update State (Merge)
{
"msg_type": "state_update",
"data": { "mode": "standby" }
}
Only the specified keys are updated. Existing keys are preserved.
Read State
{
"msg_type": "state_read"
}
Response:
{
"statusTable": {
"firmware": "1.2.0",
"mode": "standby"
}
}
Checking for Messages
Poll for messages sent to your entity:
{
"msg_type": "msg_check",
"context": { "limit": 5 }
}
Response (array of messages, or 204 if none):
[
{
"msg_type": "publish",
"data": { "command": "reboot" },
"tags": ["maintenance"],
"source": "123456:us-1:entity:control-panel",
"timestamp": "2025-01-15T10:30:45Z"
}
]
Complete Python Example
A full sensor collection script using the Nano Agent:
SOCKET_PATH = "/var/lib/tendrl/tendrl_agent.sock"
def send_message(msg):
"""Send a message to the Nano Agent and return the response."""
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
sock.connect(SOCKET_PATH)
sock.sendall(json.dumps(msg).encode())
# Read response (optional, only needed for wait=true or msg_check)
sock.settimeout(5)
try:
response = sock.recv(4096)
return json.loads(response.decode())
except socket.timeout:
return None
finally:
sock.close()
def publish(data, tags=None, wait=False):
"""Publish data to Contact."""
msg = {
"msg_type": "publish",
"data": data,
"context": {}
}
if tags:
msg["context"]["tags"] = tags
if wait:
msg["context"]["wait"] = True
return send_message(msg)
def check_messages(limit=5):
"""Check for incoming messages."""
return send_message({
"msg_type": "msg_check",
"context": {"limit": limit}
})
def get_state():
"""Read entity state table."""
return send_message({"msg_type": "state_read"})
def update_state(data):
"""Merge data into state table."""
return send_message({
"msg_type": "state_update",
"data": data
})
# Main loop
print("Starting sensor collection...")
while True:
# Publish sensor data
publish(
{"temperature": 22.5, "humidity": 65},
tags=["sensor", "environment"]
)
# Check for commands
messages = check_messages()
if messages and isinstance(messages, list):
for msg in messages:
print(f"Command: {msg}")
time.sleep(10)
Shell Script Example
Using the tendrl CLI (recommended):
#!/bin/bash
set -euo pipefail
tendrl ping
while true; do
CPU=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}')
MEM=$(free -m | awk 'NR==2{printf "%.1f", $3*100/$2}')
DISK=$(df -h / | awk 'NR==2{print $5}' | tr -d '%')
tendrl publish -data "{\"cpu\":$CPU,\"memory\":$MEM,\"disk\":$DISK}" -tags system,metrics
sleep 60
done
Raw socket alternative (requires nc -U):
#!/bin/bash
SOCK="/var/lib/tendrl/tendrl_agent.sock"
while true; do
# Collect system metrics
CPU=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}')
MEM=$(free -m | awk 'NR==2{printf "%.1f", $3*100/$2}')
DISK=$(df -h / | awk 'NR==2{print $5}' | tr -d '%')
# Publish via Nano Agent
echo "{\"msg_type\":\"publish\",\"data\":{\"cpu\":$CPU,\"memory\":$MEM,\"disk\":$DISK},\"context\":{\"tags\":[\"system\",\"metrics\"]}}" | \
nc -U "$SOCK"
sleep 60
done
Context Fields Reference
| Field | Type | Description |
|---|---|---|
tags |
string[] | Tags for routing and flow triggering (max 10) |
wait |
boolean | Wait for server response instead of batching |
limit |
integer | Messages to retrieve (msg_check only) |
entity |
string | Target entity identifier |
Error Responses
| Error | Cause | Solution |
|---|---|---|
Queue full, try again later |
Queue at capacity | Reduce send rate or increase -maxQueue |
Too many tags provided; maximum is 10 |
More than 10 tags | Reduce tag count |
Unknown message type |
Invalid msg_type |
Use: publish, heartbeat, state_new, state_update, state_read, msg_check |
Tendrl