Node Executor
Node Executor protocol schemas
@module automation/node-executor
Node Executor Plugin Protocol — Wait Node Pause/Resume
Defines the specification for node executor plugins, with a focus on
the wait node executor that supports flow pause and external-event
resume (signal, manual, webhook, condition).
The protocol covers:
- WaitResumePayload: The payload delivered when a paused flow is resumed
- WaitExecutorConfig: Configuration for the wait executor plugin
- NodeExecutorDescriptor: Generic node executor plugin descriptor
Source: packages/spec/src/automation/node-executor.zod.ts
TypeScript Usage
import { ActionCategorySchema, ActionDescriptorSchema, ActionParadigmSchema, NodeExecutorDescriptorSchema, WaitEventTypeSchema, WaitExecutorConfigSchema, WaitResumePayloadSchema, WaitTimeoutBehaviorSchema } from '@objectstack/spec/automation';
import type { ActionCategory, ActionDescriptor, ActionParadigm, NodeExecutorDescriptor, WaitEventType, WaitExecutorConfig, WaitResumePayload, WaitTimeoutBehavior } from '@objectstack/spec/automation';
// Validate data
const result = ActionCategorySchema.parse(data);ActionCategory
Action palette category
Allowed Values
logicdataiohumancontrolcustom
ActionDescriptor
Canonical cross-paradigm action/node descriptor (ADR-0018)
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| type | string | ✅ | Registry action/node type (matches the executor type) |
| version | string | ✅ | Executor version (semver) |
| name | string | ✅ | Display label (or i18n key) |
| description | string | optional | Action description |
| icon | string | optional | Icon id resolved by the designer |
| category | Enum<'logic' | 'data' | 'io' | 'human' | 'control' | 'custom'> | ✅ | Palette category |
| paradigms | Enum<'flow' | 'approval'>[] | ✅ | Authoring surfaces that may offer this action |
| configSchema | any | optional | JSON Schema for the node config (drives the designer form; undeclared keys are rejected at registration) |
| supportsPause | boolean | ✅ | Supports async pause/resume |
| supportsCancellation | boolean | ✅ | Supports cancellation |
| supportsRetry | boolean | ✅ | Supports retry on failure |
| needsOutbox | boolean | ✅ | Dispatch via service-messaging outbox (retry/idempotency/dead-letter) |
| isAsync | never | optional | [REMOVED] ActionDescriptor.isAsync was removed in @objectstack/spec 17 (#6748, ADR-0049) — no execution path ever read it, so declaring it never made a node suspend and omitting it never stopped one. Delete the key. The live mechanism is two-part: an executor suspends by RETURNING suspend: true from execute(), and its descriptor must declare supportsPause: true (plus the resumeAuthority its pauses need) or the engine refuses that suspension (#6667). Declaring isAsync: true alongside supportsPause: true was always redundant; declaring it alone was always inert. |
| handlerContract | Enum<'none' | 'pure'> | ✅ | Effect contract for author-supplied code this action invokes: 'none' (invokes none) or 'pure' (must not write — it returns a value and the flow graph persists it) |
| resumeAuthority | Enum<'any' | 'service'> | optional | Who may resume a run this node suspended: 'any' (the generic resume route) or 'service' (only the owning service, e.g. approvals). Carries no schema default so an omission stays observable — and an omission is fail-CLOSED at run time, equivalent to 'service': a pausing node whose pause is open to the generic route must declare 'any' explicitly (#5561) |
| maturity | Enum<'ga' | 'beta' | 'reserved'> | ✅ | Runtime maturity: ga (shipped), beta, or reserved (contract only — designers grey this out) |
| source | Enum<'builtin' | 'plugin'> | ✅ | builtin = platform baseline; plugin = third-party contributed |
| deprecated | boolean | ✅ | Deprecated alias kept for back-compat |
| aliasOf | string | optional | Canonical type this alias forwards to |
ActionParadigm
Authoring paradigm that may offer this action
Allowed Values
flowapproval
NodeExecutorDescriptor
Node executor plugin descriptor
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| id | string | ✅ | Unique executor plugin identifier |
| name | string | ✅ | Display name |
| nodeTypes | string[] | ✅ | FlowNodeAction types this executor handles |
| version | string | ✅ | Plugin version (semver) |
| description | string | optional | Executor description |
| supportsPause | boolean | ✅ | Whether the executor supports async pause/resume |
| supportsCancellation | boolean | ✅ | Whether the executor supports mid-execution cancellation |
| supportsRetry | boolean | ✅ | Whether the executor supports retry on failure |
| configSchemaRef | string | optional | JSON Schema $ref for executor-specific config |
WaitEventType
Wait event type determining how a paused flow is resumed
Allowed Values
timersignalwebhookmanualcondition
WaitExecutorConfig
Wait node executor plugin configuration
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| defaultTimeoutMs | integer | ✅ | Default timeout in ms (default: 24 hours) |
| defaultTimeoutBehavior | Enum<'fail' | 'continue' | 'fallback'> | ✅ | Default behavior when wait timeout is exceeded |
| conditionPollIntervalMs | integer | ✅ | Polling interval for condition waits in ms (default: 30s) |
| conditionMaxPolls | integer | ✅ | Max polling attempts for condition waits (0 = unlimited) |
| webhookUrlPattern | string | ✅ | URL pattern for webhook resume endpoints |
| persistCheckpoints | boolean | ✅ | Persist wait checkpoints to durable storage |
| maxPausedExecutions | integer | ✅ | Max concurrent paused executions (0 = unlimited) |
WaitResumePayload
Payload for resuming a paused wait node
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| executionId | string | ✅ | Execution ID of the paused flow |
| checkpointId | string | ✅ | Checkpoint ID to resume from |
| nodeId | string | ✅ | Wait node ID being resumed |
| eventType | Enum<'timer' | 'signal' | 'webhook' | 'manual' | 'condition'> | ✅ | Event type that triggered resume |
| signalName | string | optional | Signal name (when eventType is signal) |
| webhookPayload | Record<string, any> | optional | Webhook request payload (when eventType is webhook) |
| resumedBy | string | optional | User ID or system identifier that triggered resume |
| resumedAt | string | ✅ | ISO 8601 timestamp of the resume event |
| variables | Record<string, any> | optional | Variables to merge into flow context upon resume |
WaitTimeoutBehavior
Behavior when a wait node exceeds its timeout
Allowed Values
failcontinuefallback