LetsFlow
Search…
Scenario
A Live Contract scenario is a definition of procedure as a Finite State Machine (FSM). As an FSM, the scenario can be visualized as flowchart and instantiated as a process.

Workflow

A workflow consists of an orchestrated and repeatable pattern of business activity.
A scenario is composed of a set of states and actions. An action can be executed by an actors which may trigger a state change.
The scenario can be instantiated to create a process. A scenario is stateless whereas a process is stateful. Stateful means that the computer or program keeps track of the state of interaction. Stateless means that there is no record of previous interactions.
The scenario may be defined in YAML, which is better readable. The workflow service only accepts JSON, but the LTO client libraries can convert this.

Golden flow

Each state MAY define a default action and each action MUST define a default response. Following these defaults results in the golden flow.
Omit a default action to wait for the timeout by default.

Implicit states

Scenarios have a number of implicit states. Except for :initial, these don't need to be defined in the scenario. You may define these not the less to set things like descriptions.
Initial state
The state with key :initial is the initial state of the FSM.
Success state
The :success state is an end state indicating that the process has been completed successfully.

Cancelled state

The :cancelled state an end state indicating that the process has been cancelled by one of the actors.
Failed state
The :failed state is an end state indicating that the process has ended because of an error or other unexpected problem.

Example

In this scenario a supplier provides a quotation for a client to accept. The process can be started either by the client or by the supplier.
If the client starts the process, the golden flow is
  1. 1.
    Client selects the supplier and describes the service he would like a quotation for
  2. 2.
    Client invites the supplier to participate in the process
  3. 3.
    Supplier uploads a quote (due date depends on urgency)
  4. 4.
    Client accepts the quote
  5. 5.
    done
If the supplier starts the process, the golden flow is
  1. 1.
    Supplier enters the client information
  2. 2.
    Supplier uploads a quote
  3. 3.
    Supplier invites the client to participate in the process
  4. 4.
    Client accepts the quote
  5. 5.
    done
