Complete reference for all LoT operations available within actions. These operations allow you to manipulate variables, perform calculations, transform strings, read and write MQTT topics, and implement conditional logic.
Quick Reference: Use the sidebar or the index table below to jump to specific operations.
SET, GET TOPIC, and GET JSON are the core operations for working with data in actions. They allow you to store values, read from MQTT topics, and extract fields from JSON payloads.
Creates or assigns a value to an internal variable:
Copy
Ask AI
SET "variable_name" WITH <value>
Variables exist only during action execution and are referenced using {variable_name}.
Static Value
From Topic
Calculated
Copy
Ask AI
SET "threshold" WITH 100SET "status" WITH "active"SET "enabled" WITH TRUE
Copy
Ask AI
SET "current_temp" WITH (GET TOPIC "sensors/temperature")// For topic "sensors/temp001/data": POSITION 2 gets the sensor IDSET "sensor_id" WITH TOPIC POSITION 2
Copy
Ask AI
SET "total" WITH (GET TOPIC "count/a" + GET TOPIC "count/b")SET "average" WITH ({sum} / {count})
Variable names must be enclosed in double quotes when using SET, but referenced with curly braces: SET "myVar" WITH 10 then use {myVar}.
When an action is triggered by a wildcard topic pattern, GET TOPIC inherits the matched wildcard values:
Copy
Ask AI
DEFINE ACTION ProcessWithContextON TOPIC "sensors/+/temperature" DO // If triggered by "sensors/temp001/temperature" // The + wildcard matches "temp001" // This GET TOPIC uses the same wildcard value: SET "humidity" WITH (GET TOPIC "sensors/+/humidity" AS DOUBLE) // Reads from "sensors/temp001/humidity"
// Read and processSET "last_temp" WITH (GET TOPIC "sensors/temperature" AS DOUBLE)// Check before using (EMPTY check)IF GET TOPIC "config/threshold" == EMPTY THEN SET "threshold" WITH 80ELSE SET "threshold" WITH (GET TOPIC "config/threshold" AS DOUBLE)// Combine multiple topic valuesSET "total" WITH (GET TOPIC "counters/a" AS INT + GET TOPIC "counters/b" AS INT)
Use dot notation to access nested objects and bracket notation for arrays:
Copy
Ask AI
// Nested object accessSET "nested" WITH (GET JSON "data.sensors.temperature" IN PAYLOAD AS DOUBLE)SET "deep" WITH (GET JSON "metadata.config.threshold" IN PAYLOAD AS INT)// Array access (0-indexed)SET "first_reading" WITH (GET JSON "readings[0].value" IN PAYLOAD AS DOUBLE)SET "second_sensor" WITH (GET JSON "data.sensors[1].id" IN PAYLOAD AS STRING)
DEFINE ACTION ProcessComplexJSONON TOPIC "sensors/data" DO // Top-level fields SET "sensor_id" WITH (GET JSON "id" IN PAYLOAD AS STRING) SET "timestamp" WITH (GET JSON "timestamp" IN PAYLOAD AS STRING) // Nested fields SET "temp" WITH (GET JSON "readings.temperature" IN PAYLOAD AS DOUBLE) SET "humidity" WITH (GET JSON "readings.humidity" IN PAYLOAD AS DOUBLE) // Array access SET "latest" WITH (GET JSON "history[0].value" IN PAYLOAD AS DOUBLE) PUBLISH TOPIC "processed/" + {sensor_id} + "/temp" WITH {temp} PUBLISH TOPIC "processed/" + {sensor_id} + "/humidity" WITH {humidity}
Version Requirement:GET ENV, GET SECRET, KEEP ENV, KEEP SECRET, DELETE ENV, and DELETE SECRET are available from Coreflux Broker v1.9.3 and above.
LoT Actions can read, write, and delete environment variables and encrypted secrets at runtime. Environment variables store non-sensitive configuration (hostnames, ports, URLs). Secrets store sensitive credentials encrypted with AES-256-GCM.
Use environment variables for configuration that can safely appear in logs (hostnames, ports, feature flags). Use secrets for anything sensitive (passwords, API keys, tokens).
Reads an environment variable. The broker checks the managed .env file first, then falls back to process, user, and machine environment variables. Returns an empty string if not found.
-- Read connection settingsSET "host" WITH (GET ENV "DB_HOST")SET "port" WITH (GET ENV "DB_PORT")SET "apiUrl" WITH (GET ENV "API_BASE_URL")-- Use in conditional logicIF GET ENV "FEATURE_FLAG" == "enabled" THEN PUBLISH TOPIC "features/new" WITH "active"
-- Read credentialsSET "dbPass" WITH (GET SECRET "DB_PASSWORD")SET "apiKey" WITH (GET SECRET "API_KEY")-- Use in conditional logicIF GET SECRET "LICENSE_KEY" == EMPTY THEN PUBLISH TOPIC "system/warnings" WITH "No license key configured"
DEFINE ACTION SecureDataForwarderON TOPIC "sensors/+/data" DO SET "sensor_id" WITH TOPIC POSITION 2 -- Read configuration from environment SET "apiUrl" WITH (GET ENV "API_BASE_URL") SET "region" WITH (GET ENV "DEPLOY_REGION") -- Read credentials from secrets SET "apiKey" WITH (GET SECRET "API_KEY") IF {apiUrl} == EMPTY THEN PUBLISH TOPIC "system/errors" WITH "API_BASE_URL not configured" ELSE -- Forward sensor data with region tag PUBLISH TOPIC "forwarded/" + {region} + "/" + {sensor_id} WITH PAYLOAD PUBLISH TOPIC "forwarded/" + {sensor_id} + "/timestamp" WITH TIMESTAMP "UTC" -- Track last forwarded sensor KEEP ENV "LAST_FORWARDED_SENSOR" WITH {sensor_id}
For full details on environment variable resolution order, encryption key management, and deployment configuration, see Environment Variables & Secrets.
// Simple arithmetic with literalsSET "sum" WITH (10 + 5)SET "difference" WITH (100 - 25)SET "product" WITH (6 * 7)SET "quotient" WITH (100 / 4)SET "remainder" WITH (17 % 5)SET "negative" WITH (-42)
// Add values from two different topicsSET "total" WITH (GET TOPIC "sensors/count/a" AS INT + GET TOPIC "sensors/count/b" AS INT)// Calculate percentageSET "percentage" WITH (GET TOPIC "current/value" AS DOUBLE / GET TOPIC "max/value" AS DOUBLE * 100)// Temperature conversion (Celsius to Fahrenheit)SET "fahrenheit" WITH (GET TOPIC "sensors/temp/celsius" AS DOUBLE * 9 / 5 + 32)
DEFINE ACTION CalculateWithPayloadON TOPIC "input/value" DO SET "doubled" WITH (PAYLOAD AS DOUBLE * 2) SET "incremented" WITH (PAYLOAD AS INT + 1) PUBLISH TOPIC "output/doubled" WITH {doubled}
DEFINE ACTION TemperatureProcessorON TOPIC "sensors/+/temperature" DO // POSITION 1="sensors", POSITION 2=sensor_id (wildcard), POSITION 3="temperature" SET "sensor_id" WITH TOPIC POSITION 2 SET "celsius" WITH PAYLOAD AS DOUBLE // Convert to Fahrenheit SET "fahrenheit" WITH ({celsius} * 9 / 5 + 32) // Calculate deviation from setpoint SET "setpoint" WITH (GET TOPIC "config/setpoint" AS DOUBLE) SET "deviation" WITH ({celsius} - {setpoint}) SET "deviation_percent" WITH ({deviation} / {setpoint} * 100) PUBLISH TOPIC "processed/" + {sensor_id} + "/fahrenheit" WITH {fahrenheit} PUBLISH TOPIC "processed/" + {sensor_id} + "/deviation" WITH {deviation_percent}
// String + Number (number is converted to string)SET "message" WITH ("Temperature is: " + {temp})PUBLISH TOPIC "alerts/temperature" WITH ("High temp: " + {celsius} + "°C")
DEFINE ACTION DynamicPublisherON TOPIC "input/+/+/data" DO // POSITION 1="input", POSITION 2=region, POSITION 3=device, POSITION 4="data" SET "region" WITH TOPIC POSITION 2 SET "device" WITH TOPIC POSITION 3 SET "timestamp" WITH TIMESTAMP "UTC" // Build dynamic output topic SET "output_topic" WITH ("processed/" + {region} + "/" + {device}) // Build descriptive message SET "message" WITH ("Device " + {device} + " in " + {region} + " reported at " + {timestamp}) PUBLISH TOPIC {output_topic} WITH {message}
// Random integer in range (inclusive)RANDOM BETWEEN <min> AND <max>RANDOM INT BETWEEN <min> AND <max>// Random double/float in rangeRANDOM DOUBLE BETWEEN <min> AND <max>// Unique identifiersRANDOM UUIDRANDOM GUIDRANDOM ULID
// Random integer between 1 and 100SET "dice_roll" WITH (RANDOM BETWEEN 1 AND 6)SET "random_percent" WITH (RANDOM INT BETWEEN 0 AND 100)// Using expressions for rangeSET "random_in_range" WITH (RANDOM INT BETWEEN {min_value} AND {max_value})
// Random double between 0.0 and 1.0SET "probability" WITH (RANDOM DOUBLE BETWEEN 0.0 AND 1.0)// Random temperature for simulationSET "simulated_temp" WITH (RANDOM DOUBLE BETWEEN 18.5 AND 25.5)
// Generate UUID (e.g., "550e8400-e29b-41d4-a716-446655440000")SET "transaction_id" WITH (RANDOM UUID)// Generate GUID (same format as UUID)SET "session_id" WITH (RANDOM GUID)// Generate ULID (e.g., "01ARZ3NDEKTSV4RRFFQ69G5FAV")// ULIDs are sortable by timeSET "event_id" WITH (RANDOM ULID)
DEFINE ACTION SimulateSensorON EVERY 5 SECONDS DO SET "temperature" WITH (RANDOM DOUBLE BETWEEN 20.0 AND 30.0) SET "humidity" WITH (RANDOM INT BETWEEN 40 AND 80) SET "pressure" WITH (RANDOM DOUBLE BETWEEN 1000.0 AND 1020.0) PUBLISH TOPIC "simulated/sensor/temperature" WITH {temperature} PUBLISH TOPIC "simulated/sensor/humidity" WITH {humidity} PUBLISH TOPIC "simulated/sensor/pressure" WITH {pressure}
Generate unique record identifiers:
Copy
Ask AI
DEFINE ACTION CreateRecordON TOPIC "records/create" DO SET "record_id" WITH (RANDOM UUID) SET "timestamp" WITH TIMESTAMP "UTC" PUBLISH TOPIC "records/" + {record_id} WITH PAYLOAD PUBLISH TOPIC "records/index/latest" WITH {record_id}
Distribute work across workers:
Copy
Ask AI
DEFINE ACTION RandomRouterON TOPIC "incoming/requests" DO SET "worker" WITH (RANDOM INT BETWEEN 1 AND 4) PUBLISH TOPIC "workers/" + {worker} + "/queue" WITH PAYLOAD
// Extract all digits from payloadSET "numbers" WITH FILTER PAYLOAD USING REGEX "[0-9]+"// Extract from a topic valueSET "extracted" WITH FILTER (GET TOPIC "data/raw") USING REGEX "[a-zA-Z]+"// Extract email patternSET "email" WITH FILTER PAYLOAD USING REGEX "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"// Extract numbers from mixed contentSET "value" WITH FILTER "Temperature: 23.5°C" USING REGEX "[0-9]+\\.?[0-9]*"
// Replace in payloadSET "cleaned" WITH REPLACE "old" WITH "new" IN PAYLOAD// Replace in topic valueSET "modified" WITH REPLACE "error" WITH "warning" IN (GET TOPIC "logs/latest")// Replace in variableSET "formatted" WITH REPLACE " " WITH "_" IN {sensor_name}// Remove characters by replacing with empty stringSET "digits_only" WITH REPLACE "[^0-9]" WITH "" IN {mixed_content}
Sends data to an MQTT topic, broadcasting it to all clients subscribed to that topic. Published messages are delivered immediately and can trigger other actions or routes listening to the topic.
// StringPUBLISH TOPIC "system/status" WITH "online"// NumberPUBLISH TOPIC "sensors/reading" WITH 23.5// VariablePUBLISH TOPIC "output/value" WITH {calculated_result}// Payload passthroughPUBLISH TOPIC "forwarded/data" WITH PAYLOAD// TimestampPUBLISH TOPIC "events/timestamp" WITH TIMESTAMP "UTC"
Cannot Use Inline JSON ObjectsPUBLISH TOPIC does not support inline JSON object literals. This will NOT work:
Copy
Ask AI
// ❌ WRONG - This does not workPUBLISH TOPIC "output/data" WITH {"temperature": 23.5, "humidity": 65}
Why?PUBLISH TOPIC is designed for simple scalar values (strings, numbers, timestamps, variables). It doesn’t have the type system or schema validation needed for structured JSON data.Solution: For structured JSON output, use Models with PUBLISH MODEL:
Copy
Ask AI
// ✅ CORRECT - Define a model and publish itDEFINE MODEL SensorData COLLAPSED ADD DOUBLE "temperature" ADD DOUBLE "humidity"DEFINE ACTION PublishStructuredDataON TOPIC "sensors/input" DO PUBLISH MODEL SensorData TO "output/data" WITH temperature = 23.5 humidity = 65
Models provide type safety, schema validation, and proper JSON serialization. See Publishing Models for complete guidance.
DEFINE ACTION MultiPublishON TOPIC "input/data" DO PUBLISH TOPIC "output/raw" WITH PAYLOAD PUBLISH TOPIC "output/timestamp" WITH TIMESTAMP "UTC" PUBLISH TOPIC "output/source" WITH "sensor_001"
Triggering Other Actions: When you publish to a topic, any action with ON TOPIC matching that path will execute. This enables chaining actions together for complex workflows.
Stores a value in an internal broker topic that persists between action executions. Think of KEEP as creating a persistent variable - unlike SET (which exists only during one execution), KEEP values survive and can be read later.
KEEP vs PUBLISH: Both write to topics, but PUBLISH sends to the MQTT bus (external clients can subscribe). KEEP stores internally for your actions to read later - like a private scratchpad that doesn’t broadcast to subscribers.
DEFINE ACTION PersistentCounterON EVERY 10 SECONDS DO SET "current" WITH (GET TOPIC "state/counter") IF {current} == EMPTY THEN KEEP TOPIC "state/counter" WITH 1 ELSE KEEP TOPIC "state/counter" WITH ({current} + 1) PUBLISH TOPIC "stats/count" WITH (GET TOPIC "state/counter")
IF {temperature} > 90 THEN PUBLISH TOPIC "alerts/critical" WITH "CRITICAL: " + {temperature}ELSE IF {temperature} > 80 THEN PUBLISH TOPIC "alerts/warning" WITH "WARNING: " + {temperature} ELSE IF {temperature} > 70 THEN PUBLISH TOPIC "alerts/info" WITH "Elevated: " + {temperature} ELSE PUBLISH TOPIC "status/normal" WITH "OK"
// Add timestamp to published messagesPUBLISH TOPIC "events/created" WITH TIMESTAMP "UTC"PUBLISH TOPIC "sensors/reading/time" WITH TIMESTAMP "UNIX"// Store timestamp for later referenceKEEP TOPIC "cache/last_update" WITH TIMESTAMP "UNIX"
// Store timestamp in a variableSET "event_time" WITH TIMESTAMP "UTC"SET "process_start" WITH TIMESTAMP "UNIX"// Use in string concatenationSET "log_message" WITH ("Event occurred at " + TIMESTAMP "UTC")PUBLISH TOPIC "logs/events" WITH {log_message}
DEFINE ACTION AuditLoggerON TOPIC "actions/+/executed" DO SET "action_name" WITH TOPIC POSITION 2 SET "utc_time" WITH TIMESTAMP "UTC" SET "unix_time" WITH TIMESTAMP "UNIX" // Human-readable log PUBLISH TOPIC "audit/" + {action_name} + "/log" WITH ("Action " + {action_name} + " executed at " + {utc_time}) // Machine-readable timestamp for database storage PUBLISH TOPIC "audit/" + {action_name} + "/timestamp" WITH {unix_time}
LoT supports callable actions - actions that can be invoked by other actions with input parameters and return values. This enables modular, reusable logic blocks.
DEFINE ACTION CalculateAverageINPUT value1 AS DOUBLEINPUT value2 AS DOUBLEDO SET "sum" WITH ({value1} + {value2}) SET "avg" WITH ({sum} / 2)RETURN OUTPUT avg
Use the callable action:
Copy
Ask AI
DEFINE ACTION ProcessSensorPairON TOPIC "sensors/pair/data" DO SET "temp1" WITH (GET JSON "sensor1" IN PAYLOAD AS DOUBLE) SET "temp2" WITH (GET JSON "sensor2" IN PAYLOAD AS DOUBLE) CALL ACTION CalculateAverage WITH value1 = {temp1}, value2 = {temp2} RETURN result PUBLISH TOPIC "sensors/average" WITH {result}
DEFINE ACTION AnalyzeValueINPUT value AS DOUBLEINPUT threshold AS DOUBLEDO SET "is_above" WITH ({value} > {threshold}) SET "difference" WITH ({value} - {threshold}) SET "percentage" WITH ({value} / {threshold} * 100)RETURN OUTPUT is_above OUTPUT difference OUTPUT percentage
Copy
Ask AI
DEFINE ACTION CheckThresholdON TOPIC "sensors/+/value" DO SET "sensor_id" WITH TOPIC POSITION 2 SET "current_value" WITH PAYLOAD AS DOUBLE SET "threshold" WITH (GET TOPIC "config/threshold" AS DOUBLE) CALL ACTION AnalyzeValue WITH value = {current_value}, threshold = {threshold} RETURN above, diff, pct PUBLISH TOPIC "analysis/" + {sensor_id} + "/above_threshold" WITH {above} PUBLISH TOPIC "analysis/" + {sensor_id} + "/difference" WITH {diff} PUBLISH TOPIC "analysis/" + {sensor_id} + "/percentage" WITH {pct}
Build reusable utility actions for common operations:
Copy
Ask AI
// Reusable temperature conversionDEFINE ACTION ConvertCelsiusToFahrenheitINPUT celsius AS DOUBLEDO SET "fahrenheit" WITH ({celsius} * 9 / 5 + 32)RETURN OUTPUT fahrenheit// Reusable percentage calculationDEFINE ACTION CalculatePercentageINPUT value AS DOUBLEINPUT total AS DOUBLEDO SET "pct" WITH ({value} / {total} * 100)RETURN OUTPUT pct// Main processing action using utilitiesDEFINE ACTION ProcessTemperatureReadingON TOPIC "sensors/+/celsius" DO SET "sensor_id" WITH TOPIC POSITION 2 SET "temp_c" WITH PAYLOAD AS DOUBLE SET "max_temp" WITH (GET TOPIC "config/max_temperature" AS DOUBLE) CALL ACTION ConvertCelsiusToFahrenheit WITH celsius = {temp_c} RETURN temp_f CALL ACTION CalculatePercentage WITH value = {temp_c}, total = {max_temp} RETURN capacity PUBLISH TOPIC "sensors/" + {sensor_id} + "/fahrenheit" WITH {temp_f} PUBLISH TOPIC "sensors/" + {sensor_id} + "/capacity_percent" WITH {capacity}
The TRIGGER statement allows actions to programmatically trigger route events or mappings. This is useful for initiating data pipeline operations or triggering external integrations.
// Trigger a route with payload dataTRIGGER "EmailRoute" TO PAYLOAD FOR "SendAlert"// Trigger with a variableSET "message" WITH ("Alert: " + {sensor_id} + " exceeded threshold")TRIGGER "NotificationRoute" TO {message} FOR "EmailMapping"// Trigger with a literal valueTRIGGER "DatabaseRoute" TO "backup_requested" FOR "BackupEvent"
DEFINE ACTION AlertHandlerON TOPIC "alerts/+/critical" DO SET "alert_type" WITH TOPIC POSITION 2 SET "alert_data" WITH PAYLOAD SET "timestamp" WITH TIMESTAMP "UTC" // Build alert message SET "message" WITH ("Critical alert [" + {alert_type} + "] at " + {timestamp}) // Trigger email notification route TRIGGER "EmailNotification" TO {message} FOR "CriticalAlertEmail" // Also trigger database storage TRIGGER "DatabaseStorage" TO {alert_data} FOR "StoreAlert" PUBLISH TOPIC "alerts/processed" WITH {alert_type}
DEFINE ACTION SendDailyReportON EVERY 24 HOURS DO SET "report_data" WITH (GET TOPIC "reports/daily/summary") TRIGGER "EmailRoute" TO {report_data} FOR "DailyReportEmail"
Copy
Ask AI
DEFINE ACTION ArchiveOldDataON EVERY 1 HOUR DO SET "cutoff_time" WITH TIMESTAMP "UNIX" TRIGGER "DatabaseRoute" TO {cutoff_time} FOR "ArchiveEvent"
Copy
Ask AI
DEFINE ACTION NotifyExternalSystemON TOPIC "events/important" DO TRIGGER "RestAPIRoute" TO PAYLOAD FOR "WebhookEvent"
CALL MCP allows actions to invoke tools provided by MCP (Model Context Protocol) routes. This enables integration with AI assistants and external tools.
DEFINE ROUTE FileSystem WITH TYPE MCP ADD MCP_CONFIG WITH SERVER_COMMAND "npx" WITH SERVER_ARGUMENTS "-y, @modelcontextprotocol/server-filesystem, /data" WITH CLIENT_NAME "CorefluxBroker"
// Call an MCP tool with argumentsCALL MCP "FileSystem.read_file" WITH (path = "/data/config.json") RETURN AS {file_content}// Call without argumentsCALL MCP "MyMCPRoute.list_resources" RETURN AS {resources}// Call with multiple argumentsCALL MCP "MyMCPRoute.echo" WITH (message = "Hello", count = 3) RETURN AS {response}
DEFINE ACTION ReadDeviceConfigON TOPIC "devices/+/request_config" DO SET "device_id" WITH TOPIC POSITION 2 SET "config_path" WITH "/configs/" + {device_id} + ".json" CALL MCP "FileSystem.read_file" WITH (path = {config_path}) RETURN AS {config_data} IF {config_data} == EMPTY THEN PUBLISH TOPIC "devices/" + {device_id} + "/config/error" WITH "Config not found" ELSE PUBLISH TOPIC "devices/" + {device_id} + "/config" WITH {config_data}
This example combines the key operations covered on this page—SET, GET TOPIC, GET JSON, arithmetic, IF/THEN, PUBLISH, and KEEP—in a realistic sensor processing action.
Copy
Ask AI
DEFINE ACTION ComprehensiveProcessorON TOPIC "sensors/+/data" DO // Extract sensor ID from topic path (POSITION 2 = the wildcard) SET "sensor_id" WITH TOPIC POSITION 2 // Parse JSON payload SET "temperature" WITH (GET JSON "temp" IN PAYLOAD AS DOUBLE) // Convert to Fahrenheit SET "fahrenheit" WITH ({temperature} * 9 / 5 + 32) // Conditional alerting IF {temperature} > 80 THEN PUBLISH TOPIC "alerts/" + {sensor_id} WITH "High temp: " + {temperature} // Publish processed data PUBLISH TOPIC "processed/" + {sensor_id} + "/temperature" WITH {temperature} PUBLISH TOPIC "processed/" + {sensor_id} + "/fahrenheit" WITH {fahrenheit} PUBLISH TOPIC "processed/" + {sensor_id} + "/timestamp" WITH TIMESTAMP "UTC" // Cache for later reference KEEP TOPIC "cache/" + {sensor_id} + "/last_reading" WITH PAYLOAD