Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Read trigger

Poll a view function on an interval and fire when a condition is met: health factors, utilization, oracle staleness, anything an eth_call can see.

rflow_version: 1
name: utilization-watch
 
config:
  port: 3940
  db_connection: ${DATABASE_URL}
 
networks:
  - name: ethereum
    chain_id: 1
    rpc: ${ETH_RPC}
 
contracts:
  LendingPool:
    abi: ./abis/lending-pool.json
    network: ethereum
    address: "0xPool..."
 
notifications:
  channels:
    ops:
      console: {}
 
workflows:
  high-utilization:
    trigger:
      read: 
        contract: LendingPool
        network: ethereum
        function: "getUtilization()"
        every: 1m
        condition: "${{ output > wei('0.95', 18) }}"
        mode: threshold          # threshold (default) | changed 
    steps:
      - id: alert
        notify:
          channel: ops
          message: "utilization crossed 95%: ${{ format_units(trigger.args.output, 18) }}"
FieldRequiredDescription
contractβœ…A contract registry name
networkβœ…A declared network
functionβœ…Solidity signature, e.g. getUtilization()
argsArguments, each of which may be an expression
everyβœ…Poll interval, e.g. 1m
conditionFiring condition over the decoded value; if omitted, every poll fires
modethresholdthreshold | changed; see below

The decoded value is available to the condition: expression as output (alias result), decoded exactly like a read: step.

Firing modes β€” edge-triggered, never spam

  • threshold (default) β€” fire when the condition is true and it was false on the previous poll: a falseβ†’true crossing. A condition that stays true fires once, not every minute.
  • changed β€” fire when the decoded value differs from the previous poll's (the first observation only records a baseline).

The previous poll's state is persisted per workflow (rflow.read_trigger_state), so a restart mid-"true" does not re-fire a threshold trigger.

The trigger context

PathDescription
trigger.args.output / trigger.args.valueThe decoded read value at fire time
trigger.read.function, trigger.read.networkWhat was polled
trigger.read.observed_atObservation timestamp (ISO)

Exactly-once

Each fire claims read:{workflow}:{poll instant}: one run per polling instant, and the persisted edge state carries the dedupe across restarts.