BytesMap
Automate

Workflow automation

Build, review and run effects with conditions, inputs and revision control.

Open Markdown

Review means automatic rules. A workflow reads its inputs and data, filters records, and follows the matching Condition path. It does not wait for a person to approve a run. Schedule that workflow to check those rules periodically, or run it from an existing button or form.

Build the logic

The action canvas has twelve generic operations. Choose every field, condition and destination explicitly; there are no built-in customer, account or support rules.

NodePurpose
StartConfigure triggers, declare typed inputs and optionally choose a database.
Saved queryReuse a saved visual or native query and bind its parameters.
SQL / native queryRead with the database's native language in the middle of a workflow.
Filter recordsKeep records matching AND/OR/NOT conditions in an already fetched list.
Map valuesBuild values or records from inputs, earlier results and expressions.
ValidateStop when a required rule fails.
ConditionChoose the true or false path automatically.
HTTP requestCall a REST endpoint with a method, URL, headers and optional JSON/text body.
Send notificationSend a bound title/message through existing notification channels.
Insert recordMap fields for one new PostgreSQL record.
Update recordIdentify one PostgreSQL record and verify original values before changing it.
Return resultEnd a path and optionally return a value.

For example: Start → Saved query → Filter records → Condition. The true path can call an API and notify a channel; the false path can go straight to Return result. The user supplies the rules. Filters operate on the returned batch. Put aggregation and filtering in the query when a decision needs the full database population; query row limits and truncation metadata still apply.

SQL parameters use :name and explicit value bindings. PostgreSQL and MySQL retain their existing positional syntax too; one statement cannot mix positional and named parameters. The shared lexer preserves strings, comments and casts, and drivers receive values separately. SQLite uses its native named bindings. Non-SQL native steps use their source language; use Saved query for dynamic parameters on those sources. Native steps are reads: use record steps for database mutations.

HTTP supports GET, POST, PUT, PATCH, DELETE and HEAD. Its result exposes body, status and ok. Enable Continue with error responses to route non-success status codes through a Condition. Transport failures still stop the step. Bearer, Basic and API-key headers can be saved through the encrypted vault after saving the draft. Credentials belong to that workflow and exact API origin; definitions contain only the reference. Ordinary authored headers are visible in the definition. Requests do not follow redirects. The existing outbound-network policy permits public HTTPS; desktop/self-hosted deployments can opt in to internal HTTP with BYTESMAP_NOTIFY_ALLOW_INTERNAL.

Opening, editing, saving and publishing a workflow does not execute its queries, requests or messages. Publication checks paths, read-only native syntax, bindings, permissions and destinations. The HTTP timeout is editable from 1–120 seconds. Request and response bodies are bounded to 1 MiB.

Configure triggers on Start

Select the workflow's Start → Triggers & inputs, either in its own editor or expanded inside a View. Both use the same trigger editor. Publish the current draft before adding an automatic trigger. A workflow can be called from a View button or the API, and can also have schedule and data-condition triggers. They all execute the same published workflow through the same runtime.

Incoming API request → Connection details shows the published workflow's endpoint and a copyable HTTP example with its typed inputs. It uses the normal POST /api/actions/:id/run operation and a workspace API key with Run and dependency access. A webhook sender can call it when it supports a custom authorization header and JSON body; fixed third-party payloads need an application adapter. Set requestKey to the incoming event/delivery ID and reuse the same key and payload on retries. Viewing or copying the example does not execute the workflow. Draft changes do not change the shown input contract, and the request's revision remains explicitly pinned.

Schedule trigger runs with configured starting inputs. Data condition checks a saved query and runs the workflow when that query returns at least one record. Choose the output for a visual data flow and bind its parameters. Define filters and aggregate thresholds in the query builder; for example, return a row only when the number of backend errors exceeds your threshold. A plain COUNT(*) returns a row even when its value is zero, so add the threshold condition in that query.

The default Once when the condition becomes true runs on the first matching check, then waits for a nonmatching check before it can run again. Once when the condition stops being true waits for a matching check, then runs once when a later check returns no records. An initially empty result does not fire a clearing trigger. Every check while the condition is true runs on each matching check. Checks that do not meet the selected transition appear in history as Condition not triggered. A matched check consumes its transition even if the action fails; review the failed run before using Run now to retry. Manual Run now evaluates the condition too, ignores the previous match, and leaves the automatic transition state unchanged. For a clearing trigger, Run now runs only when there are no matching records. Calling the workflow directly from a button or API is an independent trigger and does not evaluate its automatic conditions.

