Skip to main content

Workflow Distribution

This guide covers how to prepare and distribute your workflows to other users, including documenting expected inputs, creating configurable templates, and making your workflows easy to understand and use.

Table of Contents

Template Fields

Template fields allow workflow authors to create parameterized workflows that end users can configure before execution. When building a workflow for distribution, you can mark specific fields as templates to indicate which values should be customized by each user.

This system enables workflow creators (editors) to define what the final user needs to configure, rather than hardcoding environment-specific values. It's useful for model names, timeout values, token limits, and other parameters that vary between deployments or use cases.

Defining Template Fields

A template field is defined using special markers in place of actual values:

  • __type: The data type ("string", "number", "boolean", "object", "array")
  • __description: Human-readable description of what this field is for
  • __required: Optional boolean, defaults to true. When false, the field is optional
  • __default: Optional default value. Used when the field is optional and not configured by the user

A field is detected as a template when both __type and __description are present.

Required vs Optional Template Fields

Required template fields (default behavior):

  • Must be configured by the end user before execution
  • No default value

Optional template fields with default:

  • Can be left unconfigured
  • Will use the __default value if not configured
  • Useful for parameters that have sensible defaults

Optional template fields without default:

  • Can be left unconfigured
  • Parameter will be omitted entirely if not configured
  • Useful for truly optional parameters

Template Field Locations

Template fields can be defined in:

  • Addon configurations (addons[].config)
  • Step parameters (workflow.steps[].parameters)
  • Nested objects at any depth

Example: Basic Template Fields

{
"addons": [
{
"id": "openai-1",
"package": "openai",
"config": {
"model": {
"__type": "string",
"__description": "Model name (e.g., gpt-4, gpt-3.5-turbo)",
"__required": true
},
"timeout": {
"__type": "number",
"__description": "Request timeout in seconds",
"__required": false,
"__default": 30
},
"retry_count": {
"__type": "number",
"__description": "Number of retry attempts on failure",
"__required": false
}
}
}
]
}

In this example:

  • model is required and must be configured
  • timeout is optional with a default of 30 seconds
  • retry_count is optional without a default (will be omitted if not configured)

Example: Nested Template Fields

{
"workflow": {
"steps": [
{
"id": "step-1",
"parameters": {
"model": {
"__type": "string",
"__description": "Model name"
},
"config": {
"temperature": {
"__type": "number",
"__description": "Model temperature (0.0-1.0)"
},
"advanced": {
"max_tokens": {
"__type": "number",
"__description": "Maximum tokens for response"
}
}
}
}
}
]
}
}

Configuration Process

The template field workflow:

  1. Workflow creator (editor) builds a workflow and marks certain fields as templates using __type and __description
  2. Workflow creator distributes the workflow to end users
  3. End user receives the workflow and replaces template fields with their specific configuration values
  4. End user executes the configured workflow with the engine

This separation allows the workflow creator to design reusable workflows while giving end users control over environment-specific settings.

Replacing Template Fields

To configure a workflow with template fields, replace each template with an actual value:

Before (template field):

{
"max_tokens": {
"__type": "number",
"__description": "Maximum tokens for response"
}
}

After (configured):

{
"max_tokens": 500
}

Remove the __type, __description, __required, and __default markers and replace the entire object with the actual value.

For optional fields with defaults, you can either:

  • Provide your own value (replaces the default)
  • Leave it unconfigured and it will use the __default value
  • Omit the field entirely if you want to use the default

Documenting Expected Content

When creating workflows that accept payloads, you should document what data structure is expected in the payload's content field. This helps users understand how to properly invoke your workflow.

Expected Content Field

The expectedContent field in entrypoints is an array that describes the fields expected inside the payload's content object.

{
"entrypoints": [
{
"id": "process-user",
"name": "Process User Data",
"startAt": "step-validate-user",
"expectedContent": [
{
"name": "username",
"type": "string",
"description": "The username of the user to process"
},
{
"name": "email",
"type": "string",
"description": "User's email address"
},
{
"name": "age",
"type": "number"
}
]
}
]
}

Field Definition Structure

Each field in expectedContent has the following properties:

  • name (required): The name of the field in the payload content object
  • type (required): The data type of the field (e.g., "string", "number", "boolean", "object", "array")
  • description (optional): A human-readable description of what this field represents and how it should be used

Payload Structure

Payloads always have two required fields: type and content. The expectedContent array describes what fields should be in the content object:

user-data.json:

{
"type": "application/json",
"content": {
"username": "john_doe",
"email": "john@example.com",
"age": 30
}
}

In this example:

  • type and content are the standard payload structure
  • The content object contains the fields described in expectedContent: username, email, and age

Best Practices for Distribution

1. Document All Entrypoints

Every entrypoint that accepts external data should have expectedContent defined:

{
"entrypoints": [
{
"id": "default",
"name": "Default Processing",
"startAt": "step-start",
"expectedContent": []
},
{
"id": "process-order",
"name": "Process Order",
"startAt": "step-validate-order",
"expectedContent": [
{
"name": "orderId",
"type": "string",
"description": "Unique order identifier"
},
{
"name": "totalAmount",
"type": "number",
"description": "Total order amount in USD"
}
]
}
]
}

The corresponding payload would be:

{
"type": "application/json",
"content": {
"orderId": "ORD-12345",
"totalAmount": 99.99
}
}

2. Use Clear Descriptions

Provide helpful descriptions that explain what the field is used for, valid values or formats, and whether the field is optional:

{
"name": "date",
"type": "string",
"description": "ISO 8601 date string (e.g., 2024-01-15T10:30:00Z)"
}

3. Nested Objects

For complex nested structures, document nested fields using dot notation:

{
"expectedContent": [
{
"name": "user",
"type": "object",
"description": "User object containing profile information"
},
{
"name": "user.username",
"type": "string",
"description": "Unique username identifier"
},
{
"name": "user.profile.theme",
"type": "string",
"description": "UI theme preference (light/dark)"
}
]
}

Payload:

{
"type": "application/json",
"content": {
"user": {
"username": "johndoe",
"profile": {
"theme": "dark"
}
}
}
}