Discourse Workflows

AI-generated summary

lindsey introduced Discourse Workflows, a visual automation builder included in Discourse core for Business and Enterprise plans. It allows admins to create multi-step automations using a drag-and-drop canvas, connecting triggers, conditions, and actions. Key concepts include Data Tables for persistent state and lookups, a global Executions tab for monitoring, and Templates to jumpstart workflow creation. Users are encouraged to request new templates or share feedback.

Users reported initial issues and received guidance. patrickemin faced a permission error when enabling the plugin, which awesomerobot clarified must be activated via /admin/config/upcoming-changes. dennisjbr encountered an “Invalid JSON payload” error when using AI-powered workflows with Gemini 3 Flash. sam suggested switching to more robust LLMs (like Sonnet or Luna) due to the complex tool requirements of the workflow agent. j.jaffeux later confirmed a fix was implemented.

Community contributions and updates followed. Ethsim2 submitted a PR adding Event actions (open/close events) to Workflows, noting that while the code was tested, the feature might be superseded by official updates. j.jaffeux confirmed that an official Event node is scheduled for release. Addressing a separate issue regarding PM tags, j.jaffeux explained the need to add users to pm_tags_allowed_for_groups and promised better error messaging. Additionally, new triggers for tag creation and nodes for adding tags to groups were announced in subsequent commits.

Finally, Ethsim2 clarified the templating language used within Workflows. Contrary to Liquid or Handlebars, it uses sandboxed JavaScript expressions (e.g., ={{ $json.topic.title.toLowerCase() }}) evaluated server-side. The implementation exposes specific globals like $json and $input and shares conceptual similarities with n8n, a popular automation tool, including specific behaviors for merging data.

:discourse2: Summary Discourse Workflows lets admins create advanced automations through a visual builder to automate almost anything in your community.
:open_book: Install Guide This plugin is bundled with Discourse core. There is no need to install the plugin separately.

Workflows is a visual automation builder that lets admins create advanced, multi-step automations using a drag-and-drop canvas — connecting triggers, conditions, actions, and flow-control nodes to automate almost anything on your Discourse site.

:discourse: Discourse Workflows is available on the Business or Enterprise plans.

Key concepts

If you’re familiar with other automation tooling, you will likely recognize most of the vocabulary used in Workflows:

  • Workflow: A saved automation made up of connected nodes.
  • Node: A single step in a workflow: triggers, conditions, actions, and flow-control / utilities.
  • Trigger: The starting point of a workflow. A trigger can be manual or initiated by a specific event — topic being created, a schedule firing, or an incoming webhook.
  • Condition: A routing node that evaluates a rule and splits the flow into branches. For example, an If node routes the flow based on a true or false evaluation.
  • Action: A node that does something specific — creating a post, granting a badge, calling an external API, etc.
  • Item: The data that flows between nodes. Items are JSON objects that you can inspect in execution logs and reference using expressions.
  • Expression: A dynamic value written as {{ ... }} that resolves at runtime and is used to reference data from earlier nodes, variables, or site settings.

Creating a workflow

To build a workflow:

  1. Go to Admin > Plugins > Workflows and click New workflow.

  1. Name your workflow.
  2. Click Add first step and choose your trigger.

  1. Use the + button to add additional nodes.

  1. Double-click on a node to configure it. In the configuration panel, details about inputs for the node will be shown on the left side and details about the outputs of the node will be shown on the right side of the screen. You may need to run the workflow once before seeing all the various details.

  1. When you’re ready to go live, click Publish.

:light_bulb: Tips:

  • Use sticky notes, located in the three-dot menu in the top right of the builder, to document what your workflow does. Stickies don’t have any effect on the workflow but make templates and shared workflows easier to understand.
  • Use the log node during development to send debug values into the execution log without impacting the workflow’s behavior.
  • You can export and import workflows as JSON to share them with teammates or move them between sites. See Exporting and importing workflows below for what is and isn’t transferred.

Expressions and dynamic data

Fields that accept expressions show a {/} button in the editor. Click it to browse available data from the trigger and earlier nodes and insert a reference.

Common expressions

Expression What it returns
{{ $json.topic.title }} The title of the topic from the current item
{{ $json.post.url }} The URL of the post from the current item
{{ $json.user.username }} The username of the user associated with the current item
{{ $workflow_vars.my_variable }} The value of a workflow variable named my_variable
{{ $vars.my_variable }} The value of a global variable named my_variable
{{ $site_settings.title }} Your site’s title
{{ $execution.id }} The unique ID of the current execution
{{ $('Node Name').item.json.property }} Output from a specific upstream node, referenced by its canvas name

Static and dynamic values

Fields that start with = are treated as expressions. Fields without a leading = are treated as plain text. The expression picker handles this for you automatically.

Managing workflows

There are a number of features that help you manage your existing workflows.

Executions

Every time a workflow runs, Discourse records an execution. Go to Workflows → Executions to see the history.

