Skip to content

Workflow File Format ​

This page documents the JSON shape of a workflow: every top-level field, what a node and a connection look like on the wire, and which fields are required. It assumes you already know what a workflow, node, and connection are; see Concepts first if not.

The file itself ​

A workflow is plain JSON, saved with a .aerini extension by convention. A .json file with the same shape works the same way, see Workflow file. This is the shape Aerini's own database stores, the shape exchanged between the desktop frontend and the engine, and the shape the scheduler loads for a background run.

Top-level fields ​

FieldTypeRequiredDefault / notes
schema_versionstringNoSee Schema version below.
idstringYesUnique ID for this workflow.
namestringYesDisplay name shown in the Workflows sidebar and window title.
descriptionstringNoDefaults to an empty string. Not currently editable from the desktop UI; present in the schema for hand-authored or generated files.
nodesarray of node objectsYesEvery box on the canvas, including trigger nodes.
edgesarray of connection objectsYesCalled a "connection" everywhere else in these docs; the JSON key is edges.
metadataobjectNoDefaults per field if omitted, see Metadata below.
max_duration_secsnumberNoWall-clock limit for the whole run, in seconds. The executor clamps any value to the 10 to 86400 range. Omit for no limit.
unlimited_durationbooleanNoDefaults to false. Only takes effect on a manual run started from the desktop app; scheduled and background runs never read this field. When true, the run ignores both the server's duration ceiling and this workflow's own max_duration_secs.
parallel_executionbooleanNoDefaults to false. When true, independent branches run concurrently instead of one after another.
max_concurrent_nodesnumberNoCaps simultaneous node tasks when parallel_execution is true. Falls back to 8 if unset.
settingsobjectNoCurrently holds only chat, see Chat settings below.

Metadata ​

The metadata object as a whole is optional: leave it out entirely and every field below falls back to its default. Include it, though, and author, created_at, and updated_at are required inside it; only tags and collection_id keep their own per-field defaults regardless.

FieldTypeDefault when metadata is absent
authorstring"user"
created_atstring, ISO-8601current time
updated_atstring, ISO-8601current time
versionstring"1.0.0". A free-form label, not the same field as the top-level schema_version.
tagsarray of strings[]
collection_idstring or nullnull

collection_id references a named collection in the Workflows sidebar by ID. The collection's own name and color live outside the workflow file; a missing or null collection_id leaves the workflow Uncategorized.

Chat settings ​

settings.chat mirrors the Chat Panel toggles set from the Workflow Settings modal. Each field defaults independently, so a file that sets only some of them still loads correctly. See Chat Panel for what each toggle actually does in the app.

FieldTypeDefault
allow_attachmentsbooleanfalse
allow_image_responsesbooleantrue
max_message_lengthnumber2000
session_persistencebooleantrue
show_brandingbooleantrue

Nodes ​

Aerini has no separate top-level list for triggers. Manual Trigger, Schedule, and Webhook are ordinary entries in nodes, identified by the node_type_id values manual_trigger, schedule, and webhook.

FieldTypeRequiredDefault / notes
idstringYesUnique within this workflow, e.g. "node_abc123".
node_type_idstringYesWhich node implementation to run, e.g. "http_request". See Nodes Reference for every valid value.
node_typestringYesOne of "action", "ai", "logic", "utility". Controls which palette section the node appears in; has no effect on execution.
namestringYesLabel shown on the canvas block.
configobjectNoDefaults to {}. Node-specific settings from the config panel; shape depends entirely on node_type_id, see Nodes Reference.
credentialsobjectNoDefaults to {}. Maps a config field name to a saved credential's ID, e.g. {"api_key": "openai-prod"}. The secret itself never appears in this file, see Credentials.
input_schemaobjectYesJSON Schema the node's input must match. The app always writes {} for a node with no schema of its own; the key still has to be present.
output_schemaobjectYesSame rule as input_schema, for the node's output.
retryobjectNoDefaults to one attempt, no automatic retry, see Retry below.
fallback_nodestring or nullNoReserved for future use. Not read by the executor in the current version.
disabledbooleanNoDefaults to false. When true, the executor skips the node and treats it as if it succeeded with empty output.
positionobjectNoDefaults to {"x": 0, "y": 0}. Canvas coordinates, {"x": number, "y": number}, ignored by the executor.

The desktop app also writes ports and dynamic_ports into every saved node object, canvas metadata it uses to draw connection points. Neither is read by the engine; a file that leaves them out loads fine.

Retry ​

FieldTypeDefault
max_attemptsnumber1
backoff_msnumber500

max_attempts: 1 means no automatic retry. A node with side effects, an email send or an HTTP POST, only retries on its own if a workflow author raises this above 1 from the Retry UI.

Connections ​

A connection is the line drawn from one node's output to another's input; the JSON key for the array holding them is edges, and each entry below is one connection.

FieldTypeRequiredDefault / notes
idstringYesUnique ID for this connection.
from_nodestringYesSource node's id.
from_portstringYesOutput port name on the source node, e.g. "output", or a branch name such as "on_true" for a node with more than one output.
to_nodestringYesTarget node's id.
to_portstringYesInput port name on the target node, e.g. "input".
conditionstring or nullNoExpression the canvas uses to decide whether to draw the line. Not evaluated by the executor: routing follows from_port alone.
on_successstring or nullNoAlternate target node ID activated when the source node succeeds, used to register an extra reachability edge.
on_failurestring or nullNoTarget node ID the executor routes to when the source node fails after every retry attempt, instead of aborting the run.

Schema version ​

Every workflow file carries a schema_version field so whatever loads it knows which shape to expect. As of Aerini 0.4.0 the format hasn't changed since it was introduced, so this is "1.0" everywhere and there is nothing to migrate yet. A file with no schema_version field at all, saved before the field existed, is treated as the oldest version this build knows and loads normally.

What happens for a version that's older, newer, or otherwise mismatched, and what runs when a migration path actually exists, is covered in Updating §Opening older or newer workflow files rather than repeated here. A version-by-version history of format changes will live in schema-migrations.md once there is more than one version to show.

aerini-server's exported config ​

Choosing Export → Export for Server writes a config file, aerini-server.json, whose workflow_json field holds this exact schema, unmodified, as a JSON string, the same shape the desktop app already has saved to its own database. aerini-server serve reads that file and loads the workflow the same way the desktop app does. See Server Deployment and Server CLI Reference for the rest of that config file and the flags around it.

What Export writes ​

Export → Export workflow and Export → Export All write this same schema, field for field, with one deliberate exception: metadata.collection_id is always written as null. Collection membership is this sidebar's local folder organization, not a portable property of the workflow itself, so it never leaves the app through an exported file.

Everything else, including parallel_execution, unlimited_duration, max_concurrent_nodes, settings, and the rest of metadata, is written exactly as it stands in the workflow being exported, omitted only where Top-level fields above already says the native format omits an at-default field. Re-importing an exported file restores all of it; the workflow lands in Uncategorized, since collection membership is the one thing an export never carries.

A .json file works the same as a .aerini file here too, see Workflow file.

What's next ​

  • Concepts, for what a workflow, node, and connection are before reading their JSON shape
  • Nodes Reference, for what belongs inside a given node type's config
  • Credentials, for how the credentials map resolves to a real secret at run time
  • schema-migrations.md, for a version-by-version history once the format has more than one version to show