Flows
Flows are reactive data processing pipelines that transform and analyze telemetry data in real time. Written in BtScript (a Scheme dialect) or C#, flows enable sophisticated event-driven automation across your IoT infrastructure.
What is a Flow?
A flow is a virtual actor that processes input signals and produces output signals. When telemetry arrives from assets, flows react to the data, perform computations, and emit results or trigger actions.
Flows are compiled to .NET assemblies and run as FlowGrains (Orleans virtual actors) in the asset processor silo. This architecture provides automatic scaling, fault tolerance, and location transparency.
Artifact Types
Beacon Tower uses three artifact types, each identified by a BTI (Beacon Tower Identifier) prefix:
- Flow (
btf:) — A complete data processing pipeline - Task (
btft:) — Reusable computation with state - Function (
btff:) — Stateless reusable computation
Development Workflow
- Write BtScript code in a
.btsfile - Compile to a .NET assembly using the BtScript compiler
- Upload the artifact to the artifact registry (PostgreSQL)
- Create runtime instances attached to specific assets
See the Local Flow Development guide for detailed setup instructions.
BtScript Language
BtScript is a Scheme dialect with S-expression syntax. Flows define input bindings, triggers, computations, and outputs in a reactive programming model.
(flow id: temp-conversion
(inputs
(celsius "sensor.temperature"))
(trigger on-any: celsius)
(let ((fahrenheit (+ (* celsius 1.8) 32)))
(emit fahrenheit-output value: fahrenheit)))
See the BtScript Overview for a language introduction and the BtScript Language Reference for complete syntax documentation.
Flow Triggers
Triggers determine when a flow executes. All input signals must receive at least one value before the flow can run.
on-any:— Activate when any listed signal updateson-all:— Activate when all listed signals have new values (synchronized)on-timer:— Activate on a schedule (ISO 8601 duration, e.g.,PT5M)on-change:— Activate when a signal value changes (not just updates)
(trigger on-any: vibration temperature)
(trigger on-timer: PT5M)
Active vs Passive Inputs
Inputs listed in the trigger are active (can wake the flow). Inputs not listed are passive (read via (latest x) without triggering execution).
Gates
Gates provide internal synchronization points separate from the main trigger. Use zip: to wait for multiple signals or on-timer: for periodic synchronization within a flow.
(gate zip: pressure temperature)
State Management
Flows maintain state across executions for rolling aggregations and time-windowed computations. State persistence modes include sync, async, timer-based, on-deactivate, or none.
(rolling-avg window: PT5M input: vibration as: vib-avg)
For a comprehensive guide to persistence options and state management patterns, see Persistence & State.
Output and Reusable Artifacts
Flows emit values using the emit form. For conditional logic, use cond, when, and begin to control output behavior.
Tasks (stateful, btft:) and functions (stateless, btff:) are reusable computation artifacts that can be shared across flows. Declare dependencies with require and reference them by BTI identifier.
For details on tasks, functions, parallel execution, and advanced language features, see the BtScript Language Reference.
Flow Service API
The Flow Service provides HTTP endpoints for managing artifacts and runtime instances.
Note: The Flow Service runs separately from the core Beacon Tower API and uses a different base URL.
Upload Artifact
POST /api/v1/artifacts
Content-Type: multipart/form-data
inputType: btscript
file: pump-monitor.bts
Query Artifacts
GET /api/v1/artifacts
Create Runtime Instance
POST /api/v1/instances
Content-Type: application/json
{
"bti": "btf:pump-monitor;1.0.0",
"assetId": "pump_42"
}
This creates a FlowGrain instance that binds the flow to the specified asset's telemetry signals.
Error Handling
Flows should handle errors using conditional logic and defensive programming. When a flow throws an unhandled exception, the FlowGrain logs the error and remains dormant until the next valid input arrives.
For details on the compilation pipeline and runtime architecture, see Compilation & Runtime.
Next Steps
- BtScript Overview — Language introduction and architecture
- BtScript Language Reference — Complete syntax reference
- Telemetry Ingestion — Message format, headers, and data validation
- Telemetry and Timeseries — Signal data models
- Local Flow Development — Set up your development environment