Skip to main content

Blueprints & Plugins

Blueprints are pre-built, configurable workflow actions that can be added to any workflow from the Plugin Catalog. Each blueprint provides a guided wizard to collect configuration values, then generates the underlying V8 script automatically. Blueprints are stored as inline nodes directly on the workflow JSON — they do not require a separate Workflow Entity in the database.

Plugin Catalog

The Plugin Catalog is accessible from the workflow canvas:

  • Sidebar panel — click the plugin icon in the left sidebar to browse all available plugins
  • Right-click context menu — right-click on a node and select "Plugins" to open the catalog

Plugins are organized by category and searchable. Each card shows the plugin name, description, and category badge.

Available Plugins

PluginCategoryDescription
Post to MastodonSocialPost a status update to a Mastodon server
Post Latest Prompt to MastodonSocialPost the most recent AI prompt response to Mastodon
Send EmailEmailSend an email via the SendGrid API
Store to MemoryStorageStore a value to short-term memory (S3) for later retrieval
Retrieve from MemoryStorageRetrieve a value from short-term memory (S3)
Publish to ChannelDataPublish a message to a Redis pub/sub channel for real-time delivery
Shopify Worst SellersShopifyFetch active products and rank by lowest sales
HTTP RequestCommunicationsMake a single HTTP request (GET, POST, PUT, DELETE, PATCH, OPTIONS)
HTTP StreamCommunicationsOpen a long-lived HTTP streaming connection

Blueprint Wizard

When you select a plugin from the catalog, a multi-step wizard guides you through configuration. Each step contains one or more fields that map to script parameters.

Wizard Field Types

Field TypeRendered AsDescription
textText inputStatic string value or environment variable name
textareaMulti-line inputLarger text content (e.g., email body)
selectDropdownChoose from predefined options
variable-pickerIdentifier / variable inputReference a V8 global variable or expression
jsonJSON editor (Monaco)JSON object or expression with syntax highlighting
booleanCheckboxTrue/false toggle
templateTemplate editorJinja2/Nunjucks template with {{ variable }} interpolation

Identifier vs. String Mode

Many fields support toggling between identifier mode (references a variable by name, e.g., payload.email) and string mode (a literal value, e.g., "user@example.com"). Click the mode toggle icon on any field to switch.

Validation

Fields include client-side validation rules: required fields, string minimums, regex patterns, and valid JavaScript identifiers. The wizard highlights errors before you can proceed to the next step.

Required Variables

Some plugins require environment variables to be configured at the organization level. The wizard shows these requirements and links to setup documentation. For example:

  • Mastodon requires MASTODON_URL and MASTODON_ACCESS_TOKEN
  • SendGrid requires SENDGRID_API_KEY
  • Shopify requires SHOPIFY_STORE_DOMAIN and SHOPIFY_ACCESS_TOKEN
  • HTTP Request/Stream — API keys are optional but commonly used

Inline Blueprint Nodes

When a blueprint is applied, the workflow canvas creates an inline node. Unlike standard Workflow Entity nodes that reference a database entity by ID, inline nodes carry their configuration directly on the workflow JSON:

{
"ref": "node-abc123",
"entityType": "action",
"name": "HTTP Request",
"blueprintSlug": "http-request",
"blueprintVersion": 1,
"blueprintValues": {
"url": "https://api.example.com/v1/data",
"method": "GET",
"apiKey": "MY_API_KEY",
"apiKeyHeader": "x-api-key",
"followRedirects": true,
"body": null
},
"preScript": "const result = await httpRequest({\n url: \"https://api.example.com/v1/data\",\n method: \"GET\",\n apiKey: MY_API_KEY,\n apiKeyHeader: \"x-api-key\",\n followRedirects: true,\n body: null,\n});\nprint(\"HTTP\", result.status, \"GET\", \"https://api.example.com/v1/data\");",
"postScript": null,
"children": [...]
}

Key Fields

FieldTypeDescription
blueprintSlugstringIdentifies which blueprint created this node (e.g., "http-request", "sendgrid-email")
blueprintVersionnumberBlueprint version number for upgrade tracking
blueprintValuesobjectThe wizard field values used to generate the script
preScriptstringThe generated V8 script that runs during execution
postScriptstring | nullOptional post-execution script

No Database Entity Required

Inline nodes do not have an entityId. The workflow engine generates a synthetic entity ID (inline-<ref>) at runtime. This means:

  • No WFE row — the node's script lives in the workflow JSON, not in the WorkflowEntity table
  • Self-contained — copying or exporting a workflow includes all plugin configuration
  • Immutable — changing a blueprint node requires re-running the wizard, which regenerates the script

Visual Indicators

