Corteksa
GuidesAutomation

Best Practices

Automation — Best Practices

The recommended way to build reliable, correct workflows.

✓ Start narrow, then widen

Pick the tightest trigger for the intent — status_changed to one value beats field_changed on a broad set of fields. Add filter_config conditions so the action only runs on the records you mean. A skipped execution is cheap; a wrong send is not.

✓ Validate before you activate

Call POST /workflow/meta/validate-session-link (message triggers) and POST /workflow/:slug/test (dry run) before flipping the toggle. Activation enforces the same session-link gate anyway — catch it in the builder, not with a failed live run.

✓ Reference everything by slug

object_slug, session_slug, field_slug, status_field_slug are stable across environments. Never build a config around a numeric id — it breaks across dev/stage/prod and data migrations.

✓ Let variables do the work

Personalize with {{field_slug}}, trigger diff ({{old_value}}, {{new_value}}, {{admin_name}}), system dates ({{today}}, {{TODAY + 3}}), and message context ({{message_body}}, {{sender_name}}). Pull the palette from GET /workflow/meta/variables/:triggerType.

✓ Design actions to be idempotent

Runs can retry (Bull, provider webhook retries). An update_field that sets an absolute value is safe to run twice; a webhook receiver should de-dupe on record_slug + timestamp. Don't assume exactly-once.

✓ Verify outbound webhook signatures

Always check X-Workflow-Signature (HMAC-SHA256 of the raw body with your shared secret) before trusting a send_webhook payload. Never target private/local URLs — the engine blocks them.

✓ Watch runs, don't poll

Subscribe to /workflow/events for execution.completed/failed/skipped and stats.updated. Fall back to GET /workflow/:slug/executions for history, not as a live poll.

✓ Mind the limits

Per workspace: 50 workflows, ≤ 20 filter conditions, ≤ 10 field updates per action, 4096-char message templates. Workflow runs also draw on the workspace's monthly execution allowance — exhausted allowance skips new runs.

✓ Pace bulk sends

For scheduled reminder campaigns on WhatsApp, use the trigger's send_guard (daily cap, random gaps, rest breaks, warm-up) so a fresh number isn't blasted and flagged. Matches roll over across ticks instead of firing all at once.

✗ Don't rely on a workflow re-triggering itself

An action's own CRM write is tagged sourceType: "automation" and won't re-fire the engine (loop prevention). Model multi-step logic with steps[] (Action / Delay / Condition / Approval), not by chaining separate workflows through side effects.

✗ Don't reach past the pinned connection

When extending the engine, all DB access goes through repoProvider and every processor handler is @TenantScoped(). A raw DataSource bypasses RLS on hyper-tenant and silently reads/writes zero rows. See Backend Integration.

On this page