New to Kestra?
Use blueprints to kickstart your first workflows.
List Airtable records missing a required field, alert Slack with the record IDs, and log the result for ops teams.
A shared Airtable base drifts out of compliance one blank cell at a time: a record created without an owner, a status nobody set, a required approval field nobody filled in. Airtable has no native rule that pages anyone when a required field goes missing, it just sits blank until someone opens the view and notices. This blueprint reads what is actually blank right now, using Airtable's own formula filter, and reports it with the real record IDs attached.
This blueprint was created by Mohit Jeswani.
list_incomplete_records (io.kestra.plugin.airtable.records.List) runs a
filterByFormula of {<required_field_name>} = BLANK() against the table, so Airtable's
own API does the blank check server-side instead of this flow paging through every record
to check client-side. Read-only; nothing in Airtable is changed. allowFailure: true
covers an API or auth error without failing the flow outright.evaluate (io.kestra.plugin.core.output.OutputValues) reads the matched count directly
from the API response's own size field and collects the matched record IDs with a jq
filter.route (io.kestra.plugin.core.flow.If):summary logs the count and severity, closing the governance cycle.errors alerts Slack if the flow itself fails, for example an expired personal access
token.records.List used with
filterByFormula for a governance check, distinct from this repo's existing Airtable
blueprint, which only writes records via records.Create rather than auditing them.Airtable's formula filter answers one query at a time; it does not keep a schedule, compare
the result against a tolerance you declare, or notify a Slack channel when blanks pile up.
Kestra keeps required_field_name and max_incomplete_count as flow inputs, turns the
filtered query into a Slack page naming the actual record IDs, and keeps a full execution
history of every run.
required_field_name
blank, to confirm the filter logic against.This flow calls the Airtable API directly over HTTPS; there is no official local Airtable
emulator, so list_incomplete_records cannot be exercised against a local Docker container.
AIRTABLE_PERSONAL_ACCESS_TOKEN: the Airtable personal access token used by
list_incomplete_records. In Kestra OSS, provide it as the base64-encoded environment
variable SECRET_AIRTABLE_PERSONAL_ACCESS_TOKEN.SLACK_WEBHOOK_URL: used by alert and the errors block. In Kestra OSS, provide it as
the base64-encoded environment variable SECRET_SLACK_WEBHOOK_URL.| Input | Default | Purpose |
|---|---|---|
airtable_table_id |
<your-table-name> |
Table to audit |
required_field_name |
Owner |
Field that must never be blank |
max_incomplete_count |
1 |
Blank-record count that triggers the Slack alert |
{{ outputs.list_incomplete_records.rows }}: every matched record (id, createdTime,
fields).{{ outputs.evaluate.values.incomplete_count }} / .incomplete_ids: how many records are
incomplete and their IDs, semicolon-joined.{{ outputs.evaluate.values.severity }}: OK, COMPLIANCE_BREACH, or CRITICAL.required_field_name must match the Airtable field's exact display name, including
spacing and case; a mismatched name makes the formula reference a field that does not
exist and the filter matches nothing rather than erroring.BLANK() matches an empty text value or an unset field; a field explicitly set to the
number 0 or the text "false" is not blank and will not match, which is correct
behavior but can look surprising for a boolean-style field.enableAutoPagination: true fetches every matching page; on a very large table with many
blank records this can take several API calls, each subject to Airtable's own rate limits.AIRTABLE_PERSONAL_ACCESS_TOKEN and SLACK_WEBHOOK_URL secrets.airtable_base_id, airtable_table_id, and required_field_name to a real table and
field.summary logs a count.alert
fires with its record ID.daily trigger once the inputs reflect your real base and compliance policy.required_field_name values with io.kestra.plugin.core.flow.Loop to
enforce more than one required field in a single scheduled run.io.kestra.plugin.airtable.records.Update on each incomplete record to set a
"Needs Review" status field, gated behind an explicit confirm_flag input so tagging never
runs by accident.incomplete_ids by a "Team" or "Owner" field already present on related records to
route each team's incomplete records to its own Slack channel.