UniteLabs
Concepts

Subscription

How you consume Sensor-type actions (and streaming Controls) over time.

A subscription is a long-lived consumption of a streaming action — primarily a Sensor, and in some cases a long-running Control that emits progress updates before it completes.

When you subscribe to a Sensor the connector pushes values as they change (or on a fixed interval). When you consume a long-running Control as a stream you get status updates — "spinning up", "at target speed", "complete" — followed by the final result.

In the UI, a Sensor opens a live-stream panel when you click Subscribe. In the SDK the same thing is handled with an async for loop. See the Terminology table.

Creating a subscription

From Python, subscribing is the same as calling any streaming action:

async for change in file_system.folder_service.changes():
    print(change)

The async for loop stays open as long as you want to consume the stream. Break out to cancel it.

From the REST API, create a subscription explicitly with the action ID and a polling interval:

curl -X POST "$BASE_URL/v1/subscriptions" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "<action-uuid>",
    "parameters": {},
    "interval": 1000
  }'

And cancel it explicitly:

curl -X DELETE "$BASE_URL/v1/subscriptions/$SUBSCRIPTION_ID" \
  -H "Authorization: Bearer $TOKEN"

When you subscribe

Two situations produce subscriptions:

  • Sensor actions — the primary case. A Sensor exists specifically to stream values over time (file-system changes, live sensor feeds, monitoring readings). You subscribe to receive each new value as it arrives.
  • Streaming Control actions — the secondary case. A Control that takes time to complete can report progress as it runs (centrifuge spin, PCR cycle, plate move). You subscribe to receive status updates and intermediate results, concluding with the Control's final return value.

You subscribe to both the same way. The difference is what comes down the pipe.

Lifecycle and reliability

An active subscription holds open a streaming connection between the platform and the connector. Platform-side we invest heavily in keeping these connections alive across temporary network failures — reconnecting automatically when the connector becomes reachable again. But subscriptions do not live forever. They end when:

  • You cancel them explicitly (breaking out of async for, or DELETE /v1/subscriptions/{id})
  • The connection closes and cannot be re-established
  • The run or workflow they belong to finishes — workflow-scoped subscriptions are cleaned up automatically when the workflow completes

Do not leak subscriptions. Long-running scripts that fan out subscriptions and never close them can exhaust connector resources and confuse downstream consumers that see stale streams.

Listing active subscriptions

curl "$BASE_URL/v1/subscriptions" \
  -H "Authorization: Bearer $TOKEN"

Useful when debugging leaked streams from a previous run, or when verifying that a new subscription registered before a dependent component starts consuming it.