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

bash

# 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

json

{
  "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:

json

{
  "msg_type": "publish",
  "data": { "temperature": 22.5 },
  "context": { "wait": true }
}

The socket returns the server response before closing.

Send to a Specific Entity

json

{
  "msg_type": "publish",
  "data": { "command": "reboot" },
  "dest": "control-panel-01"
}

Heartbeats

Send system metrics directly (not batched):

json

{
  "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

json

{
  "msg_type": "state_new",
  "data": { "firmware": "1.2.0", "mode": "active" }
}

Update State (Merge)

json

{
  "msg_type": "state_update",
  "data": { "mode": "standby" }
}

Only the specified keys are updated. Existing keys are preserved.

Read State

json

{
  "msg_type": "state_read"
}

Response:

json

{
  "statusTable": {
    "firmware": "1.2.0",
    "mode": "standby"
  }
}

Checking for Messages

Poll for messages sent to your entity:

json

{
  "msg_type": "msg_check",
  "context": { "limit": 5 }
}

Response (array of messages, or 204 if none):

json

[
  {
    "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:

python


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):

bash

#!/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):

bash

#!/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