Each execution shows the date and time when it was completed and its status:

  • Completed: Ran to completion without error.
  • Error: Failed at a specific node; click into the execution to see the error and the data that caused it.
  • Running: Currently processing.
  • Waiting: Paused due to a Wait node; waiting for a response in a form, modal, chat approval; or a Call Workflow node waiting for a sub-workflow to complete.
  • Rate limited: The workflow was skipped due to rate limiting.
  • Skipped: The trigger fired but the workflow was unpublished.

You can click the Show button for a more in depth look at the workflow’s execution. This shows each step of the workflow, which you can expand to view the exact details, and the duration of that step.

At the bottom of the page, you can see the overall duration of the workflow. You can also Export the log if needed for sharing or troubleshooting purposes.

Settings

On the Workflows → Settings tab, you can:

  • Configure an error workflow that should trigger if there are any failures when this workflow runs. If the workflow has an error trigger, it will handle errors as defined by that trigger.
  • Set the timezone for schedule triggers. The workflow will default to using the site timezone if this is unset.
  • Delete the workflow. :warning: This is permanent so you should consider exporting your workflow (accessible in the three-dot menu on the top right corner of the workflow builder) before proceeding.

Versions

Every time you make an update to the workflow, we’ll save the previous version(s). This makes it easy to Revert changes that didn’t work as you expected.

Exporting and importing workflows

Use the three-dot menu in the top right corner of the workflow builder to Export a workflow as a JSON file, and Import to load one. Common uses: sharing a workflow with teammates, or moving it from a staging site to production.

Importing adds the file’s nodes to the workflow you have open; it does not create a new workflow. To copy a workflow, create an empty workflow first, then import into it. Imported changes are saved as a draft until you publish.

Included in the export: nodes and their configuration, connections, sticky notes, and workflow variable definitions.

Not transferred, so set these up on the destination site before publishing:

  • Credentials: credential references are removed on import. Create the credentials on the destination site and select them again in each node.
  • Data tables: tables, columns, and rows are not exported. Recreate them and select them in the Data table nodes.
  • Variable values: workflow variable definitions are imported, but not their values. Set them in the workflow’s Variables tab. If a variable with the same key already exists, the import keeps the existing one and shows which keys were skipped. Global variables are not exported.
  • Workflow settings: the error workflow and timezone are not applied. Set them again in the Settings tab.
  • Site-specific references: IDs, names, and URLs for categories, groups, users, chat channels, Data Explorer queries, and called workflows are kept as-is and may not match the destination site. Workflow variables make these easier to change.

:light_bulb: Run the imported workflow manually and check the Executions log before publishing it.

Variables

There are two kinds of variables:

  • Workflow variables are scoped to a single workflow. Define them in the workflow’s Variables tab and reference them with {{ $workflow_vars.key_name }}. They have a type (string, integer, boolean, enum, category, category list, group, group list, tag list, or list), so values are validated and picked with the right selector. Changes to definitions and values follow the workflow’s draft/publish flow.
  • Global variables are shared by all workflows. Define them in Workflows → Variables and reference them with {{ $vars.key_name }}.

Use workflow variables for values that change between sites or uses, such as a category, a group, or a recipient, so you can reuse the workflow without editing its nodes.

Credentials

Some nodes — like HTTP request or AI Agent — need to authenticate with external services. Store API keys and secrets in Workflows → Credentials rather than pasting them directly into node fields. Credentials are encrypted at rest and can be reused across workflows.

Supported credential types:

  • Basic Auth (username + password)
  • Bearer token
  • Header auth (custom header name and value)

Data tables

Data tables are persistent, structured tables internal to the Workflows plugin. Use the Data table node to read from or write to them. They support string, number, boolean, and date column types.

Data tables are useful for:

  • Deduplication — record which users or topics a workflow has already processed
  • State — track whether a topic is in a particular stage of a process
  • Lookups — store mappings (like topic ID → assigned staff member) that your workflows can query

Executions

You can view all the executions of all workflows from the Executions tab. The format and function is very similar to the workflow-specific executions, but shows across all workflows for easier monitoring.

Templates

When you create a new workflow, you can start from a template instead of a blank canvas. Templates are pre-built workflows for common use cases — they’re annotated with sticky notes explaining how they work and are a good way to learn the system.

:megaphone: Interested in seeing more templates? We will work to expand the library of available templates over time, but please let us know if there’s a template that you’d like to see here to make your use of Workflows easier.

You can also export any workflow as a JSON file to share it with others or use it as your own starting point.

24 Likes

Hi, when trying to activate this plugin I have the following error message: You do not have permission to change the hidden settings : discourse_workflows_enabled

2 Likes

At the moment it must be enabled from /admin/config/upcoming-changes, not admin/plugins

3 Likes

Hi, if I understand the purpose of these Workflows correctly, one template example I wish is to add an admin button to topics that would immediately bump the topic. Feasible ? :grinning_face:

1 Like

Howdy!

