Flows Tools
Tools for creating, updating, and executing automation flows.
Available Tools
flow_createCreate a new flow. Params: name (required), description. Returns empty flow ready for nodes.
Input Schema
name | stringrequired | Name for the new automation flow |
description | string | Optional description of the flow |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_create",
"arguments": {
"name": "example",
"description": "example"
}
}
}flow_listList all automation flows. Returns array with id, name, description, isActive, triggerType, nodes[], edges[].
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_list",
"arguments": {}
}
}flow_getAvailableNodesGet available node types for building flows. Params: type ("all"|"triggers"|"utilities"|"tools"|"connectors"|"agents"|"ai"), category, mcpServerId, connectorId, toolNames, search, limit (default 50), offset. Returns: triggers, utilities (with defaultConfig), ai config, tools (built-in apps, with inputSchema for each tool), connectors (the built-in Serenities tools first, then the user's own MCP connectors from Automations → Connectors, each with connectorId, slug and tools. Without toolNames / connectorId / category / search this is a COMPACT index — every tool's name, toolName, toolKind, group and one-line description, no inputSchema; pass toolNames: ["tables_createRow", …] to load exactly those tools with inputSchema, or narrow with connectorId / category / search for full detail, limit/offset paginated. Add one as a tool node with data.kind "connector" and data.connectorId, no connectionId; see nodeStructure.connectorStep), agents (the user's AI agents — add one as a tool node with data.kind "agent" and data.agentId, config {task, waitMode, timeoutMinutes}; see nodeStructure.agentStep), nodeStructure templates, utilityCategories.
Input Schema
type | string | Filter by node type. "connectors" = the user's own MCP connectors (Automations → Connectors) and their tools, added as connector steps |
category | string | Filter utilities/tools by category. For connectors: a tool group — a platform tool's router such as "tables" or "flow", or a user connector's slug — and switches the connectors answer to full detail |
mcpServerId | string | Filter tools by specific MCP server |
connectorId | string | Connectors: only this connector (a connectorId from a previous call, or "platform:serenities" for the built-in Serenities tools); switches the connectors answer to full detail |
toolNames | array | Connectors: load exactly these tools WITH their inputSchema, by name or toolName (e.g. ["tables_createRow", "gmail_send_message"]). The cheap follow-up to the compact index |
search | string | Search by name or description. For connectors this switches to full detail (inputSchema) for the matches |
limit | integer | Max items for tools, and for full-detail connector tools (default 50) |
offset | integer | Offset for tools / full-detail connector tools pagination |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_getAvailableNodes",
"arguments": {
"type": "example",
"category": "example",
"mcpServerId": "example"
}
}
}flow_getByIdGet flow details with nodes and edges. Param "id" is flow ID from list.
Input Schema
id | stringrequired | Flow ID from list |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_getById",
"arguments": {
"id": "example"
}
}
}flow_updateUpdate flow. Params: id (flow ID), name, description, isActive, triggerType, nodes, edges. Nodes: [{id, type: "trigger"|"tool"|"utility"|"ai", position: {x, y}, data: {label, sequenceNumber, ...}}]: a step's settings go in data.config; a trigger node has data.triggerType ("manual"|"webhook"|"schedule"|"table"|"event") and its own settings directly on data. A table trigger's settings sit directly on the node's data, never in data.config: data.triggerType "table", data.tableId (the table's id, from tables_listTables) and data.tableEventType, one of: row_created, row_updated, row_deleted, field_changed, status_changed, form_submitted, date_arrives, date_approaching, date_passed. Optional, also on data: viewId, fieldIds (field_changed, status_changed and the date_* events: the column), statusValues (status_changed) and daysBeforeApproaching (date_approaching). A connector step is a "tool" node with data.kind "connector" and data.connectorId (from getAvailableNodes type "connectors"); the connector must belong to the user or the save is refused. Trigger nodes have data.triggerType. Edges: [{id, source, target, sourceHandle: "output", targetHandle: "input"}]. After adding trigger nodes, use createWebhook/createSchedule to set up the backend.
Input Schema
id | stringrequired | Flow ID from list |
name | string | New name for the flow |
description | string | New description |
nodes | array | Array of flow nodes (at most 1000) |
edges | array | Array of flow edges connecting nodes (at most 5000) |
triggerType | string | Trigger type: "manual", "webhook", "schedule", "table" |
isActive | boolean | Whether the flow is active |
usedSequenceNumbers | array | Used sequence numbers for node ordering |
stopAfterMinutes | number | "Stop a run after" in whole minutes, from 1 up to the plan's longest run (getById shows runTime.maxMinutes); null goes back to the plan default |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_update",
"arguments": {
"id": "example",
"name": "example",
"description": "example"
}
}
}flow_updateNodeConfigUpdate a single node configuration in place (no need to resend the whole flow). Params: flowId, nodeId, config (object with node settings). REPLACES the node's existing config: read it with getById first and send the full merged object. The config shape of each node type comes from getAvailableNodes and getHelp; values support {{template}} references, e.g. {{#2.email}}. On a table trigger the settings (tableId, tableEventType, viewId, fieldIds, statusValues, daysBeforeApproaching) are written on the node's data, where the trigger reads them; any other key is refused. An Event Trigger is set with accountEvents_setFlowEventTrigger instead (refused here).
Input Schema
flowId | stringrequired | Flow ID |
nodeId | stringrequired | Node ID within the flow (from getById — node ids live in the nodes array) |
config | objectrequired | The node's config object — REPLACES the node's existing config, so read the current config via getById first and send the full merged object. The shape depends on the node type: call getAvailableNodes (and getHelp for worked examples) to see each type's config fields. Values support {{template}} references to prior node outputs, e.g. {{#2.email}}. On a table trigger the settings (tableId, tableEventType, …) are written on the node's data, where the trigger reads them; an Event Trigger is set with accountEvents_setFlowEventTrigger instead. |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_updateNodeConfig",
"arguments": {
"flowId": "example",
"nodeId": "example",
"config": {}
}
}
}flow_editNodeConfigEdit node config by merging partial updates. Only provided fields are updated, existing fields preserved. Use this for adding mappings. Params: flowId, nodeId, config (partial object). On a table trigger the settings (tableId, tableEventType, viewId, fieldIds, statusValues, daysBeforeApproaching) are written on the node's data, where the trigger reads them; any other key is refused. An Event Trigger is set with accountEvents_setFlowEventTrigger instead (refused here).
Input Schema
flowId | stringrequired | Flow ID |
nodeId | stringrequired | Node ID within the flow |
config | objectrequired | Partial config to merge. Only provided fields are updated, existing fields are preserved. On a table trigger the settings (tableId, tableEventType, …) are written on the node's data, where the trigger reads them; an Event Trigger is set with accountEvents_setFlowEventTrigger instead. |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_editNodeConfig",
"arguments": {
"flowId": "example",
"nodeId": "example",
"config": {}
}
}
}flow_deleteDelete a flow. Param "id" is flow ID. WARNING: Permanent. Act only on what the person named or picked.
Input Schema
id | stringrequired | Flow ID to delete |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_delete",
"arguments": {
"id": "example"
}
}
}flow_createWebhookCreate webhook trigger for a flow. Params: flowId, triggerId (trigger node ID). Returns webhook with token and URL.
Input Schema
flowId | stringrequired | Flow ID |
triggerId | stringrequired | Trigger node ID in the flow |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_createWebhook",
"arguments": {
"flowId": "example",
"triggerId": "example"
}
}
}flow_getWebhookGet webhook details. Params: flowId, triggerId (trigger node ID). Returns the live webhook link: treat it as a password (so this is a write tool that needs an edit role: a read-only connection or a Viewer is refused it).
Input Schema
flowId | stringrequired | Flow ID the trigger belongs to |
triggerId | stringrequired | Trigger node ID |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_getWebhook",
"arguments": {
"flowId": "example",
"triggerId": "example"
}
}
}flow_deleteWebhookDelete a flow's webhook trigger. Params: flowId, triggerId (trigger node ID). Act only on what the person named or picked.
Input Schema
flowId | stringrequired | Flow ID the trigger belongs to |
triggerId | stringrequired | Trigger node ID |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_deleteWebhook",
"arguments": {
"flowId": "example",
"triggerId": "example"
}
}
}flow_createScheduleCreate a flow's schedule trigger. Params: flowId, triggerId (trigger node ID), cronExpression (5 parts: minute hour day month weekday), timezone (default UTC). Example: "0 9 * * *" for 9am daily.
Input Schema
flowId | stringrequired | Flow ID |
triggerId | stringrequired | Trigger node ID |
cronExpression | stringrequired | Cron expression (5 parts): minute hour day month weekday. Example: "0 9 * * *" for 9am daily |
timezone | string | Timezone (default: UTC). Example: "America/New_York" |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_createSchedule",
"arguments": {
"flowId": "example",
"triggerId": "example",
"cronExpression": "example"
}
}
}flow_getScheduleGet a flow's schedule trigger. Param "triggerId" (trigger node ID).
Input Schema
triggerId | stringrequired | Trigger node ID |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_getSchedule",
"arguments": {
"triggerId": "example"
}
}
}flow_updateScheduleUpdate a flow's schedule trigger. Params: triggerId, cronExpression, timezone.
Input Schema
triggerId | stringrequired | Trigger node ID |
cronExpression | stringrequired | Cron expression (5 parts): minute hour day month weekday |
timezone | stringrequired | Timezone. Example: "America/New_York", "UTC" |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_updateSchedule",
"arguments": {
"triggerId": "example",
"cronExpression": "example",
"timezone": "example"
}
}
}flow_deleteScheduleDelete a flow's schedule trigger. Param "triggerId" (trigger node ID). Act only on what the person named or picked.
Input Schema
triggerId | stringrequired | Trigger node ID |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_deleteSchedule",
"arguments": {
"triggerId": "example"
}
}
}flow_getExecutionsGet execution history for a flow with pagination. Params: flowId (required), limit (1-50, default 10), cursor (from previous response).
Input Schema
flowId | stringrequired | Flow ID |
limit | number | Max results (1-50, default 10) |
cursor | string | Pagination cursor from previous response |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_getExecutions",
"arguments": {
"flowId": "example",
"limit": 0,
"cursor": "example"
}
}
}flow_getExecutionDetailsGet detailed execution info including node results. Params: executionId, includeFullData (boolean, for copying data).
Input Schema
executionId | stringrequired | Execution ID from getExecutions |
includeFullData | boolean | Include full node results (for copying data) |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_getExecutionDetails",
"arguments": {
"executionId": "example",
"includeFullData": true
}
}
}flow_getActiveExecutionGet the most recent running execution for a flow. Param "flowId".
Input Schema
flowId | stringrequired | Flow ID |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_getActiveExecution",
"arguments": {
"flowId": "example"
}
}
}flow_getActiveExecutionsGet all currently running executions for a flow. Param "flowId".
Input Schema
flowId | stringrequired | Flow ID |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_getActiveExecutions",
"arguments": {
"flowId": "example"
}
}
}flow_getSnapshotsGet flow version history (snapshots). Each save creates a snapshot for rollback. Params: flowId, cursor (optional), limit (1-50, default 20).
Input Schema
flowId | stringrequired | Flow ID |
cursor | string | Pagination cursor |
limit | number | Max results (1-50, default 20) |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_getSnapshots",
"arguments": {
"flowId": "example",
"cursor": "example",
"limit": 0
}
}
}flow_deleteSnapshotDelete a snapshot. Cannot delete the latest snapshot. Param "snapshotId". Act only on what the person named or picked.
Input Schema
snapshotId | stringrequired | Snapshot ID from getSnapshots |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_deleteSnapshot",
"arguments": {
"snapshotId": "example"
}
}
}flow_restoreFromSnapshotByIdRestore flow nodes and edges from a previous snapshot. Params: flowId, snapshotId.
Input Schema
flowId | stringrequired | Flow ID |
snapshotId | stringrequired | Snapshot ID to restore from |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_restoreFromSnapshotById",
"arguments": {
"flowId": "example",
"snapshotId": "example"
}
}
}flow_stopExecutionStop a running execution. Param "executionId". Act only on what the person named or picked.
Input Schema
executionId | stringrequired | Execution ID to stop |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_stopExecution",
"arguments": {
"executionId": "example"
}
}
}flow_runManualFlowExecute a flow manually. Params: flowId (required), triggerData (optional object), triggerId (optional, uses manual trigger if not specified), executionMode ("test" (pinned data: steps that have pinned output use it) or "live" (live data: every step runs for real); only for this run. Triggered runs always do every step for real.). WHO RUNS IT: a flow runs as the workspace — whoever builds it decides what it can do and can only wire what they may use; anyone in the workspace can run it unless its "Who can run this flow" names who may (the Owner and Admins always can; its own triggers always start it). The person who started it is passed in as data: {{run.startedBy.name}}, {{run.startedBy.role}}, {{run.startedBy.kind}} — for personalising and logging, never rights.
Input Schema
flowId | stringrequired | Flow ID to execute |
triggerData | object | Data to pass to the trigger node |
triggerId | string | Specific trigger node ID (uses manual trigger if not specified) |
executionId | string | Custom execution ID for a NEW run (generated if not provided); an id already in use is refused |
executionMode | string | Execution mode: "test" uses pinned data, "live" runs normally |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_runManualFlow",
"arguments": {
"flowId": "example",
"triggerData": {},
"triggerId": "example"
}
}
}flow_pinNodeDataPin data to a node for testing: when the flow is in Pin mode, that step uses the pinned output instead of running. Pinned data is used only when you press Run here; every triggered run does every step for real. Params: flowId, nodeId, input (optional), output (required - the pinned data).
Input Schema
flowId | stringrequired | Flow ID |
nodeId | stringrequired | Node ID to pin data to |
input | any | Input data to pin |
output | any | Output data to pin - used as fixed output in test mode |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_pinNodeData",
"arguments": {
"flowId": "example",
"nodeId": "example",
"input": {}
}
}
}flow_unpinNodeDataRemove pinned data from a node so it executes normally. Params: flowId, nodeId.
Input Schema
flowId | stringrequired | Flow ID |
nodeId | stringrequired | Node ID to unpin |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_unpinNodeData",
"arguments": {
"flowId": "example",
"nodeId": "example"
}
}
}flow_toggleActiveToggle flow active/inactive. Param "flowId"; optional "expectActive" (whether it is on now, as you last saw it — if it changed since, nothing is changed). Inactive flows do not process webhook or schedule triggers.
Input Schema
flowId | stringrequired | Flow ID |
expectActive | boolean | Whether the flow is on now (as you last saw it). If it is no longer in that state, nothing is changed. |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_toggleActive",
"arguments": {
"flowId": "example",
"expectActive": true
}
}
}flow_enterListenModeShow the next real runs of a flow live in the editor; the flow still runs as usual. Params: flowId, triggerType ("webhook" or "table"), duration (ms, 1 second to 15 minutes, default 5 minutes).
Input Schema
flowId | stringrequired | Flow ID |
triggerType | stringrequired | Type of trigger to listen for |
duration | integer | Listen duration in ms (1 second to 15 minutes; default 5 minutes) |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_enterListenMode",
"arguments": {
"flowId": "example",
"triggerType": "example",
"duration": {}
}
}
}flow_exitListenModeStop watching a flow's runs in the editor — for everyone in the workspace on that flow. Param "flowId".
Input Schema
flowId | stringrequired | Flow ID |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_exitListenMode",
"arguments": {
"flowId": "example"
}
}
}flow_cancelQueuedFlowCancel a flow run that is still waiting for a free slot (it has not started yet): it is taken out of the waiting list and never starts. Param: executionId (the id the run was given when it was started). Anyone who may run the flow can cancel its waiting runs. A run that has already started, finished or been cancelled, or does not exist, answers that no waiting run was found; stop a running one with stopExecution. Returns { success: true, cancelled: true } when the run was taken out. Act only on what the person named or picked.
Input Schema
executionId | stringrequired | Execution ID of the queued flow |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_cancelQueuedFlow",
"arguments": {
"executionId": "example"
}
}
}flow_getHelpGet focused help for Flows API. Call when a parameter shape is unclear (one call per topic). Topics: - "overview": What flows are, quick start, node types - "nodes": Node structure, connecting nodes - "triggers": Manual, webhook, schedule triggers - "execution": Running flows, viewing history - "testing": Pinning data, test mode, listen mode Example: getHelp({topic: "triggers"}) before setting up webhooks.
Input Schema
topic | string | Topic: "overview", "nodes", "triggers", "execution", "testing" |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_getHelp",
"arguments": {
"topic": "example"
}
}
}flow_getAccessRulesGet the execute access rules for a flow (who may invoke it from a published app via flows.invoke), and hasHome (true when the flow already belongs to a site). Its home sites (`sites`) list only the sites you may open; saving the list keeps any you can't see. Param: id (flow ID).
Input Schema
id | stringrequired | Flow ID from list |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_getAccessRules",
"arguments": {
"id": "example"
}
}
}flow_setAccessRulesSet who may invoke a flow from published apps via flows.invoke(). Flows are DENY-BY-DEFAULT — without rules only the owner can invoke. A flow a page starts runs as the workspace (it can read any of the owner's bases): only what its response node returns reaches the visitor. Params: id (flow ID), accessRules ({ execute: Condition, sites?: [siteId] } — same shape as backend-function rules). sites = the flow's HOME sites: only their members count for signed-in / role / plan / property rules, and through any other site the flow runs only if its rule says "Anyone, everywhere". Public has two levels: { type: "public", scope: "home" } = "Anyone on this site" (only through its home sites) and { type: "public", scope: "everywhere" } = "Anyone, everywhere". A public rule with no level keeps the saved one; made public now on a flow with home sites it starts as "Anyone on this site"; a flow with NO sites made public must name its sites or say scope "everywhere" — refused otherwise. Saving is checked like any flow save: you may only save rules you may change (refused if the flow holds something the person you act for may not use). Leaving `sites` out keeps the saved list.
Input Schema
id | stringrequired | Flow ID from list |
accessRules | objectrequired | { execute: Condition, sites?: [siteId] } — same shape as backend-function rules (public/authenticated/has_role/user_property/policy refs, or {all|any|not} groups). `sites` = the flow's home sites: only their members count for signed-in/role/plan/property rules, and only they can run it unless it is "Anyone, everywhere" (left out = keep the saved list). A public leaf has two levels: { type: "public", scope: "home" } = "Anyone on this site" (through its home sites only — what a newly public flow with home sites starts as; a flow with no sites made public must name them or say "everywhere") and { type: "public", scope: "everywhere" } = "Anyone, everywhere" (through any of your sites). Saving is checked like any flow save: you may only save rules you may change. Missing/empty execute = nobody can invoke from the published app (the owner always can). Example public form flow on one site: { execute: [{ type: "public", scope: "home" }], sites: ["<siteId>"] }. |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_setAccessRules",
"arguments": {
"id": "example",
"accessRules": {}
}
}
}flow_getWhoCanRun"Who can run this flow" (teammates and agents, not site visitors): { everyone, roles, people, agents } — everyone: true when no list is set — and powers: what anyone who can run it can use it to do, in words. The Owner and Admins can always run it; its own triggers always start it. Param: flowId.
Input Schema
flowId | stringrequired | Flow ID from list |
withChangeRefusal | boolean | Also say whether you may change the list, and why not (the whole save check: ask it only when about to change it). |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_getWhoCanRun",
"arguments": {
"flowId": "example",
"withChangeRefusal": true
}
}
}flow_setWhoCanRunSet "Who can run this flow": everyone in the workspace (everyone: true), or the Owner, Admins and the roles (admin, editor = Developer, viewer), member user ids and agent ids you name. Running, stopping and raising an event that fires it follow the list; its own triggers always start it. Changing it is a save: refused if the flow holds something the person you act for may not use. Params: flowId, everyone, roles, people, agents.
Input Schema
flowId | stringrequired | Flow ID from list |
everyone | booleanrequired | true: everyone in the workspace can run it (the lists are ignored) |
roles | arrayrequired | Roles that can run it: admin, editor (Developer), viewer |
people | arrayrequired | Member user ids that can run it |
agents | arrayrequired | Agent ids that can run it |
Example Call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "flow_setWhoCanRun",
"arguments": {
"flowId": "example",
"everyone": true,
"roles": {}
}
}
}