On the workflow canvas, blueprint nodes appear with a circular icon matching their category, distinguishing them from standard star-shaped action nodes. Double-clicking a blueprint node re-opens the wizard for editing.


Script Template System

Each blueprint definition includes a scriptTemplate — a JavaScript code template with {{placeholder}} tokens that are substituted with wizard values.

How Templates Work

  1. The wizard collects values for each field (e.g., url, method, apiKey)
  2. Each {{key}} in the template is replaced with the field's value, rendered according to its renderAs mode:
    • string — wrapped in quotes: "https://api.example.com"
    • identifier — bare variable name: MY_API_KEY
    • expression — raw expression: { key: "value" }
    • template — Nunjucks rendered string
  3. The resulting script is stored as preScript on the node

Example: HTTP Request Template

Template:

const result = await httpRequest({
url: {{url}},
method: {{method}},
followRedirects: {{followRedirects}},
apiKey: {{apiKey}},
apiKeyHeader: {{apiKeyHeader}},
body: {{body}},
});
print("HTTP", result.status, {{method}}, {{url}});

With wizard values url="https://api.example.com/v1/data", method="POST", apiKey=MY_API_KEY, the generated script becomes:

const result = await httpRequest({
url: "https://api.example.com/v1/data",
method: "POST",
followRedirects: true,
apiKey: MY_API_KEY,
apiKeyHeader: "x-api-key",
body: { key: "value" },
});
print("HTTP", result.status, "POST", "https://api.example.com/v1/data");

Blueprint Outputs

Each blueprint defines expected output paths so the admin UI can suggest variables for downstream entities:

Output PathLabelDescription
context.lastResultResponse / ResultThe full return value from the script function
context.lastResult.statusStatus CodeHTTP status code (HTTP plugins)
context.lastResult.dataResponse DataParsed response body (HTTP plugins)
context.lastResult.headersResponse HeadersHTTP response headers
context.lastResult.linesProcessedLines ProcessedStream line count (HTTP Stream)
context.lastResult.keyStorage KeyS3 key (STM Store)
context.lastResult.urlPost URLMastodon post URL
context.lastResult.channelChannel NamePubSub channel name
context.lastResult.subscriberCountSubscriber CountPubSub delivery count

Execution at Runtime

When the consumer encounters an inline blueprint node during workflow traversal:

  1. Detection — the node has a preScript but no entityId, indicating an inline node
  2. Synthetic entity — a temporary entity object is created with ID inline-<ref>, the node's name, and the preScript/postScript
  3. Standard evaluation — the synthetic entity is passed through the same Unified Entity Evaluator pipeline as database-backed entities (arguments → preScript → condition → prompt → postScript)
  4. Entity-resume handling — if the script dispatches via Kinesis (e.g., httpRequest, httpStreamConnect), the __resumeDispatched__ flag prevents in-process child traversal. The children run when the Kinesis message is consumed.
  5. Logging — execution log entries use the synthetic ID and the node's name for traceability

Example Execution Log Entry

{
"type": "script",
"action": "executed",
"entityId": "inline-node-abc123",
"entityName": "HTTP Request",
"entityType": "Action",
"durationMs": 245
}

Plugin Visibility

Not all script modules appear in the Plugin Catalog. Modules set showInPlugins: false to hide from the UI while remaining available for direct script use. Hidden plugins are also excluded from the consumer's database sync — they exist only in code.

Currently hidden plugins include internal utilities like print, evaluateCondition, sleep, and assistantResearch. All plugins listed in the catalog table above have showInPlugins: true.


Database Sync

The consumer synchronizes plugin metadata with the database on startup:

  1. Load definitions — calls getScriptDefinitions() from the shared library to get all script modules
  2. Filter — skips modules with showInPlugins === false
  3. Upsert — creates or updates rows in the Plugin table with name, displayName, category, description, and definitions
  4. Cleanup — deletes rows for modules that were previously visible but are now hidden

This sync ensures the admin UI always reflects the current set of available plugins.


Creating a Blueprint (Seed System)

Blueprints are defined in prisma/seeds/blueprints.ts in the admin project and seeded to the database. Each blueprint seed includes:

interface BlueprintSeed {
slug: string; // Unique identifier (e.g., "http-request")
name: string; // Display name
description: string; // Shown in the catalog
category: string; // Grouping (Social, Email, Storage, etc.)
icon: string; // Material UI icon name
entityTypeName: string; // Always "Action" for current blueprints
steps: BlueprintStep[]; // Wizard steps with fields
scriptTemplate: string; // {{placeholder}} code template
outputs?: BlueprintOutput[];
requiredVariables?: BlueprintRequiredVariable[];
}

Blueprints are upserted (created or updated) on each seed run. Deprecated blueprints can be listed in REMOVED_BLUEPRINT_SLUGS for automatic cleanup.