Workflows

A workflow is a workspace-scoped DAG that fuses the brain with action. Author it in chat ("when a Threads draft is approved, post it, wait 24 hours, then ask the brand specialist to summarize engagement") or in the web builder (the Workflow tab in the app). The runtime knows about assistants, memory, and tools, so an assistant_call step inherits the workspace's brain at the moment it runs.

Step types

Workflows are built from four step types. Sequential by default; branch steps fan out; wait steps pause the run and resume on a scheduler tick.

assistant_call

Invoke an assistant with a prompt. The callee has the workspace's tools, memory, and knowledge available. Optional fields restrict its tools, push the output to a channel, or carry a persistent session across runs.

tool_call

Invoke a first-party or MCP connector tool directly. allow-policy tools run unattended; ask-policy tools pause the run on the unified approvals queue; block-policy errors at dispatch.

wait

Pause until an absolute timestamp or for a relative duration. The runtime stores a scheduled_jobs row and the poll worker resumes the run at the deadline.

branch

Evaluate a JSONLogic condition against the previous step's output and the run-scope vars bag. Routes to one of two nextStepIds.

Triggers

Four ways to fire a workflow. Every trigger feeds the same runtime. The differences are only at the front edge.

Manual

POST /api/workflows/:id/run from your service, or click "Run now" in the web builder.

Schedule

Cron expression in your workspace timezone. Runs on the scheduled-jobs poll worker.

Webhook

HMAC-signed POST /api/workflow-webhooks/:slug from any external service. Per-row slug + secret.

Event

A subscribed event source is a connector instance (GitHub, Fathom, Gmail, Calendar) or a channel integration (Slack, Telegram). It fires the workflow whenever its match filter passes.

Cost

A workflow run is billed as the sum of its assistant_call steps at whatever tier each step uses. tool_call, wait, and branch steps cost zero credits. Before you run a workflow, the builder shows the exact message count ("Running 'Competitor Analysis': 3 Pro messages per run"); branches are shown as a range.

Approvals

Workflows pause on the same unified approvals queue every other surface uses (chat, app-kind staged writes, distribution drafts). One pending_approvals table, one resolve endpoint, four canonical kinds. Resolution is cross-channel: start a run from web, approve from Telegram.

tool_invocation

An ask-policy tool reached during a chat turn pauses the loop until the user approves. Per-tool default expiry (5 min on TG / Slack / web); fires immediately on rejection.

workflow_step

An ask-policy tool reached inside a workflow run inserts a pending row and the run pauses. Resolution resumes via the same resume protocol the chat path uses.

staged_write

Operational-primitive writes proposed by a kind='app' assistant (CRM / Tasks / KB / Files / Entities) queue for founder review with the proposed diff embedded in the payload.

distribution_draft

An app-kind reply draft awaiting publish on Threads or X. Lives in the feed UI; same row shape, same resolve endpoint.

Auto-approve via permission grants

A workflow definition can carry permission_grants: { action_kind, grant: 'allow' | 'ask' | 'block' } entries that auto-approve listed actions inside an active run while leaving the assistant's per-tool defaults untouched everywhere else. Two ways to author them: tick "always allow within this workflow" on the first run's approval prompts (the ticks land back on the workflow definition), or edit the grants table directly. Audit trail names the workflow_run_id and the grant entry that authorized each auto-approved action; revoking a grant takes effect on subsequent runs, not in-flight ones.

REST surface

The web builder is one client of the REST API. Other clients (a custom dashboard, a deployment-driven workflow generator) can use the same surface. Auth is the standard workspace-member check.

GET /api/workflows?workspaceId=  ·  GET /api/workflows/:id  ·  POST /api/workflows  ·  PATCH /api/workflows/:id  ·  DELETE /api/workflows/:id  ·  POST /api/workflows/:id/run  ·  GET /api/workflows/:id/runs  ·  POST /api/workflow-webhooks/:slug