Process-Flow Platform Blocks
Three host-executed workflow blocks for creating process-flow tasks, spawning instances, and writing governed table rows — the building blocks of automated ingest pipelines.
The process-flow platform blocks are first-party workflow blocks that run with host-level database and network access — they cannot run inside a sandboxed vendor integration. Use them when a workflow needs to interact directly with the process-flow or managed-table subsystem.
These blocks are visible in the workflow editor's block gallery under the Core category: Create Process Task, Table Write, and Create Process Instance. They are available in every workflow, regardless of which integrations the organization has enabled.
create_process_task — Create Process Task
Creates a new task inside an existing process-flow instance. Use this when a workflow is triggered by an external event (calendar, webhook, schedule) and needs to add a task to a flow that is already running.
Block type: create_process_task
Sub-blocks:
| Sub-block | Required | Meaning |
|---|---|---|
processInstance | Yes | The process-flow instance to add the task to. Populated from a combobox listing live instances in the current workspace environment. Can also be set via a template reference (e.g. {{trigger.instanceId}}). |
taskName | Yes | Display name for the new task. Supports template variables from the workflow trigger (e.g. {{trigger.event.title}}). |
attributes | No | A JSON object of extra attributes to store on the task (e.g. { "scheduledDate": "{{trigger.event.start}}" }). Must be valid JSON. |
Output: { taskId, instanceId, stageName } when successful; { error } when not.
Example (calendar trigger → add a board-pack review task):
import { defineWorkflow, defineBlock, defineEdge } from '@scrydon/sdk-authoring/workflows'
export const calendarToTask = defineWorkflow({
slug: 'calendar-to-board-review-task',
name: 'Calendar → Board Review Task',
version: '1.0.0',
definition: {
blocks: {
'block-start': {
id: 'block-start',
type: 'starter',
name: 'Start',
position: { x: 0, y: 0 },
subBlocks: {},
outputs: {},
enabled: true,
},
'block-create-task': {
id: 'block-create-task',
type: 'create_process_task',
name: 'Create board review task',
position: { x: 240, y: 0 },
subBlocks: {
processInstance: {
id: 'processInstance',
type: 'combobox',
value: '{{trigger.instanceId}}',
},
taskName: {
id: 'taskName',
type: 'short-input',
value: 'Board pack review — {{trigger.event.title}}',
},
attributes: {
id: 'attributes',
type: 'code',
value: '{ "scheduledDate": "{{trigger.event.start}}" }',
},
},
outputs: { taskId: 'string', instanceId: 'string', stageName: 'string' },
enabled: true,
},
},
edges: [
{ id: 'e1', source: 'block-start', target: 'block-create-task' },
],
loops: {},
parallels: {},
},
})table_write — Table Write
Writes one or more rows to a governed managed table bound to an ontology object type. The block resolves the object type to its silver table at run time, then dispatches the write through the api-table path. No user interaction is required — designed for automated ingest pipelines.
Block type: table_write
Sub-blocks:
| Sub-block | Required | Meaning |
|---|---|---|
objectType | Yes | Ontology object-type slug identifying the target managed table. The block resolves the silver binding at run time. |
mode | Yes | "upsert" (match on identity column, update or insert) or "append" (always insert a new row). |
rows | Yes | A JSON array of { [columnSlug]: value } objects, 1–500 rows per call. A code sub-block can produce this as a JSON string. |
Output: { written: <row count>, tableId: "<uuid>" }.
Sentinel errors (returned as { success: false, error: "<sentinel>" }):
| Sentinel | Meaning |
|---|---|
table_write_target_unresolved | objectType is not bound to a silver table in this workspace. Verify the ontology type exists and is bound to a managed table. |
table_write_org_mismatch | The resolved table belongs to a different organization than the running workflow. This should not happen in normal usage; contact support. |
table_write_user_required | The workflow execution context does not carry a user identity. Workflows triggered by service accounts or webhooks satisfy this automatically. |
Example (webhook ingest — writing a track observation):
'block-write-observation': {
id: 'block-write-observation',
type: 'table_write',
name: 'Write track observation',
position: { x: 480, y: 0 },
subBlocks: {
objectType: {
id: 'objectType',
type: 'short-input',
value: 'track_observation', // ontology object-type slug
},
mode: {
id: 'mode',
type: 'dropdown',
value: 'upsert',
},
rows: {
id: 'rows',
type: 'code',
// JSON array produced by a preceding function block:
value: '{{block-parse-payload.response}}',
},
},
outputs: { written: 'number', tableId: 'string' },
enabled: true,
},The object type must be bound to a managed table in the workspace environment where the workflow runs. If the object type ships in the same Pack, the Pack must be installed before the workflow runs. The write is attributed to the workflow execution's user identity — workflows run by a service account satisfy the identity requirement automatically.
create_process_instance — Create Process Instance
Creates a new process-flow instance from a pack-declared template, optionally
seeding it with a context object and a dedupeKey. When a dedupeKey is
set, the block is idempotent: a second call with the same key returns the
existing live instance instead of creating a duplicate.
Block type: create_process_instance
Sub-blocks:
| Sub-block | Required | Meaning |
|---|---|---|
packId | Yes | The package.id of the Pack that ships the target process-flow template. |
processFlowSlug | Yes | The slug of the process-flow template within that Pack. |
name | Yes (1–200 chars) | Human-readable name for the created instance. Supports template references. |
context | No | A JSON object seeded into the instance as processFlow.context (accessible to map actions via focusAttribute, to agent steps, etc.). A code sub-block can produce a JSON string. |
dedupeKey | No (1–500 chars) | When set, enforces at most one live instance per key in this workspace environment. Concurrent calls with the same key converge to a single instance. |
detection | No | A TrackDetectedEvent-shaped JSON object. Accepted and validated; on a valid parse the platform publishes a thin signal to the org-events realtime topic (this is what powers live operational pictures such as Horizon) — leave it unset if you do not need live-event integration. The pre-rename key copDetection is still accepted as a legacy alias; new workflows should use detection. |
Deduplication contract. The dedupe key is enforced at the database level
— a partial unique index on (workspaceEnvironmentId, dedupeKey) covering
only non-terminal instances. Concurrent webhook deliveries for the same key
always converge to one instance; no application-level race is possible. A
terminal instance (completed or cancelled) releases the key, allowing a
fresh instance to be created.
Output: { instanceId: "<uuid>", deduped: <boolean> }. deduped: true
when the call returned an existing live instance rather than creating a new one.
Sentinel errors:
| Sentinel | Meaning |
|---|---|
create_process_instance_no_environment | The workflow execution context does not carry a workspace environment id, or workspace resolution failed. |
create_process_instance_invalid_context | context is not a valid JSON object. |
create_process_instance_user_required | The workflow execution context does not carry a user identity. |
Example (webhook ingest — open a response instance per detected track):
'block-create-instance': {
id: 'block-create-instance',
type: 'create_process_instance',
name: 'Open response instance',
position: { x: 720, y: 0 },
subBlocks: {
packId: {
id: 'packId',
type: 'short-input',
value: 'scrydon-drone-response',
},
processFlowSlug: {
id: 'processFlowSlug',
type: 'short-input',
value: 'drone-response',
},
name: {
id: 'name',
type: 'short-input',
value: 'Track {{trigger.body.trackId}}',
},
context: {
id: 'context',
type: 'code',
value: '{ "trackRef": "{{trigger.body.trackId}}" }',
},
dedupeKey: {
id: 'dedupeKey',
type: 'short-input',
value: '{{trigger.body.trackId}}', // one live instance per track
},
},
outputs: { instanceId: 'string', deduped: 'boolean' },
enabled: true,
},packId and processFlowSlug must match a template that is already installed
in the organization. The block instantiates an existing template — it does not
install the Pack. Install the Pack first (Settings → Packs), then deploy the
ingest workflow.
Building an ingest pipeline
The three blocks compose naturally into a webhook-driven ingest pipeline:
[Webhook trigger]
↓
[Function block — parse payload, build rows]
↓
[table_write — write observation rows]
↓
[create_process_instance — open response flow, deduped by trackId]A full worked example ships as part of the drone-response C2 pack (see the Pack examples directory). The Pack includes the ontology (Track / TrackObservation object types), the ingest workflow, and the response process flow — install them in one upload and the webhook URL is live immediately.