Back to Discourse

Workflow AI authoring use cases

plugins/discourse-workflows/USE_CASES.md

2026.7.0-latest9.2 KB
Original Source

Workflow AI authoring use cases

Purpose: maintain a durable set of prompts for evaluating the Workflow AI authoring loop as schemas, tools, and prompting change.

How to run a dev eval

Use the synchronous dev runner so the latest local code and tools are used:

bash
bin/rails runner /tmp/workflow_ai_dev_run.rb '<prompt>' 'AI dev eval <id>' > /tmp/workflow_ai_<id>.json

For each run, record:

  • Session/workflow IDs and status
  • Tool calls used
  • Proposal shape
  • Whether Code nodes were avoided when declarative nodes are sufficient
  • Whether workflow_validate_patch was used and final expression_errors is empty
  • Token/time totals
  • Any optimization applied

Core regression prompts

IDPromptExpected shapeKey checks
tl1-cake-chatif a tl1 posts a post with the word cake make a post in the general chat channel linking to ittrigger:post_created -> condition:filter -> action:send_chat_messageUses $json.user.trust_level (trust level lives on the user object, not the post), $json.post.raw, $json.post.post_url; no Code node; chat template starts with =.
support-tag-replywhen a new topic is created in Support, tag it needs-review and reply with Thanks for contacting support. Our team will review this soon.trigger:topic_created -> action:topic_tags -> action:post (create)Resolves category/tag; after action:topic_tags, downstream reply uses $json.topic_id; no Code node.
closed-support-wait-archive-chat30 days after a topic in Support is closed, archive it and post a message in General chat linking to the topictrigger:topic_closed -> flow:wait -> action:topic (archive) -> action:send_chat_messageUses flow:wait; no unnecessary forum search/read; topic link template starts with =.
manual-maintenance-chatcreate a manual workflow that sends a message to General chat saying Maintenance window is starting nowtrigger:manual -> action:send_chat_messageStatic message does not need expression syntax; validates without expression errors.
closed-general-tl1-chatwhen a topic by a tl1 or lower is closed in the general category message the general channel with a link to the posttrigger:topic_closed -> action:topic (get) -> action:group (check_membership) -> condition:if -> action:send_chat_messageUses action:topic get to hydrate first-post fields (the topic payload has no trust_level). Resolves the trust_level_2 automatic group and uses action:group with operation: check_membership, resolved group_id, and username: ={{ $json.post.username }}, then continues on the condition false branch (group_membership.in_group == false) for TL1-or-lower because trust_level_N is cumulative for TL >= N. Uses $json.post.post_url; no Code node; no clarification needed.
friend-group-post-dm-adminwhen anyone in the friend group posts send admin a dm with a link to the posttrigger:post_created -> action:group (check_membership) -> condition:if -> action:send_personal_messageResolves the friend group and admin user; sets resolved group_id, uses $json.post.username for membership, branches on $json.group_membership.in_group, and uses $json.post.post_url in a leading-= personal message body; no Code node.

Additional prompts to rotate into evals

IDPromptExpected shapeKey checks
post-staff-exclusionwhen a non-staff user posts in General and the post contains urgent, send a message to General chat with a link to the posttrigger:post_created -> condition:filter -> action:send_chat_messageUses boolean filter on $json.post.staff plus string contains on $json.post.raw; no Code node.
topic-created-category-chatwhen a new topic is created in Support by a TL0 user, message General chat with the topic title and post linktrigger:topic_created -> condition:filter -> action:send_chat_messageUses $json.post.trust_level == 0, $json.topic.title, $json.post.post_url.
closed-topic-no-author-filterwhen any topic in General is closed, message General chat with a link to the topictrigger:topic_closed -> action:send_chat_message or trigger:topic_closed -> action:topic (get) -> action:send_chat_messageIf only topic link is needed, no author lookup is required; if post link is requested, use action:topic get.
wait-chat-reminderwhen a topic in Support is closed, wait 7 days and message General chat with the topic titletrigger:topic_closed -> flow:wait -> action:send_chat_messageWait parameters are wait_amount: 7, wait_unit: days; dynamic chat template starts with =.
tag-onlywhen a new topic is created in Support, add the needs-review tagtrigger:topic_created -> action:topic_tagsResolves category/tag; no reply; no Code node.
reply-onlywhen a new topic is created in Support, reply Thanks, we will review this shortly.trigger:topic_created -> action:post (create)Uses $json.topic.id; no unnecessary tag lookup.
post-created-category-filterwhen a post is created in Support by a TL1 user, message General chat with the post linktrigger:post_created -> condition:filter -> action:send_chat_messageTrigger category scoping or category filter is correct; uses $json.post.trust_level.
archive-closed-topicwhen a topic in Support is closed, wait 30 days and archive ittrigger:topic_closed -> flow:wait -> action:topic (archive)Uses archive operation, no chat lookup.
manual-topic-createcreate a manual workflow that creates a topic in General titled Maintenance update with body Maintenance is complete.trigger:manual -> action:topic (create)Resolves category; create operation includes title/raw/category; no Code node.
manual-logcreate a manual workflow that writes a log entry saying Manual workflow rantrigger:manual -> action:logNo external discovery needed; no Code node.
topic-admin-button-chatadd a topic admin button workflow that sends the current topic link to General chattrigger:topic_admin_button -> action:send_chat_messageUses topic-only schema; dynamic template starts with =.
tag-changed-chatwhen a topic in Support gets the needs-review tag, message General chat with the topic titletrigger:topic_tag_changed -> condition:filter? -> action:send_chat_messageUses tag-changed schema for added_tags/new_tags if available; should query catalog first.
category-changed-chatwhen a topic is moved into Support, message General chat with a link to the topictrigger:topic_category_changed -> action:send_chat_messageShould query catalog for old/new category fields before drafting.
badge-grantwhen a TL1 user posts in General with the word helpful, grant them the Basic badgetrigger:post_created -> condition:filter -> action:badgeUses declarative filter; resolves badge; no Code node.
group-addwhen a TL1 user creates a topic in Support, add them to the helpers grouptrigger:topic_created -> condition:filter -> action:groupUses $json.post.username; resolves group; no Code node.
http-request-warningwhen a new topic is created in Support, send the topic title to https://example.com/webhooktrigger:topic_created -> action:http_requestIncludes external HTTP risk; validates URL/method/body; no Code unless necessary.

Known edge cases to keep testing

  • Topic-only triggers that need author/post fields should use action:topic get before filtering or messaging.
  • Generic prompts like "when someone posts" should use trigger:post_created for all regular posts; do not ask whether to include replies unless the prompt explicitly narrows the scope.
  • Actions that replace item JSON require downstream nodes to use the action output schema, not the original trigger schema.
  • Dynamic strings containing {{ }} must start with =.
  • Simple trust/text/category/staff checks should use condition:filter, not Code nodes. condition:if is for separate true/false branches.
  • Trust level is only exposed as $json.user.trust_level on triggers with a user object (e.g. trigger:post_created); the post/topic payloads have no trust_level. When a trust-level check is needed but no trust_level field is in scope (topic-only triggers), resolve the cumulative trust_level_N automatic group and use action:group with operation: check_membership plus resolved group_id -- do not ask for clarification or add a Code node.
  • Condition builder entries must use leftValue and rightValue; left/right will not execute correctly.
  • Connections leaving condition:filter or condition:if should use connection_type: "true" for the passing branch, not main.
  • Group membership checks should use action:group with operation: check_membership and the resolved group_id instead of Code nodes. Branch with condition:if on $json.group_membership.in_group when different member and non-member paths are needed.
  • DM/personal-message notifications should use action:send_personal_message instead of chat or topic reply nodes.
  • Forum search/read should not be used for node/schema discovery; use workflow_node_catalog and workflow_validate_patch.