How do we ensure that the “Build with AI” uses a particular LLM?
When using Google Gemini as the default LLM in our system im getting the error: Invalid JSON payload received. Unknown name “additionalProperties” at ‘tools[0].function_declarations[5].parameters’: Cannot find field

Thanks!

1 Like

Which Gemini model are you using? To change it pick the workflow agent and swap the default llm on it

1 Like

Hey Sam! Gemini 3 Flash.

I found the workflow setting and it was indeed Gemini Flash 3. I moved to ti GPT Nano 5, and still get the same error.

I even changed default for everyone to GPT Nano 5 and checked the individual Workflow setting. Set that to override with GPT Nano 5 as well.

Still no dice. :frowning:

1 Like

Any chance you have access to Luna or terra, or 3.5 flash or sonnet ?

The workflow ai agent has quite a few tools so if tend to require a recent llm

1 Like

I could have sworn Flash Lite worked, but it did not. GPT Nano 5 definitely worked. It looks like this is a known issue even with Wordpress. here is a link for reference. What we need to do is whenever we are using a Gemini provider, to remove the additionalProperties item from the JSON Response Schema: Remove `additionalProperties` from the JSON response schema - Pull Request #18 - WordPress/ai-provider-for-google - GitHub

yikes, I am spiking a move to interactions api, so I think this should give us a far more stable bridge into gemini models, hopefully next week.

2 Likes

Awesome and thanks for the quick response! I found some more content but I think you get the idea. :wink:

This is Google’s own Gemini explanation. Hope it makes sense? I don’t get all of it, but I just know it chokes on that property. LOL.

TL;DR: The error persists because Google uses two entirely different engines for schema processing. While Gemini supports standard JSON Schema for Structured Outputs (response_json_schema), its Function Calling / Tool Execution engine still uses Google’s strict OpenAPI 3.0 Protobuf parser, which rejects or chokes on additionalProperties.

1. Tool Calling vs. Structured Output (The Engine Split)

Google’s Gemini API validates schemas in two separate places:

  • Structured Outputs (response_json_schema): Designed for formatting the model’s final response. It uses standard JSON Schema parsing and handles additionalProperties cleanly.

  • Tool / Function Calling (tools[0].function_declarations): Designed for passing site tools (like Discourse AI search, persona actions, or web browsing) to the model. This endpoint parses schemas into Google’s internal google.ai.generativelanguage.v1beta.Schema Protobuf object.

Because the tool endpoint maps parameters to a legacy OpenAPI 3.0 subset, sending additionalProperties in a function declaration causes the API parser to return a 400 Bad Request or MALFORMED_FUNCTION_CALL.

GitHub

2. Why Frameworks Like Discourse Inject It

Orchestration frameworks (Discourse AI, Model Context Protocol/MCP, LangChain, Pydantic, Zod) automatically generate JSON schemas for custom tools:

  1. Strict Enforcement Defaults: Generators automatically add "additionalProperties": false to force strict parameter typing.

  2. Dynamic Maps/Dictionaries: If a tool parameter uses a key-value hash/dictionary (e.g., dict[str, Any] or a Ruby Hash), schema generators output "additionalProperties": { "type": "string" }.

  3. Unsanitized Payload: When Discourse sends these auto-generated tool schemas to Google’s function declarations endpoint, Gemini’s Protobuf parser flags additionalProperties as an invalid or unknown field.

3. How to Resolve It in Discourse

If you are seeing this error in Discourse AI tool calls:

  • Avoid Dynamic Hash/Dict Parameters: Ensure custom tool parameters explicitly define every expected key under properties rather than using open-ended objects.

  • Serialize Dynamic Data as Strings: If a tool must accept arbitrary key-value pairs, define the parameter as a STRING and instruct the tool to accept a serialized JSON string.

  • Filter Out additionalProperties in Custom Tools: If you have custom AI tools defined under /admin/plugins/discourse-ai/ai-tools, edit the parameter JSON schema to remove any "additionalProperties" blocks.

I just made a pr that add support for interaction api, if you have a test env would be happy with some more testing

Are there any plans to allow retrieving external user IDs through workflows? I’d like to make a form which checks some information about the current user in the identity provider system before continuing, but the Get User node does not output any external_id field as far as I can tell.

Thanks for the feedback, that should do it: FIX: supports optional data for workflow user node (#42400) · discourse/discourse@4d0c688 · GitHub

3 Likes

Is there some way to convert a user_id into username? I was looking into a use case that sends the creator of a topic a personal message. But from the topic object I can only get the user_id, and the action for personal message requires a username instead.

Or alternatively - if there was a way to get the first post using the topic_id, then it would work too, I see post has a username field

1 Like

@thgl Yes given we have a data-explorer node, any kind of query to get any kind of info is possible (in this case I hardcoded the user_id but you get the idea):

workflow-nodes-2026-08-18.json (2.1 KB)

2 Likes

@patrickemin Not sure if you have seen it already but I have added all the building blocks necessary for this use case, let me know if you need help.

1 Like

Ah that is nifty, thanks!

Well, I did not find the action to assign to the admin topic button for that use case: