@loopstack/meeting-notes-example-workflow
v0.20.3
Published
A complete workflow demonstrating how to create a workflow in loopstack based on a meeting notes summary use case.
Maintainers
Readme
@loopstack/meeting-notes-example-workflow
A module for the Loopstack AI automation framework.
This module provides an example workflow demonstrating how to build human-in-the-loop AI workflows with manual triggers and interactive documents.
Overview
The Meeting Notes Example Workflow shows how to create workflows that pause for user input and allow users to review and edit AI-generated content. It takes unstructured meeting notes and uses AI to extract structured information like date, participants, decisions, and action items.
By using this workflow as a reference, you'll learn how to:
- Use manual triggers to pause workflows for user input
- Create interactive documents with action buttons
- Handle transition payloads from user interactions via
runtime.transition.payload - Transform unstructured text into structured data with AI
- Build review-and-confirm patterns for AI outputs
- Use
@Stateto manage workflow state with schemas - Use
@Inputto define workflow arguments and document content schemas
This example is essential for developers building workflows that require human oversight or approval steps.
Installation
See SETUP.md for installation and setup instructions.
How It Works
Workflow Flow
- Start - User provides unstructured meeting notes via the input form
- Wait for Input - User can edit the notes, then clicks "Optimize Notes"
- AI Processing - LLM extracts structured information into a formatted document
- Review - User reviews and can edit the structured output
- Confirm - User clicks "Confirm" to finalize
Key Concepts
1. Workflow Input and State
Define input parameters with @Input and workflow state with @State:
@Input({
schema: z.object({
inputText: z
.string()
.default(
'- meeting 1.1.2025\n- budget: need 2 cut costs sarah said\n...',
),
}),
})
args: {
inputText: string;
};
@State({
schema: z.object({
meetingNotes: MeetingNotesDocumentSchema.optional(),
optimizedNotes: OptimizedMeetingNotesDocumentSchema.optional(),
}),
})
state: {
meetingNotes?: z.infer<typeof MeetingNotesDocumentSchema>;
optimizedNotes?: z.infer<typeof OptimizedMeetingNotesDocumentSchema>;
};2. Manual Triggers
Use trigger: manual to pause the workflow and wait for user interaction:
- id: user_response
from: waiting_for_response
to: response_received
trigger: manualThe workflow pauses at waiting_for_response until the user triggers the transition.
3. Document Actions with Buttons
Add action buttons to documents that trigger transitions. These are defined in the document's YAML config:
# meeting-notes-document.yaml
type: document
ui:
form:
properties:
text:
title: Text
widget: textarea
actions:
- type: button
widget: button
transition: user_response
options:
label: 'Optimize Notes'When clicked, the button triggers the user_response transition with the current document content.
4. Transition Payloads
Access user input from the transition payload using runtime.transition.payload:
- id: user_response
from: waiting_for_response
to: response_received
trigger: manual
call:
- id: create_response
tool: createDocument
args:
id: input
document: meetingNotesDocument
update:
content: ${{ runtime.transition.payload }}
assign:
meetingNotes: ${{ result.data.content }}The runtime.transition.payload contains the document content when the user clicked the button. The result is saved to workflow state via assign.
5. Custom Document Schemas
Define document content schemas using @Input on the content property:
export const MeetingNotesDocumentSchema = z.object({
text: z.string(),
});
@Document({
configFile: __dirname + '/meeting-notes-document.yaml',
})
export class MeetingNotesDocument implements DocumentInterface {
@Input({
schema: MeetingNotesDocumentSchema,
})
content: {
text: string;
};
}6. Structured Output Documents
Define complex document schemas for structured AI output:
export const OptimizedMeetingNotesDocumentSchema = z.object({
date: z.string(),
summary: z.string(),
participants: z.array(z.string()),
decisions: z.array(z.string()),
actionItems: z.array(z.string()),
});Configure the document UI with ordering, collapsible arrays, and confirm button:
# optimized-notes-document.yaml
type: document
ui:
form:
order:
- date
- summary
- participants
- decisions
- actionItems
properties:
date:
title: Date
summary:
title: Summary
widget: textarea
participants:
title: Participants
collapsed: true
items:
title: Participant
actionItems:
title: Action Items
collapsed: true
items:
title: Action Item
actions:
- type: button
widget: button
transition: confirm
options:
label: 'Confirm'7. AI Document Generation
Use aiGenerateDocument to populate a structured document. Reference state values with state.<name>:
- id: optimize_notes
from: response_received
to: notes_optimized
call:
- id: prompt
tool: aiGenerateDocument
args:
llm:
provider: openai
model: gpt-4o
response:
id: final
document: optimizedNotesDocument
prompt: |
Extract all information from the provided meeting notes into the structured document.
<Meeting Notes>
{{ state.meetingNotes.text }}
</Meeting Notes>Dependencies
This workflow uses the following Loopstack modules:
@loopstack/core- Core framework functionality@loopstack/core-ui-module- ProvidesCreateDocumenttool@loopstack/ai-module- ProvidesAiGenerateDocumenttool
About
Author: Jakob Klippel
License: Apache-2.0
Additional Resources
- Loopstack Documentation
- Getting Started with Loopstack
- Find more Loopstack examples in the Loopstack Registry
