@loopstack/meeting-notes-example-workflow 0.21.0 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +75 -111
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > A module for the [Loopstack AI](https://loopstack.ai) automation framework.
4
4
 
5
- This module provides an example workflow demonstrating how to build human-in-the-loop AI workflows with manual triggers and interactive documents.
5
+ This module provides an example workflow demonstrating how to build human-in-the-loop AI workflows with interactive documents and review steps.
6
6
 
7
7
  ## Overview
8
8
 
@@ -10,13 +10,13 @@ The Meeting Notes Example Workflow shows how to create workflows that pause for
10
10
 
11
11
  By using this workflow as a reference, you'll learn how to:
12
12
 
13
- - Use manual triggers to pause workflows for user input
13
+ - Use `wait: true` transitions to pause workflows for user input
14
14
  - Create interactive documents with action buttons
15
- - Handle transition payloads from user interactions via `runtime.transition.payload`
16
- - Transform unstructured text into structured data with AI
15
+ - Handle transition payloads from user interactions
16
+ - Transform unstructured text into structured data with AI using `ClaudeGenerateDocument`
17
17
  - Build review-and-confirm patterns for AI outputs
18
- - Use `@State` to manage workflow state with schemas
19
- - Use `@Input` to define workflow arguments and document content schemas
18
+ - Define workflow input schemas via the `@Workflow` decorator
19
+ - Use the document repository to save and update documents
20
20
 
21
21
  This example is essential for developers building workflows that require human oversight or approval steps.
22
22
 
@@ -30,54 +30,48 @@ See [SETUP.md](./SETUP.md) for installation and setup instructions.
30
30
 
31
31
  1. **Start** - User provides unstructured meeting notes via the input form
32
32
  2. **Wait for Input** - User can edit the notes, then clicks "Optimize Notes"
33
- 3. **AI Processing** - LLM extracts structured information into a formatted document
33
+ 3. **AI Processing** - Claude extracts structured information into a formatted document
34
34
  4. **Review** - User reviews and can edit the structured output
35
35
  5. **Confirm** - User clicks "Confirm" to finalize
36
36
 
37
37
  ### Key Concepts
38
38
 
39
- #### 1. Workflow Input and State
39
+ #### 1. Workflow Input Schema
40
40
 
41
- Define input parameters with `@Input` and workflow state with `@State`:
41
+ Define input parameters directly in the `@Workflow` decorator with a Zod schema:
42
42
 
43
43
  ```typescript
44
- @Input({
44
+ @Workflow({
45
+ uiConfig: __dirname + '/meeting-notes.ui.yaml',
45
46
  schema: z.object({
46
47
  inputText: z
47
48
  .string()
48
49
  .default(
49
- '- meeting 1.1.2025\n- budget: need 2 cut costs sarah said\n...',
50
+ '- meeting 1.1.2025\n- budget: need 2 cut costs sarah said\n- hire new person?? --> marketing\n- vendor pricing - follow up needed by anna',
50
51
  ),
51
52
  }),
52
53
  })
53
- args: {
54
- inputText: string;
55
- };
54
+ export class MeetingNotesWorkflow extends BaseWorkflow<{ inputText: string }> {
55
+ @InjectTool() claudeGenerateDocument: ClaudeGenerateDocument;
56
56
 
57
- @State({
58
- schema: z.object({
59
- meetingNotes: MeetingNotesDocumentSchema.optional(),
60
- optimizedNotes: OptimizedMeetingNotesDocumentSchema.optional(),
61
- }),
62
- })
63
- state: {
64
57
  meetingNotes?: z.infer<typeof MeetingNotesDocumentSchema>;
65
58
  optimizedNotes?: z.infer<typeof OptimizedMeetingNotesDocumentSchema>;
66
- };
59
+ }
67
60
  ```
68
61
 
69
- #### 2. Manual Triggers
62
+ #### 2. Waiting Transitions
70
63
 
71
- Use `trigger: manual` to pause the workflow and wait for user interaction:
64
+ Use `wait: true` with a `schema` to pause the workflow and wait for user interaction. The schema validates the payload submitted by the user:
72
65
 
73
- ```yaml
74
- - id: user_response
75
- from: waiting_for_response
76
- to: response_received
77
- trigger: manual
66
+ ```typescript
67
+ @Transition({ from: 'waiting_for_response', to: 'response_received', wait: true, schema: MeetingNotesDocumentSchema })
68
+ async userResponse(payload: z.infer<typeof MeetingNotesDocumentSchema>) {
69
+ const result = await this.repository.save(MeetingNotesDocument, payload, { id: 'input' });
70
+ this.meetingNotes = result.content as z.infer<typeof MeetingNotesDocumentSchema>;
71
+ }
78
72
  ```
79
73
 
80
- The workflow pauses at `waiting_for_response` until the user triggers the transition.
74
+ The workflow pauses at `waiting_for_response` until the user submits data via the document button.
81
75
 
82
76
  #### 3. Document Actions with Buttons
83
77
 
@@ -96,38 +90,15 @@ ui:
96
90
  widget: textarea
97
91
  actions:
98
92
  - type: button
99
- transition: user_response
93
+ transition: userResponse
100
94
  label: 'Optimize Notes'
101
95
  ```
102
96
 
103
- When clicked, the button triggers the `user_response` transition with the current document content.
97
+ When clicked, the button triggers the `userResponse` transition with the current document content as the payload.
104
98
 
105
- #### 4. Transition Payloads
99
+ #### 4. Custom Document Schemas
106
100
 
107
- Access user input from the transition payload using `runtime.transition.payload`:
108
-
109
- ```yaml
110
- - id: user_response
111
- from: waiting_for_response
112
- to: response_received
113
- trigger: manual
114
- call:
115
- - id: create_response
116
- tool: createDocument
117
- args:
118
- id: input
119
- document: meetingNotesDocument
120
- update:
121
- content: ${{ runtime.transition.payload }}
122
- assign:
123
- meetingNotes: ${{ result.data.content }}
124
- ```
125
-
126
- The `runtime.transition.payload` contains the document content when the user clicked the button. The result is saved to workflow state via `assign`.
127
-
128
- #### 5. Custom Document Schemas
129
-
130
- Define document content schemas using `@Input` on the `content` property:
101
+ Define document content schemas using the `@Document` decorator with a Zod schema:
131
102
 
132
103
  ```typescript
133
104
  export const MeetingNotesDocumentSchema = z.object({
@@ -135,19 +106,15 @@ export const MeetingNotesDocumentSchema = z.object({
135
106
  });
136
107
 
137
108
  @Document({
109
+ schema: MeetingNotesDocumentSchema,
138
110
  uiConfig: __dirname + '/meeting-notes-document.yaml',
139
111
  })
140
- export class MeetingNotesDocument implements DocumentInterface {
141
- @Input({
142
- schema: MeetingNotesDocumentSchema,
143
- })
144
- content: {
145
- text: string;
146
- };
112
+ export class MeetingNotesDocument {
113
+ text: string;
147
114
  }
148
115
  ```
149
116
 
150
- #### 6. Structured Output Documents
117
+ #### 5. Structured Output Documents
151
118
 
152
119
  Define complex document schemas for structured AI output:
153
120
 
@@ -159,6 +126,18 @@ export const OptimizedMeetingNotesDocumentSchema = z.object({
159
126
  decisions: z.array(z.string()),
160
127
  actionItems: z.array(z.string()),
161
128
  });
129
+
130
+ @Document({
131
+ schema: OptimizedMeetingNotesDocumentSchema,
132
+ uiConfig: __dirname + '/optimized-notes-document.yaml',
133
+ })
134
+ export class OptimizedNotesDocument {
135
+ date: string;
136
+ summary: string;
137
+ participants: string[];
138
+ decisions: string[];
139
+ actionItems: string[];
140
+ }
162
141
  ```
163
142
 
164
143
  Configure the document UI with ordering, collapsible arrays, and confirm button:
@@ -170,67 +149,52 @@ ui:
170
149
  widgets:
171
150
  - widget: form
172
151
  options:
173
- order:
174
- - date
175
- - summary
176
- - participants
177
- - decisions
178
- - actionItems
152
+ order: [date, summary, participants, decisions, actionItems]
179
153
  properties:
180
- date:
181
- title: Date
182
- summary:
183
- title: Summary
184
- widget: textarea
185
- participants:
186
- title: Participants
187
- collapsed: true
188
- items:
189
- title: Participant
190
- actionItems:
191
- title: Action Items
192
- collapsed: true
193
- items:
194
- title: Action Item
154
+ date: { title: Date }
155
+ summary: { title: Summary, widget: textarea }
156
+ participants: { title: Participants, collapsed: true, items: { title: Participant } }
157
+ decisions: { title: Decisions, collapsed: true, items: { title: Decision } }
158
+ actionItems: { title: Action Items, collapsed: true, items: { title: Action Item } }
195
159
  actions:
196
160
  - type: button
197
161
  transition: confirm
198
162
  label: 'Confirm'
199
163
  ```
200
164
 
201
- #### 7. AI Document Generation
165
+ #### 6. AI Document Generation
202
166
 
203
- Use `aiGenerateDocument` to populate a structured document. Reference state values with `state.<name>`:
167
+ Use `ClaudeGenerateDocument` to populate a structured document. Reference workflow properties for dynamic content:
204
168
 
205
- ```yaml
206
- - id: optimize_notes
207
- from: response_received
208
- to: notes_optimized
209
- call:
210
- - id: prompt
211
- tool: aiGenerateDocument
212
- args:
213
- llm:
214
- provider: openai
215
- model: gpt-4o
216
- response:
217
- id: final
218
- document: optimizedNotesDocument
219
- prompt: |
220
- Extract all information from the provided meeting notes into the structured document.
221
-
222
- <Meeting Notes>
223
- {{ state.meetingNotes.text }}
224
- </Meeting Notes>
169
+ ```typescript
170
+ @Transition({ from: 'response_received', to: 'notes_optimized' })
171
+ async optimizeNotes() {
172
+ await this.claudeGenerateDocument.call({
173
+ claude: { model: 'claude-sonnet-4-6' },
174
+ response: { id: 'final', document: OptimizedNotesDocument },
175
+ prompt: `Extract all information from the provided meeting notes into the structured document.\n\n<Meeting Notes>\n${this.meetingNotes?.text}\n</Meeting Notes>`,
176
+ });
177
+ }
178
+ ```
179
+
180
+ #### 7. Final Confirmation with Wait
181
+
182
+ Use `@Final` with `wait: true` to create a review step before the workflow ends:
183
+
184
+ ```typescript
185
+ @Final({ from: 'notes_optimized', wait: true, schema: OptimizedMeetingNotesDocumentSchema })
186
+ async confirm(payload: z.infer<typeof OptimizedMeetingNotesDocumentSchema>) {
187
+ const result = await this.repository.save(OptimizedNotesDocument, payload, { id: 'final' });
188
+ this.optimizedNotes = result.content as z.infer<typeof OptimizedMeetingNotesDocumentSchema>;
189
+ }
225
190
  ```
226
191
 
227
192
  ## Dependencies
228
193
 
229
194
  This workflow uses the following Loopstack modules:
230
195
 
231
- - `@loopstack/core` - Core framework functionality
232
- - `@loopstack/core` - Provides `CreateDocument` tool
233
- - `@loopstack/ai-module` - Provides `AiGenerateDocument` tool
196
+ - `@loopstack/common` - Core framework decorators (`BaseWorkflow`, `@Workflow`, `@Initial`, `@Transition`, `@Final`, `@InjectTool`, `Document`)
197
+ - `@loopstack/claude-module` - Provides `ClaudeGenerateDocument` tool for AI-powered document generation
234
198
 
235
199
  ## About
236
200
 
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "summary",
10
10
  "workflow"
11
11
  ],
12
- "version": "0.21.0",
12
+ "version": "0.21.1",
13
13
  "license": "Apache-2.0",
14
14
  "author": {
15
15
  "name": "Jakob Klippel",