Pre-Bedrock filter
⚠ Template render-check failed — this would error on the first ACTIVE run
Action results (per step)
No additional output captured for this step.
Decision: no action
Bedrock returned should_act=false with no reasoning.
Action Preview
Would execute:
Error
No executions yet
No workflows configured
Create one to start automating event responses
No workflows match ""
Recent Executions
No matching events
| Status | Workflow | Version | Event | Action | Started | Duration | Tokens | Cost | |
|---|---|---|---|---|---|---|---|---|---|
Execution Detail
Error:
Chain did not finish
of steps recorded an outcome. The executor was killed mid-chain (Lambda timeout, out-of-memory, or a hard crash).
- Steps below marked COMPLETED did take effect.
- unknown outcome — each may have completed its external side effect before the process died. Check the target system before redoing any of them by hand.
- Steps after that never started.
Action results (per step)
No additional output captured for this step.
Event Payload:
Run timeline:
Repeated across rounds — the rounds themselves ran one after another:
Bedrock Response:
Template render-check failed — would error on the first ACTIVE run
Action preview (legacy)
Based on
No catalogued events yet — use the custom input below.
No catalogued event matches this filter. Events not in the catalogue can still be added below.
Custom
· Unknown event types are accepted — the router discards events with no subscribing workflow.
When unchecked, the workflow skips Bedrock and runs the action chain deterministically — useful when the event payload already contains everything the action needs (e.g. driver-tracking Slack messages templated directly off the SNS event).
Only superadmins can change the model. Contact a superadmin if you need a different one.
Changing the model on an ACTIVE workflow creates a new DRY_RUN version — not applied to the live version until promoted.
The selection mode can't change across versions — disable this workflow and create a new one to switch.
Renders {field_name} placeholders against the event payload at execute time.
Used by deterministic event-driven workflows that bypass Bedrock — leave empty when the message is
composed by the model (it'll come through action_data.message instead).
Max 2000 chars.
When set, the gateway renders this template and the literal subject/body fields below must be left blank. Leave empty to compose the email inline.
Map a gateway variable path to a column expression. Dotted keys nest (change.summary → { change: { summary } }); values support dotted paths and filters: {event.payload.listing.id}, |default('—').
Freetext; supports dotted paths and filters (e.g. {payload.listing_id}, |date('g:ia'), |default('—')).
Map a gateway context key (userId, listingId, journeyId, …) to a column expression. Empty/missing values are dropped at send time; max 16 entries.
Set exactly one of: body_template, body_column, or template_id.
Each row maps a template variable name to a column expression. Column expressions support dotted paths and filters: payload.first_name, payload.ts|date('g:ia').
Freetext; supports dotted paths and filters (e.g. {payload.listing_id}, |date('g:ia'), |default('—')).
Map a gateway context key (userId, listingId, journeyId, …) to a column expression. Empty/missing values are dropped at send time; max 16 entries.
Gateway-side template name (configured in messaging-gateway).
Each row maps a template variable name to a column expression. Column expressions support dotted paths and filters.
Freetext; supports dotted paths and filters (e.g. {payload.listing_id}, |date('g:ia'), |default('—')).
Map a gateway context key (userId, listingId, journeyId, …) to a column expression. Empty/missing values are dropped at send time; max 16 entries.
Use {column_name} to substitute row values. Same syntax as Slack notification templates.
Twilio content template SID. Gateway renders templateVars server-side.
Each row maps a template variable name to a column expression. Column expressions support dotted paths and filters, e.g. payload.driver_phone or payload.ts_start_local|date('g:ia').
Freetext; supports dotted paths and filters (e.g. {payload.listing_id}, |date('g:ia'), |default('—')).
Map a gateway context key (userId, listingId, journeyId, …) to a column expression. Empty/missing values are dropped at send time; max 16 entries.
Producer-holds-the-key: pick a name_template that's deterministic for the same logical event
(e.g. tp-followup-{listing_id}) so a re-fired source event reschedules in place rather than creating a duplicate.
Schedule group on the AWS Scheduler side. Convention: the source service that owns this schedule.
Use {column_name} to substitute row values. Re-firing for the same row should produce the same name.
AWS Scheduler expression. Typical: at(2026-05-17T09:00:00) for one-off, or a column substitution like at({fire_at_iso}).
IANA timezone, e.g. Europe/London, UTC.
Each row maps a key in the fired schedule's payload to a value template. Values support {column_name} substitution and dotted paths (e.g. {listing_id}, trustpilot-followup).
Embedded into the schedule's payload when it fires. Values are rendered against the row using the same {column} substitution.
Include an event_type key if a follow-up workflow should run when the schedule fires (e.g. event_type = TRUSTPILOT_FOLLOWUP_DUE). Without it the fired message has nowhere to route and lands in the scheduled-events DLQ.
Cancels a schedule previously created with SCHEDULE_EVENT_UPSERT. Supply the same service and name_template used at upsert time. 404 on the DELETE is treated as success — "be gone" is the goal regardless of whether the schedule still existed.
Must match the template used at upsert time so the keys line up.
Posts an admin note onto a V4 listing via POST /v1/listings/{listingId}/admin-note/{userId}. Both ids must resolve to a positive integer after templating.
Templated — must resolve to a positive integer. In AI workflows action_data is the Bedrock output, so read raw event fields via the reserved {event.*} namespace, e.g. {event.payload.listing_id}.
V4 user_id recorded as the note author. Defaults to 5987021, the dedicated Workflow user in the production DB; can be overridden with a static id or a templated column.
The note body (plain text). Supports {column} substitution and dotted paths. For an AI-authored note use the model's output key (e.g. {message}); reach raw event fields via {event.*}.
V4 admin_listing_notes.status. Blank → server default 1 (NEW_NORMAL); 2 = OLD_SAVED.
Blank → server default 0. 1 = callback flag.
Hides a listing's customer feedback via POST /v1/listings/{listingId}/feedback/hide/{userId} — flips listing_feedback.status to HIDDEN and emits LISTING_FEEDBACK_HIDDEN. Idempotent (already-hidden is a no-op). Both ids must resolve to a positive integer after templating. Pair with a LISTING_NOTE_CREATE step to record why it was hidden.
Templated — must resolve to a positive integer. In AI workflows action_data is the Bedrock output, so read raw event fields via the reserved {event.*} namespace, e.g. {event.payload.listing_id}.
Recorded as edited_by on the customer-visible feedback row, so it is always the dedicated Workflow user (5987021) — no admin is selectable here. Shows the value this step actually carries, which may differ on a workflow authored before this field was fixed.
Creates a Freshdesk ticket (POST /tickets). Every field is a static value or a template; in AI workflows read raw event fields via {event.*} and model output via its keys (e.g. {message}).
Interpolated values are HTML-escaped.
2=Open,3=Pending,4=Resolved,5=Closed. Blank → 2.
1=Low..4=Urgent. Blank → 1.
JSON object keyed by the Freshdesk cf_* internal field name (not its label). A string value is sent as templated, HTML-escaped text. For a Freshdesk number field, use {"cf_x":{"value":"{...}","type":"number"}} — it's coerced to a number (a plain string is rejected as a type mismatch).
Updates an existing ticket (PUT /tickets/{id}). Only the fields you set are sent; the rest are left unchanged.
2=Open,3=Pending,4=Resolved,5=Closed.
1=Low..4=Urgent.
Numeric Freshdesk agent id. Required to resolve/close (status 4/5) — Freshdesk rejects resolving an unassigned ticket.
JSON object keyed by the Freshdesk cf_* internal field name (not its label). A string value is sent as templated, HTML-escaped text. For a Freshdesk number field, use {"cf_x":{"value":"{...}","type":"number"}} — it's coerced to a number (a plain string is rejected as a type mismatch).
Adds a note (internal, default private) or a customer-facing reply to an existing ticket.
Updates field values on an existing Formstack submission (v2025 API). Creating submissions is not supported.
Keyed by field_<NNN>. value_type ∈ text|name|address|choice. text/choice use source; name/address use subfields.
Shortens a URL into an anyvan.link link. The result is exposed as {short_url} for a later step to embed (e.g. an SMS body Track your move: {steps[0].short_url}).
Templated against action_data — use {event.*} and {steps[N].*}.
Records the facts this workflow decided into Snowflake (DWH_LANDING.{ENV}.EVENTBUS_EVENTS). Only ACTIVE workflows publish — in DRY_RUN the chain is collapsed to a single NOOP before dispatch, so these templates are never rendered. Use the render check to validate them before promoting; it is the only pre-promotion check they get.
A map of { name: template } that becomes the event's payload.data. Names must be lower snake_case so they stay dot-navigable in Snowflake. A template that renders empty is published as JSON null, not omitted.
Name only the fields that should land as a number or boolean. Everything else stays text on purpose — coercing by guesswork would turn a reference like 0012 into 12.
Groups related events downstream. Defaults to this execution.
Steps run in order. A failing step does not stop the next.
SLACK_NOTIFICATION pre-set config (optional)
Leave both blank for no pre-set config. A message template needs a Channel ID alongside it; the template renders against the model's action_data.
The model chooses which of these to run per event — possibly none. The action-executor's Slack-channel allow-list below still applies.
Skip this event before hitting Bedrock when the expression is false.
Syntax & examples
Operators: = != > < >= <= IN (...) CONTAINS IS NULL IS NOT NULL.
Combine with AND, OR, NOT, and parentheses.
Paths are dotted, e.g. payload.listing.total.
Relative dates (compared in UTC): "@today", "@tomorrow", "@yesterday", "@now",
with offsets "@today+7d", "@today-1d", "@now-2h", "@now+30m".
Add an IANA timezone suffix to use that zone's calendar day instead of UTC:
"@today:Europe/London", "@today+2d:Europe/London" (keeps day windows aligned with local midnight across DST).
- pickup today or tomorrow:
payload.listing.date >= "@today" AND payload.listing.date <= "@today+1d" - pickup within the next 7 days:
payload.listing.date <= "@today+7d" - pickup today or tomorrow (list form):
payload.listing.date IN ("@today", "@tomorrow") - changed in the last 2 hours:
payload.someTimestamp >= "@now-2h" - pickup in the next 2 days, UK local days:
payload.listing.date >= "@today:Europe/London" AND payload.listing.date <= "@today+2d:Europe/London"
Enrichers run before Bedrock. Their output is merged and appended as "Enrichment: { ... }" to the user message.
Bedrock can call selected tools mid-decision, see the result, then continue. Costs an extra Bedrock turn per call — the loop's hard ceiling caps runaway thinking.
Hard ceiling on the agentic loop. Most decisions converge in 2–4 iterations.
Parameters
Error:
Parsed:
Referenced objects:
Estimated scan bytes:
Within threshold:
Rows:
Queried at: (query run time, not data freshness)
Elapsed:
Named SQL the snowflake_query tool can run during the agentic loop. Bedrock picks a query by name and supplies parameter values. "Test query" runs an EXPLAIN (parse + scan estimate, no data); "Run sample" executes it with the sample values and previews the rows.
Comma-separated channel IDs / #names / Slack links. Enforced by the action-executor for SLACK_NOTIFICATION and NOTIFY (method=slack). Leave blank for no restriction — an explicit empty list would block every channel.
Only superadmins can set status to Active. A superadmin will review your dry-run executions and promote this workflow when ready.
Draft with AI
Describe the workflow in plain language. The draft replaces whatever is currently in the form; review and edit it before saving — nothing is created until you click Create Workflow.
Paste a real payload from an execution so the draft references actual field paths.
Fields are aligned row by row — removed on the left, added on the right.
Group
No earlier version in this group to compare against.
What changed
Summary AI-generated
Summarising the changes…
Advisory only — read the diff below before promoting. The flags above are computed, not AI-written.
Namechanged
Namechanged
Descriptionchanged
Descriptionchanged
AI evaluationchanged
AI evaluationchanged
Modelchanged
Modelchanged
Task instructionschanged
Task instructionschanged
Agent role & ruleschanged
Agent role & ruleschanged
Action selectionchanged
Action selectionchanged
Actionschanged
—
Actionschanged
—
—
—
Subscribed eventschanged
Subscribed eventschanged
Event filterchanged
Event filterchanged
Enricherschanged
Enricherschanged
Agentic toolschanged
Agentic toolschanged
Max iterationschanged
Max iterationschanged
Snowflake querieschanged
—
Snowflake querieschanged
—
—
—
Allowed Slack channelschanged
Allowed Slack channelschanged