Skip to main content

Refractions

A Refraction is an event-driven, no-code workflow graph. A trigger starts it; Stages run in sequence, wired by pass / fail edges; and the run is recorded as an execution.

Triggers

A Refraction starts from one or more trigger nodes:

TriggerFires when
On SignalA matching Signal type arrives (optionally from specific source Facets).
On scheduleA fixed interval, cron expression (in the org timezone), or one-time time.
On API callAn inbound HTTP webhook hits the trigger's key.

Multiple triggers on one Refraction are OR — each starts its own run.

The API trigger exposes an authenticated webhook: POST /api/v1/triggers/<key> with a bearer key managed (create / reveal / rotate) on the Refraction. It supports a "learning mode" that locks the expected payload shape.

Stage catalog

Stages come from a rich, shipped set. Grouped by purpose:

Control flow — filter, conditional branch, for-each, delay, wait-until, wait-for-signal, wait-for-approval (a human gate → the Approvals inbox), assert, dedupe, rate-limit, stop.

Data — transform payload (expression DSL), set variables, format template, lookup.

Capture Sets — save to capture set, enrich from capture set, query capture set, update row, export capture set.

Device — facet command (typed parameters from the device's capability manifest; fails cleanly if the device is offline).

Integrations — call API (HTTP), send webhook (HMAC-signed), GraphQL, publish to an external MQTT broker, put an object to storage.

Notifications — email, Slack, Telegram, Discord, Microsoft Teams, PagerDuty, SMS, WhatsApp.

AI / ML — call LLM (Anthropic / OpenAI-compatible / Ollama), classify, extract, OCR.

caution

Integration and notification stages let a Refraction reach external systems your org configures — treat destinations as you would any outbound webhook target.

Conditions & expressions

A filter stage evaluates conditions against the Signal and the run's data. Operators are typed to the field:

  • String — equals, not-equals, contains, starts-with, regex.
  • Number=, !=, >, <, >=, <=, in-range.
  • Boolean — is-true / is-false.
  • List — in-list / not-in-list (great for EPC allow/blocklists).
  • Datetime — before / after / between.
  • Time-of-day — before / after / between a clock time, with a per-condition timezone; overnight windows wrap.

Conditions in a filter are combined with AND. A fail edge out of a filter or branch means condition not met — that is a normal outcome, not an error, and does not raise a failure alert.

Fields can reference a reserved envelope in any input or {{template}}: $facet.* (id, label, agent name, hardware id, type, status, site, org) and $signal.* (id, type, facet id, received at). The transform stage exposes a sandboxed function library (string ops like substr / upper / concat, encoding helpers like hex_to_ascii / hex_to_int, and numeric coercion).

Test, enable, disable

  • Test runs the graph against a chosen real trigger payload. It is a live run — side effects fire — and is always confirmed with an itemized summary first.
  • Enable activates the Refraction so it processes live Signals; Disable stops it. Both are admin actions. The graph is validated on save (no unknown stages, no dangling edges).

Executions

Every run is an execution with a status of running, completed, failed, or partial, plus per-stage results, duration, and the count of Capture Set rows written. The Executions view shows the stage chain like a CI pipeline, with live status and click-to-inspect panels, and links to the rows a run produced.

Long-running stages (an API call, a delay, waiting for a signal or an approval) pause and resume rather than blocking. A Refraction can raise a failure alert (email / Slack) on failed executions.