Decorate a function with @sensor(job=my_job, minimum_interval_seconds=60) to define a polling sensor
Inside the sensor function, query the external system (database, API, S3 prefix) using a resource passed via context.resources
Yield RunRequest(run_key=unique_id, run_config={...}) for each item that should trigger a new run; the run_key deduplicates requests so the same item never triggers twice
Yield SkipReason('no new items') when there is nothing to process to suppress spurious run history entries
Store cursor state using context.update_cursor(cursor_value) to track the last-processed position (timestamp, offset, file name) across sensor evaluations
Test the sensor locally with the Dagster UI sensor ticketing view or by calling the sensor function directly with build_sensor_context
Known gotchas
run_key uniqueness is global within a code location — reusing a run_key across different logical items silently deduplicates and drops the second request
Sensors evaluate on the Dagster daemon process; expensive or slow external queries in the sensor body block the daemon and delay other sensors — offload heavy lookups to an asset or op
Cursor state is only persisted if the sensor evaluation completes without raising an exception; partial state updates are rolled back on error, which can cause reprocessing of already-seen items
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp