Human-in-the-Loop
This example demonstrates how to create a workflow that involves human interaction and approval. Weβll build a content creation workflow that generates a draft document and waits for user confirmation before finalizing it.
Note: This example uses
create_mock
tools for demonstration purposes to keep the example simple and focused on core workflow concepts. In real-world use cases, you would replace these mock tools with actual tools that perform the specific processing operations your automation requires (such as API calls, data transformations, file operations, or LLM interactions).
Example: Content Creation with Human Approval
The following workflow demonstrates human-in-the-loop patterns through a content creation process that requires user confirmation.
In this example:
- System generates initial draft content
- Content presented to user for review in interactive form with switch control
- User can approve (switch on) for immediate publication
- User can reject (switch off) to request revision
- Revision process creates a feedback loop until approval
Workflow Configuration:
workflows:
- name: blog_post_review
type: stateMachine
transitions:
- name: create_draft # Step 1: Generate initial content draft
from: start
to: draft_created
call:
- tool: create_mock
arguments:
input: 'blog post about renewable energy'
output: |
# The Future of Renewable Energy
Renewable energy sources are becoming increasingly important as we work toward a sustainable future. Solar and wind power have seen dramatic cost reductions, making them competitive with traditional fossil fuels.
Key benefits include:
- Reduced carbon emissions
- Energy independence
- Long-term cost savings
The transition to renewable energy represents one of the most significant opportunities of our time.
as: DRAFT_CONTENT
- tool: create_chat_message
arguments:
role: 'assistant'
content: 'Draft content has been generated and is ready for your review.'
- name: show_approval_form # Step 2: Present draft to user for approval
from: draft_created
to: waiting_for_approval
call:
- tool: create_document
arguments:
document: approval_form
content:
draft_content: ${ DRAFT_CONTENT }
approved: false
feedback: ""
- name: process_approval # Step 3: Handle user's approval decision
from: waiting_for_approval
to:
- approved
- needs_revision
when: manual # Wait for user interaction
call:
- tool: create_mock
arguments:
input: ${ transition.payload }
output: ${ transition.payload.approved }
as: USER_DECISION
- tool: switch_target
arguments:
target: "{{#if USER_DECISION}}approved{{else}}needs_revision{{/if}}"
# Approval path
- name: finalize_content # Handle approved content
from: approved
to: end
call:
- tool: create_mock
arguments:
input: ${ DRAFT_CONTENT }
output: 'Content published successfully to blog.example.com'
as: PUBLISH_RESULT
- tool: create_chat_message
arguments:
role: 'assistant'
content: |
β
Content approved and published!
{{ PUBLISH_RESULT }}
# Revision path
- name: handle_revision # Handle revision requests
from: needs_revision
to: draft_created # Return to draft creation for revision
call:
- tool: create_chat_message
arguments:
role: 'assistant'
content: 'π Revision requested. Generating updated draft with your feedback...'
- tool: create_mock
arguments:
input: ${ DRAFT_CONTENT }
output: |
# The Future of Renewable Energy (Revised)
Renewable energy sources are rapidly transforming our global energy landscape. Solar and wind power have experienced unprecedented cost reductions, making them not just environmentally responsible but economically superior to traditional fossil fuels.
Key benefits include:
- Significant reduction in carbon emissions
- Enhanced energy independence and security
- Substantial long-term cost savings
- Job creation in emerging green industries
The transition to renewable energy represents the most transformative opportunity of our generation, offering both environmental and economic advantages.
as: DRAFT_CONTENT
The approval form provides user interface for content review and decision-making:
documents:
- name: approval_form
schema:
type: object
properties:
draft_content:
type: string
approved:
type: boolean
feedback:
type: string
required:
- draft_content
- approved
ui:
properties:
draft_content:
widget: textarea-expand
title: "Draft Content"
readonly: true
approved:
widget: switch
title: "Approve"
feedback:
widget: textarea
title: "Feedback (optional)"
placeholder: "Provide feedback for revisions..."
order:
- draft_content
- feedback
- approved
buttons:
- transition: process_approval
label: "Submit Decision"
enabledWhen:
- waiting_for_approval
Key Concepts:
- Boolean Decision: Switch widget provides clear approve/reject interaction
- Field Ordering:
order
property controls the layout sequence of form elements - Optional Feedback: Textarea for revision comments when approval is not granted
Understanding Human-in-the-Loop Patterns
The workflow demonstrates key patterns for human interaction:
Content Generation
- name: create_draft
from: start
to: draft_created
call:
- tool: create_mock
arguments:
input: 'blog post about renewable energy'
output: |
# The Future of Renewable Energy
Renewable energy sources are becoming increasingly important...
as: DRAFT_CONTENT
Key Concepts:
- Content Creation: Mock tool simulates content generation (could be LLM in real use)
- Data Export: Content stored in variable for later use in approval process
Create Documents for User Interaction
- name: show_approval_form
from: draft_created
to: waiting_for_approval
call:
- tool: create_document
arguments:
document: approval_form
content:
draft_content: ${ DRAFT_CONTENT }
approved: false
feedback: ""
Key Concepts:
- Document Creation: Creates interactive form with draft content
- Default Values: Sets initial state with approval false and empty feedback
- Data Passing: Draft content flows from generation to approval interface
Manual Decision Processing
- name: process_approval
from: waiting_for_approval
to:
- approved
- needs_revision
when: manual # Pauses for user input
call:
- tool: create_mock
arguments:
input: ${ transition.payload }
output: ${ transition.payload.approved }
as: USER_DECISION
- tool: switch_target
arguments:
target: "{{#if USER_DECISION}}approved{{else}}needs_revision{{/if}}"
Key Concepts:
- Manual Transition:
when: manual
waits for user interaction - Payload Access:
transition.payload
contains form data with approval status and feedback - Boolean Logic: Decision based on true/false approval value
- Conditional Routing:
switch_target
directs workflow based on boolean decision using Handlebars syntax
Approval Path
- name: finalize_content
from: approved
to: end
call:
- tool: create_mock
arguments:
input: ${ DRAFT_CONTENT }
output: 'Content published successfully to blog.example.com'
as: PUBLISH_RESULT
- tool: create_chat_message
arguments:
role: 'assistant'
content: |
β
Content approved and published!
{{ PUBLISH_RESULT }}
Revision Path
- name: handle_revision
from: needs_revision
to: draft_created # Return to draft state for revision
call:
- tool: create_chat_message
arguments:
role: 'assistant'
content: 'π Revision requested. Generating updated draft with your feedback...'
- tool: create_mock
arguments:
input: ${ DRAFT_CONTENT }
output: |
# The Future of Renewable Energy (Revised)
...enhanced content with improvements...
as: DRAFT_CONTENT
Running This Example
This example is already available in Loopstack Studio:
- Navigate to the Studio interface
- Switch to the examples workspace
- Select βExample 7: Human-in-the-Loop Workflowβ from the available automations
- Review the generated draft content
- Optionally provide feedback in the feedback field
- Use the approve switch to make your decision (on = approve, off = reject)
- Click βSubmit Decisionβ to process your choice
- For rejections, review the updated content and make another decision
Configuration Location: You can also view the complete configuration file at src/config/examples/basic/workflow-human-in-the-loop-example.yaml
Complete Example:
include:
- core/tools/create-mock.yaml
- core/tools/create-chat-message.yaml
- core/tools/create-document.yaml
- core/tools/switch-target.yaml
pipelines:
- name: human_in_the_loop_example
title: "Example 7: Human-in-the-Loop Workflow"
type: root
workspace: examples
sequence:
- workflow: blog_post_review
workflows:
- name: blog_post_review
type: stateMachine
transitions:
- name: create_draft # Step 1: Generate initial content draft
from: start
to: draft_created
call:
- tool: create_mock
arguments:
input: 'blog post about renewable energy'
output: |
# The Future of Renewable Energy
Renewable energy sources are becoming increasingly important as we work toward a sustainable future. Solar and wind power have seen dramatic cost reductions, making them competitive with traditional fossil fuels.
Key benefits include:
- Reduced carbon emissions
- Energy independence
- Long-term cost savings
The transition to renewable energy represents one of the most significant opportunities of our time.
as: DRAFT_CONTENT
- tool: create_chat_message
arguments:
role: 'assistant'
content: 'Draft content has been generated and is ready for your review.'
- name: show_approval_form # Step 2: Present draft to user for approval
from: draft_created
to: waiting_for_approval
call:
- tool: create_document
arguments:
document: approval_form
content:
draft_content: ${ DRAFT_CONTENT }
approved: false
feedback: ""
- name: process_approval # Step 3: Handle user's approval decision
from: waiting_for_approval
to:
- approved
- needs_revision
when: manual # Wait for user interaction
call:
- tool: create_mock
arguments:
input: ${ transition.payload }
output: ${ transition.payload.approved }
as: USER_DECISION
- tool: switch_target
arguments:
target: "{{#if (eq USER_DECISION true)}}approved{{else}}needs_revision{{/if}}"
# Approval path
- name: finalize_content # Handle approved content
from: approved
to: end
call:
- tool: create_mock
arguments:
input: ${ DRAFT_CONTENT }
output: 'Content published successfully to blog.example.com'
as: PUBLISH_RESULT
- tool: create_chat_message
arguments:
role: 'assistant'
content: |
β
Content approved and published!
{{ PUBLISH_RESULT }}
# Revision path
- name: handle_revision # Handle revision requests
from: needs_revision
to: draft_created # Return to draft creation for revision
call:
- tool: create_chat_message
arguments:
role: 'assistant'
content: 'π Revision requested. Generating updated draft with your feedback...'
- tool: create_mock
arguments:
input: ${ DRAFT_CONTENT }
output: |
# The Future of Renewable Energy (Revised)
Renewable energy sources are rapidly transforming our global energy landscape. Solar and wind power have experienced unprecedented cost reductions, making them not just environmentally responsible but economically superior to traditional fossil fuels.
Key benefits include:
- Significant reduction in carbon emissions
- Enhanced energy independence and security
- Substantial long-term cost savings
- Job creation in emerging green industries
The transition to renewable energy represents the most transformative opportunity of our generation, offering both environmental and economic advantages.
as: DRAFT_CONTENT
documents:
- name: approval_form
schema:
type: object
properties:
draft_content:
type: string
approved:
type: boolean
feedback:
type: string
required:
- draft_content
- approved
ui:
properties:
draft_content:
widget: textarea-expand
title: "Draft Content"
readonly: true
approved:
widget: switch
title: "Approve"
feedback:
widget: textarea
title: "Feedback (optional)"
placeholder: "Provide feedback for revisions..."
order:
- draft_content
- feedback
- approved
buttons:
- transition: process_approval
label: "Submit Decision"
enabledWhen:
- waiting_for_approval