Saving a data trigger snapshots its query and checks permissions without reading customer data. Later query edits do not silently change an enabled trigger. Edit and save the trigger to adopt the current saved query. Query and source access are checked again at execution time, including every source in a connected data flow. Removing the query or revoking access stops the check before effects.

Select an interval, daily, weekly or monthly cadence for running the action or checking its condition. Calendar schedules use an IANA time zone and follow daylight saving. Interval schedules accept 1–43,200 minutes. Dashboard delivery uses the existing schedule editor with dashboard panels, filters and channels.

Saving an enabled schedule authorizes future runs; it does not run immediately. The three-dot menu provides Edit, Run now, Run history, Pause and Delete. Editing a paused schedule can enable it again. Workflow schedules pin an immutable published revision. Republishing the workflow does not silently change an existing automation; Use latest publication explicitly selects the newer version and shows its input contract before saving.

The sidebar project filters the collection. Ownership and access come from the saved target's project and item grants. Opening a schedule does not change the selected project. Editing requires Write on its workflow or dashboard, plus the normal execution permissions for its dependencies. Individual sharing continues to work without a project grant. Schedules introduce no second permission system.

Automatic execution uses the user and originating credential that last saved the definition. Only membership/credential IDs are persisted; every run resolves their current grants. Manual Run now uses its requester. Revoking membership, project/item access or a token prevents later effects. A removed and re-added membership does not revive old automation authority. API keys, CLI, native/HTTP SDK and MCP all use the same operations; configuring channels and workspace settings remains an account-admin action.

Execution and delivery

One scheduler and durable queue handle both workflow runs and dashboard deliveries. The existing report_schedule / report_run tables gain an exclusive workflow-or-dashboard target and origin references; existing report IDs, settings and history remain intact. Dashboard-specific reports.* operations delegate to the same records and delivery services used by schedules.*. Data-condition transition state is persisted with the same durable claim and completed run. No separate condition scheduler or action executor is used.

Database-only PostgreSQL workflows retain one transaction. A workflow containing HTTP or notification steps commits database mutations in separate transactions, without holding a database lock across network calls. Earlier external effects cannot be rolled back. A failed or interrupted run with a possible committed effect is marked Check outcome, and its schedule pauses rather than repeating effects automatically. The same action request key cannot execute twice. Review history and the destination before starting a new request.

Normal failures record the failed run; later scheduled occurrences can check again. Missed intervals collapse into one catch-up run. A scheduled workflow has a five-minute execution deadline and a ten-minute durable lease. Queued Run now requests survive restarts. Interrupted workflow leases pause the schedule. History stores timing, status and the workflow activity ID, not returned database rows.

Settings → Notifications → Scheduler & channel delivery controls both schedule types. Pausing automatic checks leaves Run now available. BytesMap's API/service must remain running; the browser can close. Desktop uses its in-process scheduler. A separate worker uses the existing bun run --cwd apps/api reports:worker entry point with shared PostgreSQL metadata. See dashboard delivery and worker setup for configuration.

Shared API

MethodPathOperation
GET/api/schedulesList authorized schedules and available targets; optional projectId.
POST/api/schedulesCreate a workflow or dashboard schedule.
GET / PATCH / DELETE/api/schedules/:idRead, edit/pause or delete.
POST/api/schedules/:id/runQueue an explicit run; returns 202.
GET/api/schedules/:id/runsRecent outcomes and workflow activity IDs.
await client.schedules.create({
  kind: 'workflow',
  actionId: workflow.id,
  enabled: true,
  definition: {
    name: 'Check open cases',
    revision: workflow.publishedRevision,
    inputs: { state: 'open' },
    // Optional: omit for an unconditional scheduled run.
    condition: {
      queryId: matchingCasesQuery.id,
      params: { state: 'open' },
      mode: 'enter', // 'exit' when a match clears; 'while' on every matching check
      // outputNodeId: 'threshold', // required for a saved visual flow
    },
    recurrence: {
      frequency: 'interval',
      intervalMinutes: 15,
      time: '09:00',
      timezone: 'UTC',
      weekday: 1,
      monthDay: 1,
    },
  },
})

Data conditions are periodic checks, not database change capture or an event-stream subscription. HTTP initiation uses the authenticated API rather than a separate public webhook receiver. Loops, per-record fan-out, cross-database transactions and compensating external actions are later extensions. Existing single-record PostgreSQL mutation limits remain in effect.

Integration tests in packages/platform/test/workflow-automation.test.ts exercise real isolated PostgreSQL queries/mutations and a local HTTP server, with captured notification delivery. Browser tests in apps/dashboard/e2e/automation-schedules.e2e.ts cover authoring, encrypted settings, schedule management and execution history. They never use customer sources or real recipients.

On this page