YAML
JSON
JSON (full)
1
schema: https://specs.letsflow.io/v0.3.0/scenario#
2
id: JKdf3jddfklsr834s312
3
title: Product quotation
4
description: Send a quotation requested by the client
5
6
actors:
7
supplier:
8
$ref: "https://workflow.example.com/actors/organization/schema.json#"
9
client:
10
$ref: "https://workflow.example.com/actors/individual/schema.json#"
11
12
assets:
13
request:
14
type: object
15
properties:
16
description:
17
type: string
18
urgency:
19
type: string
20
enum:
21
- normal
22
- high
23
- critical
24
quotation:
25
type: object
26
properties:
27
title:
28
type: string
29
url:
30
type: string
31
32
definitions:
33
request_form:
34
title: Quotation request form
35
definition:
36
- fields:
37
- type: external-select
38
label: Supplier
39
name: supplier
40
url: https://jsonplaceholder.typicode.com/users
41
optionText: name
42
optionValue: "{ name, email, phone }"
43
required: true
44
- type: textarea
45
label: Description
46
name: description
47
helptip: Which service would you like a quotation for?
48
- type: select
49
label: Urgency
50
name: urgency
51
options:
52
- value: normal
53
label: Normal
54
- value: high
55
label: High
56
- value: critical
57
label: Critical
58
client_form:
59
title: Enter client information
60
definition:
61
- fields:
62
- type: text
63
label: Name
64
name: name
65
required: true
66
- type: email
67
label: E-mail
68
name: email
69
required: true
70
71
actions:
72
comment:
73
$schema: "http://workflow.example.com/actions/comment/schema.json#"
74
actor: (any)
75
request_quotation:
76
$schema: "http://workflow.example.com/actions/form/schema.json#"
77
actor: client
78
title: Quote requested by client
79
form: !ref definitions.request_form
80
update:
81
- select: assets.request
82
- select: assets.supplier
83
transform: supplier
84
invite_supplier:
85
$schema: "http://workflow.example.com/actions/invite/schema.json#"
86
actor: client
87
invite: supplier
88
responses:
89
ok:
90
display: never
91
error:
92
display: always
93
title: Failed to invite the supplier
94
data: !ref response.data.message
95
enter_client:
96
$schema: "http://workflow.example.com/actions/form/schema.json#"
97
actor: supplier
98
form: !ref definitions.client_form
99
display: never
100
update:
101
select: actors.client
102
invite_client:
103
$schema: "http://workflow.example.com/actions/invite/schema.json#"
104
actor: supplier
105
invite: client
106
responses:
107
ok:
108
display: never
109
error:
110
display: always
111
title: Failed to invite the supplier
112
description: !ref response.data.message
113
upload:
114
$schema: "http://workflow.example.com/actions/upload/schema.json#"
115
actor: supplier
116
accept: application/pdf
117
responses:
118
ok:
119
title: Provided a quotation
120
update:
121
select: assets.quotation
122
error:
123
label: An error occurred when uploading the quotation
124
display: once
125
review:
126
$schema: "http://workflow.example.com/actions/review/schema.json#"
127
actor: client
128
document: !ref assets.quotation
129
responses:
130
accept:
131
label: Accept
132
title: Accepted quotation
133
reject:
134
label: Reject
135
title: Rejected quotation
136
default_response: accept
137
138
states:
139
(any):
140
transitions:
141
- on: comment
142
goto: (current)
143
initial:
144
transitions:
145
- on: request_quotation
146
goto: invite_supplier
147
- on: enter_client
148
goto: provide_quote
149
invite_supplier:
150
transitions:
151
- on: invite_supplier.ok
152
goto: wait_for_quote
153
- on: invite_supplier.error
154
goto: (failed)
155
invite_client:
156
transitions:
157
- on: invite_client.ok
158
goto: wait_for_review
159
wait_for_quote:
160
title: Prepare quotation
161
instructions:
162
supplier: !tpl "{{ assets.request.description }} ({{ assets.request.urgency }} urgency)"
163
transitions:
164
- on: upload.ok
165
goto: wait_for_review
166
- on: upload.error
167
goto: (current)
168
provide_quote:
169
title: Provide quotation
170
transitions:
171
- on: upload.ok
172
goto: wait_for_review
173
- on: upload.error
174
goto: (current)
175
wait_for_review:
176
title: Review quotation
177
instructions:
178
client: Please review and accept the quotation
179
supplier: Please wait for the client to review the quotation.
180
transitions:
181
- on: review.accept
182
transition: (success)
183
- on: review.reject
184
transition: (cancelled)
Copied!
1
{
2
"$schema": "https://specs.letsflow.io/v0.2.0/scenario/schema.json#",
3
"id": "JKdf3jddfklsr834s312",
4
"title": "Product quotation",
5
"description": "Send a quotation requested by the client",
6
"actors": {
7
"supplier": {
8
"$ref": "https://specs.letsflow.io/v0.2.0/actor/schema.json#organization"
9
},
10
"client": {
11
"$ref": "https://specs.letsflow.io/v0.2.0/actor/schema.json#individual"
12
}
13
},
14
"assets": {
15
"request": {
16
"type": "object",
17
"properties": {
18
"description": {
19
"type": "string"
20
},
21
"urgency": {
22
"type": "string",
23
"enum": [
24
"normal",
25
"high",
26
"critical"
27
]
28
}
29
}
30
},
31
"quotation": {
32
"type": "object",
33
"properties": {
34
"title": {
35
"type": "string"
36
},
37
"url": {
38
"type": "string"
39
}
40
}
41
}
42
},
43
"definitions": {
44
"request_form": {
45
"title": "Quotation request form",
46
"definition": [
47
{
48
"fields": [
49
{
50
"type": "external-select",
51
"label": "Supplier",
52
"name": "supplier",
53
"url": "https://jsonplaceholder.typicode.com/users",
54
"optionText": "name",
55
"optionValue": "{ name, email, phone }",
56
"required": true
57
},
58
{
59
"type": "textarea",
60
"label": "Description",
61
"name": "description",
62
"helptip": "Which service would you like a quotation for?"
63
},
64
{
65
"type": "select",
66
"label": "Urgency",
67
"name": "urgency",
68
"options": [
69
{
70
"value": "normal",
71
"label": "Normal"
72
},
73
{
74
"value": "high",
75
"label": "High"
76
},
77
{
78
"value": "critical",
79
"label": "Critical"
80
}
81
]
82
}
83
]
84
}
85
]
86
},
87
"client_form": {
88
"title": "Enter client information",
89
"definition": [
90
{
91
"fields": [
92
{
93
"type": "text",
94
"label": "Name",
95
"name": "name",
96
"required": true
97
},
98
{
99
"type": "email",
100
"label": "E-mail",
101
"name": "email",
102
"required": true
103
}
104
]
105
}
106
]
107
}
108
},
109
"actions": {
110
"request_quotation": {
111
"$schema": "http://workflow.example.com/actions/form/schema.json",
112
"actor": "client",
113
"title": "Quote requested by client",
114
"form": { "<ref>": "definitions.request_form" },
115
"update": [
116
{
117
"select": "assets.request"
118
},
119
{
120
"select": "assets.supplier",
121
"transform": "supplier"
122
}
123
]
124
},
125
"invite_supplier": {
126
"$schema": "http://workflow.example.com/actions/invite/schema.json",
127
"actor": "client",
128
"invite": "supplier",
129
"responses": {
130
"ok": {
131
"display": "never"
132
},
133
"error": {
134
"display": "always",
135
"title": "Failed to invite the supplier",
136
"data": "response.data.message"
137
}
138
}
139
},
140
"enter_client": {
141
"$schema": "http://workflow.example.com/actions/form/schema.json",
142
"actor": "supplier",
143
"form": { "<ref>": "definitions.client_form" },
144
"display": "never",
145
"update": {
146
"select": "actors.client"
147
}
148
},
149
"invite_client": {
150
"$schema": "http://workflow.example.com/actions/invite/schema.json",
151
"actor": "supplier",
152
"invite": "client",
153
"responses": {
154
"ok": {
155
"display": "never"
156
},
157
"error": {
158
"display": "always",
159
"title": "Failed to invite the supplier",
160
"description": {
161
"<ref>": "response.data.message"
162
}
163
}
164
}
165
},
166
"upload": {
167
"$schema": "http://workflow.example.com/actions/upload/schema.json",
168
"actor": "supplier",
169
"accept": "application/pdf",
170
"responses": {
171
"ok": {
172
"title": "Provided a quotation",
173
"update": {
174
"select": "assets.quotation"
175
}
176
},
177
"error": {
178
"label": "An error occurred when uploading the quotation",
179
"display": "once"
180
}
181
}
182
},
183
"review": {
184
"$schema": "http://workflow.example.com/actions/review/schema.json",
185
"actor": "client",
186
"document": "assets.quotation",
187
"responses": {
188
"accept": {
189
"label": "Accept",
190
"title": "Accepted quotation"
191
},
192
"reject": {
193
"label": "Reject",
194
"title": "Rejected quotation"
195
}
196
},
197
"default_response": "accept"
198
}
199
},
200
"states": {
201
":initial": {
202
"actions": [
203
"request_quotation",
204
"enter_client"
205
],
206
"transitions": [
207
{
208
"action": "request_quotation",
209
"transition": "invite_supplier"
210
},
211
{
212
"action": "enter_client",
213
"transition": "provide_quote"
214
}
215
]
216
},
217
"invite_supplier": {
218
"action": "invite_supplier",
219
"transitions": [
220
{
221
"response": "ok",
222
"transition": "wait_for_quote"
223
},
224
{
225
"response": "error",
226
"transition": ":failed"
227
}
228
]
229
},
230
"invite_client": {
231
"action": "invite_client",
232
"transitions": [
233
{
234
"response": "ok",
235
"transition": "wait_for_review"
236
}
237
]
238
},
239
"wait_for_quote": {
240
"title": "Prepare quotation",
241
"instructions": {
242
"supplier": { "<tpl>": "{{ assets.request.description }} ({{ assets.request.urgency }} urgency)" }
243
},
244
"action": "upload",
245
"transitions": [
246
{
247
"response": "ok",
248
"transition": "wait_for_review"
249
}
250
]
251
},
252
"provide_quote": {
253
"title": "Provide quotation",
254
"action": "upload",
255
"transitions": [
256
{
257
"response": "ok",
258
"transition": "invite_client"
259
}
260
]
261
},
262
"wait_for_review": {
263
"title": "Review quotation",
264
"instructions": {
265
"client": "Please review and accept the quotation",
266
"supplier": "Please wait for the client to review the quotation."
267
},
268
"action": "review",
269
"transitions": [
270
{
271
"response": "accept",
272
"transition": ":success"
273
},
274
{
275
"response": "reject",
276
"transition": ":cancelled"
277
}
278
]
279
}
280
}
281
}
Copied!
1
{
2
"$schema": "https://specs.letsflow.io/v0.1.0/scenario/schema.json#",
3
"id": "JKdf3jddfklsr834s312",
4
"title": "Product quotation",
5
"description": "Send a quotation requested by the client",
6
"actors": {
7
"supplier": {
8
"$ref": "https://specs.letsflow.io/v0.1.0/actor/schema.json#organization"
9
},
10
"client": {
11
"$ref": "https://specs.letsflow.io/v0.1.0/actor/schema.json#individual"
12
}
13
},
14
"assets": {
15
"request": {
16
"type": "object",
17
"properties": {
18
"description": {
19
"type": "string"
20
},
21
"urgency": {
22
"type": "string",
23
"enum": ["normal", "high", "critical"]
24
}
25
}
26
},
27
"quotation": {
28
"$ref": "https://specs.letsflow.io/v0.1.0/document/schema.json#"
29
}
30
},
31
"definitions": {
32
"request_form": {
33
"title": "Quotation request form",
34
"definition": [{
35
"fields": [{
36
"$schema": "http://specs.legalthings.one/draft-01/form/schema.json#external-select",
37
"label": "Supplier",
38
"name": "supplier",
39
"url": "https://jsonplaceholder.typicode.com/users",
40
"optionText": "name",
41
"optionValue": "{ name, email, phone }",
42
"required": true
43
},
44
{
45
"$schema": "http://specs.legalthings.one/draft-01/form/schema.json#textarea",
46
"label": "Description",
47
"name": "description",
48
"helptip": "Which service would you like a quotation for?"
49
},
50
{
51
"$schema": "http://specs.legalthings.one/draft-01/form/schema.json#select",
52
"label": "Urgency",
53
"name": "urgency",
54
"options": [{
55
"value": "normal",
56
"label": "Normal"
57
},
58
{
59
"value": "high",
60
"label": "High"
61
},
62
{
63
"value": "critical",
64
"label": "Critical"
65
}
66
]
67
}
68
]
69
}]
70
},
71
"client_form": {
72
"title": "Enter client information",
73
"definition": [{
74
"fields": [{
75
"$schema": "http://specs.legalthings.one/draft-01/form/schema.json#text",
76
"label": "Name",
77
"name": "name",
78
"required": true
79
},
80
{
81
"$schema": "http://specs.legalthings.one/draft-01/form/schema.json#email",
82
"label": "E-mail",
83
"name": "email",
84
"required": true
85
}
86
]
87
}]
88
}
89
},
90
"actions": {
91
"request_quotation": {
92
"$schema": "http://specs.legalthings.one/draft-01/action/schema.json#form-action",
93
"actor": "client",
94
"form": {
95
"<ref>": "definitions.request_form"
96
},
97
"responses": {
98
"ok": {
99
"title": "Quote quested by client"
100
}
101
}
102
},
103
"invite_supplier": {
104
"$schema": "http://specs.legalthings.one/draft-01/action/schema.json#invite-action",
105
"actor": "client",
106
"invite": "supplier",
107
"responses": {
108
"ok": {
109
"display": "never"
110
},
111
"error": {
112
"display": "always",
113
"title": "Failed to invite the supplier",
114
"description": {
115
"<ref>": "response.data.message"
116
}
117
}
118
}
119
},
120
"enter_client": {
121
"$schema": "http://specs.legalthings.one/draft-01/scenario/schema.json#form-action",
122
"actor": "supplier",
123
"form": {
124
"<ref>": "definitions.request_form"
125
},
126
"responses": {
127
"ok": {
128
"display": "never",
129
"update": {
130
"select": "actors.client"
131
}
132
}
133
}
134
},
135
"invite_client": {
136
"$schema": "http://specs.legalthings.one/draft-01/scenario/schema.json#invite-action",
137
"actor": "supplier",
138
"invite": "client",
139
"responses": {
140
"ok": {
141
"display": "never"
142
},
143
"error": {
144
"display": "always",
145
"title": "Failed to invite the supplier",
146
"description": {
147
"<ref>": "response.data.message"
148
}
149
}
150
}
151
},
152
"upload": {
153
"$schema": "http://specs.legalthings.one/draft-01/scenario/schema.json#upload-action",
154
"actor": "supplier",
155
"label": "Upload",
156
"accept": "application/pdf",
157
"responses": {
158
"ok": {
159
"title": "Uploaded quotation",
160
"update": {
161
"select": "assets.quotation",
162
"data": {
163
"$schema": "https://specs.letsflow.io/v0.1.0/document/schema.json#",
164
"name": {
165
"<tpl>": "Quotation {{ actors.client.name }} {{ response.date }}"
166
},
167
"date": {
168
"<ref>": "response.date"
169
},
170
"content_media_type": {
171
"<ref>": "response.data.media_type"
172
},
173
"content_encoding": {
174
"<ref>": "response.data.encoding"
175
},
176
"content": {
177
"<ref>": "response.data.content"
178
}
179
}
180
}
181
},
182
"error": {
183
"label": "An error occurred when uploading the quotation",
184
"display": "once"
185
}
186
}
187
},
188
"review": {
189
"$schema": "http://specs.legalthings.one/draft-01/action/schema.json#review",
190
"actor": "client",
191
"document": {
192
"<ref>": "assets.quotation"
193
},
194
"responses": {
195
"accept": {
196
"label": "Accept",
197
"title": "Accepted quotation"
198
},
199
"reject": {
200
"label": "Reject",
201
"title": "Rejected quotation"
202
}
203
},
204
"default_response": "approve"
205
},
206
"cancel": {
207
"$schema": "http://specs.legalthings.one/draft-01/action/schema.json#choose",
208
"actor": ["client", "supplier"],
209
"responses": {
210
"ok": {
211
"label": "Cancel",
212
"title": "Quotation withdrawn",
213
"transition": ":failed"
214
}
215
}
216
}
217
},
218
"states": {
219
":initial": {
220
"actions": ["request_quotation", "enter_client"],
221
"transitions": [{
222
"action": "request_quotation",
223
"transition": "invite_supplier"
224
},
225
{
226
"action": "enter_client",
227
"transition": "provide_quote"
228
}
229
]
230
},
231
"invite_supplier": {
232
"title": "Waiting on the supplier to participate in this process",
233
"actions": ["invite_supplier", "cancel"],
234
"default_action": "invite_supplier",
235
"transitions": [{
236
"action": "invite_supplier",
237
"response": "ok",
238
"transition": "wait_for_quote"
239
}]
240
},
241
"provide_quote": {
242
"title": "Prepare quotation",
243
"actions": ["upload", "cancel"],
244
"default_action": "upload",
245
"transitions": [{
246
"action": "upload",
247
"response": "ok",
248
"transition": "invite_client"
249
}]
250
},
251
"invite_client": {
252
"title": "Waiting on the client to participate in this process",
253
"actions": ["invite_client", "cancel"],
254
"default_action": "invite_client",
255
"transitions": [{
256
"action": "invite_client",
257
"response": "ok",
258
"transition": "wait_for_review"
259
}]
260
},
261
"wait_for_quote": {
262
"title": "Prepare quotation",
263
"instructions": {
264
"supplier": {
265
"<tpl>": "{{ assets.request.description }} ({{ assets.request.urgency }} urgency)"
266
}
267
},
268
"actions": ["upload", "cancel"],
269
"default_action": "upload",
270
"transitions": [{
271
"action": "upload",
272
"response": "ok",
273
"transition": "wait_for_review"
274
}],
275
"timeout": {
276
"<switch>": {
277
"on": {
278
"<ref>": "assets.request.urgency"
279
},
280
"options": {
281
"normal": "3b",
282
"high": "1b",
283
"critical": "6h"
284
}
285
}
286
}
287
},
288
"wait_for_review": {
289
"title": "Review quotation",
290
"instructions": {
291
"client": "Please review and accept the quotation",
292
"supplier": "Please wait for the client to review the quotation."
293
},
294
"actions": ["review", "cancel"],
295
"default_action": "review",
296
"timeout": "7d",
297
"transitions": [{
298
"action": "review",
299
"response": "accept",
300
"transition": ":success"
301
},
302
{
303
"action": "review",
304
"response": "deny",
305
"transition": ":failed"
306
}
307
]
308
}
309
}
310
}
Copied!

Scenario schema

https://specs.letsflow.io/v0.3.0/scenario#

schema (or $schema)

The Live Contracts Scenario JSON schema URI that describes the JSON structure of the scenario.

id

A unique identifier. If the scenario is part of a Live Contract, this must be resource id that's valid for the event chain.
The id MUST point to an immutable version of the scenario. Modifying the scenario SHOULD always result in a new id. Previous versions of the scenario SHOULD remain available.

title

The title of the scenario.

description

A description of the procedure shown as scenario details.

actors

Object with JSON Schema, defining the properties for each actor. The keys of the object is used to reference the actor. The actor schema must define an object.
Read more

assets

Object with JSON schema, defining the properties for each asset. The keys of the object is used to reference the asset. The asset schema must define an object.
Read more

definitions

An object with constant values and predefined objects. This can be used to define things needed in multiple actions and/or states.
Even if it's only used in a single action or state, using definitions helps to keep actions and states small and readable.
Read more

actions

Set of the actions of the scenario. The keys of the object are used as reference of the action.
Read more

states

Set of all states of the scenario. The keys of the object are used as reference of the state.
Read more
Last modified 2yr ago