constants, secrets & lists
Three ways to get values into your expressions.
constants
Static values, addressable as ${{ constants.<name> }}:
constants:
scale_bps: "2500"
treasury: "0x1f9090aaE28b8a3dCeaDf281B0F12828e676c326"args: ["${{ mul_div(trigger.args.amount0, constants.scale_bps, 10000) }}"]secrets
Like constants, but log-redacted: anything under secrets: never appears in
rflow's logs or journal output. Addressable as ${{ secrets.<name> }}.
secrets:
HOOK_KEY: ${BACKEND_HMAC_KEY}Note the two layers here: ${BACKEND_HMAC_KEY} is plain environment substitution at
load time; ${{ secrets.HOOK_KEY }} is the expression that reads it at run time.
The typical consumers are an http_call HMAC and a
webhook trigger's inbound verification:
- id: notify-backend
http_call:
url: ${BACKEND_URL}
hmac: "${{ secrets.HOOK_KEY }}"
body: { tx: "${{ trigger.tx_hash }}" }from — external secret providers
Instead of a ${VAR} string, a secret's value may be a from: reference that
rflow fetches from AWS Secrets Manager or GCP Secret Manager at boot —
so production API keys never live in .env or the config file:
secret_providers:
aws-prod:
aws_secrets_manager:
region: eu-west-1
prefix: /rflow/prod/
secrets:
PRICE_API_KEY:
from:
provider: aws-prod
key: price-api-key
HOOK_KEY: ${BACKEND_HMAC_KEY} # both forms coexistResolution is fail-closed (a missing/denied secret aborts the boot with the
provider + key named) and a fetched value redacts identically to a declared
one, everywhere. .env stays the zero-config default — a project with no
secret_providers: behaves exactly as before. Full provider config, IAM
pointers and the rflow secrets ls|doctor commands:
external secret providers.
lists
Runtime-mutable watchlists, backed by Postgres. Seed them in YAML and use them with
the in operator:
lists:
watched_traders:
seed: ["0xWhale1...", "0xWhale2..."]trigger:
event:
contract: AnyPool
name: Swap
network: ethereum
where: "${{ trigger.args.sender in lists.watched_traders }}"Membership checks against address lists are case-insensitive — see address semantics.
| Field | Description |
|---|---|
seed | Initial members, owned by the YAML |
source | Refresh members from http: / sql: / file: on an interval — see below |
A list's effective membership is the union of the seed, runtime members
(written by rflow list add and
list_add: / list_remove: steps),
and source-refreshed members. rflow list show breaks members down by
provenance. Mutations are visible to the very next where: evaluation.
source — http / sql / file
lists:
watched_traders:
seed: ["0xWhale1..."]
source:
http:
url: https://api.example.com/traders
json_path: "$.data[*].address" # default $ — the body is already an array
refresh: 5m # default 5m
vip_vaults:
source:
sql: "SELECT address FROM analytics.vip_vaults" # single read-only SELECT, same Postgres
blocked:
source:
file: ./blocked.txt # newline-separated, # comments skippedA refresh atomically replaces only the source-tagged rows — seed, manual and workflow members survive every refresh. Values are trimmed, deduplicated and address-shaped entries lowercased.