diff --git a/README.md b/README.md
index bbab84db..a415b4b1 100644
--- a/README.md
+++ b/README.md
@@ -109,8 +109,11 @@ It is a member project of the [CNCF Serverless Working Group](https://github.com
## Documentation
The documentation for Serverless Workflow includes:
+
- [**DSL**](dsl.md): Documents the fundamentals aspects and concepts of the Serverless Workflow DSL
- [**DSL Reference**](dsl-reference.md): References all the definitions used by the Serverless Workflow DSL
+- [**Examples**](./examples/README.md): A collection of practical examples demonstrating specific features and functionalities of Serverless Workflow.
+- [**Use Cases**](./use-cases/README.md): Detailed use cases illustrating how Serverless Workflow can be applied in various real-world scenarios.
## Community
diff --git a/dsl-reference.md b/dsl-reference.md
index 9f55bd75..68b3346b 100644
--- a/dsl-reference.md
+++ b/dsl-reference.md
@@ -1451,7 +1451,7 @@ Defines the [Problem Details RFC](https://datatracker.ietf.org/doc/html/rfc7807)
|----------|:----:|:--------:|-------------|
| type | [`uri-template`](#uri-template) | `yes` | A URI reference that identifies the [`error`](#error) type.
For cross-compatibility concerns, it is strongly recommended to use [Standard Error Types](#standard-error-types) whenever possible.
Runtimes **MUST** ensure that the property has been set when raising or escalating the [`error`](#error). |
| status | `integer` | `yes` | The status code generated by the origin for this occurrence of the [`error`](#error).
For cross-compatibility concerns, it is strongly recommended to use [HTTP Status Codes](https://datatracker.ietf.org/doc/html/rfc7231#section-6) whenever possible.
Runtimes **MUST** ensure that the property has been set when raising or escalating the [`error`](#error). |
-| instance | `string` | `yes` | A [JSON Pointer](https://datatracker.ietf.org/doc/html/rfc6901) used to reference the component the [`error`](#error) originates from.
Runtimes **MUST** set the property when raising or escalating the [`error`](#error). Otherwise ignore. |
+| instance | `string` | `no` | A [JSON Pointer](https://datatracker.ietf.org/doc/html/rfc6901) used to reference the component the [`error`](#error) originates from.
Runtimes **MUST** set the property when raising or escalating the [`error`](#error). Otherwise ignore. |
| title | `string` | `no` | A short, human-readable summary of the [`error`](#error). |
| detail | `string` | `no` | A human-readable explanation specific to this occurrence of the [`error`](#error). |
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 00000000..de9599a0
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,11 @@
+# Examples
+
+Welcome to the Serverless Workflow Examples directory! This section contains a collection of brief YAML files, each representing a single workflow definition.
+
+These examples are designed to demonstrate specific features and functionalities of the Serverless Workflow DSL. They serve as a practical reference to help you understand and implement different aspects of Serverless Workflows in your projects.
+
+## Contributing
+
+We welcome contributions! If you have an example demonstrating a unique feature or use case of Serverless Workflow, feel free to submit a pull request.
+
+For more detailed information on contributing, including guidelines and best practices, please refer to our [Contributing Guide](./CONTRIBUTING.md).
\ No newline at end of file
diff --git a/examples/bearer-auth.yaml b/examples/authentication-bearer-uri-format.yaml
similarity index 100%
rename from examples/bearer-auth.yaml
rename to examples/authentication-bearer-uri-format.yaml
diff --git a/examples/bearer-auth-uri-format.yaml b/examples/authentication-bearer.yaml
similarity index 89%
rename from examples/bearer-auth-uri-format.yaml
rename to examples/authentication-bearer.yaml
index 44149c0b..18d92074 100644
--- a/examples/bearer-auth-uri-format.yaml
+++ b/examples/authentication-bearer.yaml
@@ -12,4 +12,4 @@ do:
uri: https://petstore.swagger.io/v2/pet/1
authentication:
bearer:
- token: ${ .token }
+ token: ${ .token }
\ No newline at end of file
diff --git a/examples/oauth2.yaml b/examples/authentication-oauth2.yaml
similarity index 100%
rename from examples/oauth2.yaml
rename to examples/authentication-oauth2.yaml
diff --git a/examples/oidc.yaml b/examples/authentication-oidc.yaml
similarity index 100%
rename from examples/oidc.yaml
rename to examples/authentication-oidc.yaml
diff --git a/examples/use-authentication.yaml b/examples/authentication-reusable.yaml
similarity index 100%
rename from examples/use-authentication.yaml
rename to examples/authentication-reusable.yaml
diff --git a/examples/asyncapi.yaml b/examples/call-asyncapi.yaml
similarity index 100%
rename from examples/asyncapi.yaml
rename to examples/call-asyncapi.yaml
diff --git a/examples/call-custom-function-cataloged.yaml b/examples/call-custom-function-cataloged.yaml
new file mode 100644
index 00000000..7e6c2180
--- /dev/null
+++ b/examples/call-custom-function-cataloged.yaml
@@ -0,0 +1,13 @@
+document:
+ dsl: '1.0.0'
+ namespace: samples
+ name: call-custom-function-cataloged
+ version: '1.0.0'
+do:
+ - log:
+ call: https://raw.githubusercontent.com/serverlessworkflow/catalog/main/functions/log/1.0.0/function.yaml
+ with:
+ message: Hello, world!
+ level: information
+ timestamp: true
+ format: '{TIMESTAMP} [{LEVEL}] ({CONTEXT}): {MESSAGE}'
\ No newline at end of file
diff --git a/examples/call-custom-function-inline.yaml b/examples/call-custom-function-inline.yaml
new file mode 100644
index 00000000..dde1c452
--- /dev/null
+++ b/examples/call-custom-function-inline.yaml
@@ -0,0 +1,25 @@
+document:
+ dsl: '1.0.0'
+ namespace: samples
+ name: call-custom-function-inline
+ version: '1.0.0'
+use:
+ functions:
+ getPetById:
+ input:
+ schema:
+ document:
+ type: object
+ properties:
+ petId:
+ type: string
+ required: [ petId ]
+ call: http
+ with:
+ method: get
+ endpoint: https://petstore.swagger.io/v2/pet/{petId}
+do:
+ - getPet:
+ call: getPetById
+ with:
+ petId: 69
\ No newline at end of file
diff --git a/examples/call-grpc.yaml b/examples/call-grpc.yaml
new file mode 100644
index 00000000..03604aed
--- /dev/null
+++ b/examples/call-grpc.yaml
@@ -0,0 +1,18 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: grpc-example
+ version: '0.1.0'
+do:
+ - greet:
+ call: grpc
+ with:
+ proto:
+ endpoint: file://app/greet.proto
+ service:
+ name: GreeterApi.Greeter
+ host: localhost
+ port: 5011
+ method: SayHello
+ arguments:
+ name: ${ .user.preferredDisplayName }
\ No newline at end of file
diff --git a/examples/call-http-shorthand-endpoint.yaml b/examples/call-http-endpoint-interpolation-shorthand.yaml
similarity index 100%
rename from examples/call-http-shorthand-endpoint.yaml
rename to examples/call-http-endpoint-interpolation-shorthand.yaml
diff --git a/examples/call-http-endpoint-interpolation.yaml b/examples/call-http-endpoint-interpolation.yaml
new file mode 100644
index 00000000..4c3cc594
--- /dev/null
+++ b/examples/call-http-endpoint-interpolation.yaml
@@ -0,0 +1,11 @@
+document:
+ dsl: 1.0.0-alpha1
+ namespace: examples
+ name: call-http-shorthand-endpoint
+ version: 1.0.0-alpha1
+do:
+ - getPet:
+ call: http
+ with:
+ method: get
+ endpoint: ${ "https://petstore.swagger.io/v2/pet/\(.petId)" }
\ No newline at end of file
diff --git a/examples/http-query-params.yaml b/examples/call-http-query-parameters.yaml
similarity index 100%
rename from examples/http-query-params.yaml
rename to examples/call-http-query-parameters.yaml
diff --git a/examples/call-openapi.yaml b/examples/call-openapi.yaml
new file mode 100644
index 00000000..4b129513
--- /dev/null
+++ b/examples/call-openapi.yaml
@@ -0,0 +1,14 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: openapi-example
+ version: '0.1.0'
+do:
+ - findPet:
+ call: openapi
+ with:
+ document:
+ endpoint: https://petstore.swagger.io/v2/swagger.json
+ operationId: findPetsByStatus
+ parameters:
+ status: available
\ No newline at end of file
diff --git a/examples/conditional-task.yaml b/examples/conditional-task.yaml
new file mode 100644
index 00000000..b341a7ed
--- /dev/null
+++ b/examples/conditional-task.yaml
@@ -0,0 +1,22 @@
+document:
+ dsl: '1.0.0'
+ namespace: default
+ name: conditional-task
+ version: '1.0.0'
+do:
+ - raiseErrorIfUnderage:
+ if: .customer.age < 18
+ raise:
+ error:
+ type: https://superbet-casinos.com/customer/access-forbidden
+ status: 400
+ title: Access Forbidden
+ then: end
+ - placeBet:
+ call: http
+ with:
+ method: post
+ endpoint: https://superbet-casinos.com/api/bet/on/football
+ body:
+ customer: .customer
+ bet: .bet
\ No newline at end of file
diff --git a/examples/do-multiple.yaml b/examples/do-multiple.yaml
new file mode 100644
index 00000000..d0c5e154
--- /dev/null
+++ b/examples/do-multiple.yaml
@@ -0,0 +1,17 @@
+document:
+ dsl: 1.0.0-alpha1
+ namespace: examples
+ name: call-http-shorthand-endpoint
+ version: 1.0.0-alpha1
+do:
+ - getPet:
+ call: http
+ with:
+ method: get
+ endpoint: https://petstore.swagger.io/v2/pet/{petId}
+ - buyPet:
+ call: http
+ with:
+ method: put
+ endpoint: https://petstore.swagger.io/v2/pet/{petId}
+ body: '${ . + { status: "sold" } }'
diff --git a/examples/emit.yaml b/examples/emit.yaml
new file mode 100644
index 00000000..4543e846
--- /dev/null
+++ b/examples/emit.yaml
@@ -0,0 +1,19 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: emit
+ version: '0.1.0'
+do:
+ - emitEvent:
+ emit:
+ event:
+ with:
+ source: https://petstore.com
+ type: com.petstore.order.placed.v1
+ data:
+ client:
+ firstName: Cruella
+ lastName: de Vil
+ items:
+ - breed: dalmatian
+ quantity: 101
\ No newline at end of file
diff --git a/examples/for.yaml b/examples/for.yaml
new file mode 100644
index 00000000..3e3b2f72
--- /dev/null
+++ b/examples/for.yaml
@@ -0,0 +1,21 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: for-example
+ version: '0.1.0'
+do:
+ - checkup:
+ for:
+ each: pet
+ in: .pets
+ at: index
+ while: .vet != null
+ do:
+ - waitForCheckup:
+ listen:
+ to:
+ one:
+ with:
+ type: com.fake.petclinic.pets.checkup.completed.v2
+ output:
+ as: '.pets + [{ "id": $pet.id }]'
\ No newline at end of file
diff --git a/examples/fork.yaml b/examples/fork.yaml
new file mode 100644
index 00000000..fcd9c63e
--- /dev/null
+++ b/examples/fork.yaml
@@ -0,0 +1,26 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: fork-example
+ version: '0.1.0'
+do:
+ - raiseAlarm:
+ fork:
+ compete: true
+ branches:
+ - callNurse:
+ call: http
+ with:
+ method: put
+ endpoint: https://fake-hospital.com/api/v3/alert/nurses
+ body:
+ patientId: ${ .patient.fullName }
+ room: ${ .room.number }
+ - callDoctor:
+ call: http
+ with:
+ method: put
+ endpoint: https://fake-hospital.com/api/v3/alert/doctor
+ body:
+ patientId: ${ .patient.fullName }
+ room: ${ .room.number }
\ No newline at end of file
diff --git a/examples/listen-to-all.yaml b/examples/listen-to-all.yaml
new file mode 100644
index 00000000..859a978b
--- /dev/null
+++ b/examples/listen-to-all.yaml
@@ -0,0 +1,16 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: listen-to-all
+ version: '0.1.0'
+do:
+ - callDoctor:
+ listen:
+ to:
+ all:
+ - with:
+ type: com.fake-hospital.vitals.measurements.temperature
+ data: ${ .temperature > 38 }
+ - with:
+ type: com.fake-hospital.vitals.measurements.bpm
+ data: ${ .bpm < 60 or .bpm > 100 }
\ No newline at end of file
diff --git a/examples/listen-to-any.yaml b/examples/listen-to-any.yaml
new file mode 100644
index 00000000..a842f0da
--- /dev/null
+++ b/examples/listen-to-any.yaml
@@ -0,0 +1,16 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: listen-to-any
+ version: '0.1.0'
+do:
+ - callDoctor:
+ listen:
+ to:
+ any:
+ - with:
+ type: com.fake-hospital.vitals.measurements.temperature
+ data: ${ .temperature > 38 }
+ - with:
+ type: com.fake-hospital.vitals.measurements.bpm
+ data: ${ .bpm < 60 or .bpm > 100 }
\ No newline at end of file
diff --git a/examples/listen-to-one.yaml b/examples/listen-to-one.yaml
new file mode 100644
index 00000000..c2e9e45b
--- /dev/null
+++ b/examples/listen-to-one.yaml
@@ -0,0 +1,18 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: listen-to-one
+ version: '0.1.0'
+do:
+ - waitForStartup:
+ listen:
+ to:
+ one:
+ with:
+ type: com.virtual-wf-powered-race.events.race.started.v1
+ - startup:
+ call: http
+ with:
+ method: post
+ endpoint:
+ uri: https://virtual-wf-powered-race.com/api/v4/cars/{carId}/start
\ No newline at end of file
diff --git a/examples/raise.yaml b/examples/raise.yaml
new file mode 100644
index 00000000..7f16bc1c
--- /dev/null
+++ b/examples/raise.yaml
@@ -0,0 +1,13 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: raise-not-implemented
+ version: '0.1.0'
+do:
+ - notImplemented:
+ raise:
+ error:
+ type: https://serverlessworkflow.io/errors/not-implemented
+ status: 500
+ title: Not Implemented
+ detail: ${ "The workflow '\( $workflow.definition.document.name ):\( $workflow.definition.document.version )' is a work in progress and cannot be run yet" }
\ No newline at end of file
diff --git a/examples/run-container.yaml b/examples/run-container.yaml
new file mode 100644
index 00000000..78b27470
--- /dev/null
+++ b/examples/run-container.yaml
@@ -0,0 +1,10 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: run-container
+ version: '0.1.0'
+do:
+ - runContainer:
+ run:
+ container:
+ image: hello-world
\ No newline at end of file
diff --git a/examples/run-subflow.yaml b/examples/run-subflow.yaml
new file mode 100644
index 00000000..6a96e36f
--- /dev/null
+++ b/examples/run-subflow.yaml
@@ -0,0 +1,14 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: run-subflow
+ version: '0.1.0'
+do:
+ - registerCustomer:
+ run:
+ workflow:
+ namespace: test
+ name: register-customer
+ version: '0.1.0'
+ input:
+ customer: .user
\ No newline at end of file
diff --git a/examples/cron-schedule.yaml b/examples/schedule-cron.yaml
similarity index 100%
rename from examples/cron-schedule.yaml
rename to examples/schedule-cron.yaml
diff --git a/examples/event-driven-schedule.yaml b/examples/schedule-event-driven.yaml
similarity index 100%
rename from examples/event-driven-schedule.yaml
rename to examples/schedule-event-driven.yaml
diff --git a/examples/set.yaml b/examples/set.yaml
new file mode 100644
index 00000000..f983c907
--- /dev/null
+++ b/examples/set.yaml
@@ -0,0 +1,14 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: set
+ version: '0.1.0'
+schedule:
+ on:
+ one:
+ with:
+ type: io.serverlessworkflow.samples.events.trigger.v1
+do:
+ - initialize:
+ set:
+ startEvent: ${ $workflow.input[0] }
\ No newline at end of file
diff --git a/examples/try-catch-retry.yaml b/examples/try-catch-retry.yaml
new file mode 100644
index 00000000..f32de3f0
--- /dev/null
+++ b/examples/try-catch-retry.yaml
@@ -0,0 +1,26 @@
+document:
+ dsl: '1.0.0'
+ namespace: default
+ name: try-catch-retry
+ version: '1.0.0'
+do:
+ - tryGetPet:
+ try:
+ - getPet:
+ call: http
+ with:
+ method: get
+ endpoint: https://petstore.swagger.io/v2/pet/{petId}
+ catch:
+ errors:
+ with:
+ type: https://serverlessworkflow.io.io/dsl/errors/types/communication
+ status: 503
+ retry:
+ delay:
+ seconds: 3
+ backoff:
+ exponential: {}
+ limit:
+ attempt:
+ count: 5
\ No newline at end of file
diff --git a/examples/try-catch-then.yaml b/examples/try-catch-then.yaml
new file mode 100644
index 00000000..a0ca8d3b
--- /dev/null
+++ b/examples/try-catch-then.yaml
@@ -0,0 +1,39 @@
+document:
+ dsl: '1.0.0'
+ namespace: default
+ name: try-catch
+ version: '1.0.0'
+do:
+ - tryGetPet:
+ try:
+ - getPet:
+ call: http
+ with:
+ method: get
+ endpoint: https://petstore.swagger.io/v2/pet/{petId}
+ catch:
+ errors:
+ with:
+ type: https://serverlessworkflow.io.io/dsl/errors/types/communication
+ status: 404
+ as: error
+ do:
+ - notifySupport:
+ emit:
+ event:
+ with:
+ source: https://petstore.swagger.io
+ type: io.swagger.petstore.events.pets.not-found.v1
+ data: ${ $error }
+ - setError:
+ set:
+ error: $error
+ export:
+ as: '$context + { error: $error }'
+ - buyPet:
+ if: $context.error == null
+ call: http
+ with:
+ method: put
+ endpoint: https://petstore.swagger.io/v2/pet/{petId}
+ body: '${ . + { status: "sold" } }'
\ No newline at end of file
diff --git a/examples/try-catch.yaml b/examples/try-catch.yaml
new file mode 100644
index 00000000..b54a7182
--- /dev/null
+++ b/examples/try-catch.yaml
@@ -0,0 +1,18 @@
+document:
+ dsl: '1.0.0'
+ namespace: default
+ name: try-catch
+ version: '1.0.0'
+do:
+ - tryGetPet:
+ try:
+ - getPet:
+ call: http
+ with:
+ method: get
+ endpoint: https://petstore.swagger.io/v2/pet/{petId}
+ catch:
+ errors:
+ with:
+ type: https://serverlessworkflow.io.io/dsl/errors/types/communication
+ status: 404
\ No newline at end of file
diff --git a/examples/wait-duration-inline.yaml b/examples/wait-duration-inline.yaml
new file mode 100644
index 00000000..2dfd2abc
--- /dev/null
+++ b/examples/wait-duration-inline.yaml
@@ -0,0 +1,9 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: wait-duration-inline
+ version: '0.1.0'
+do:
+ - wait30Seconds:
+ wait:
+ seconds: 30
\ No newline at end of file
diff --git a/examples/wait-duration-iso8601.yaml b/examples/wait-duration-iso8601.yaml
new file mode 100644
index 00000000..86bf314a
--- /dev/null
+++ b/examples/wait-duration-iso8601.yaml
@@ -0,0 +1,8 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: wait-duration-8601
+ version: '0.1.0'
+do:
+ - wait30Seconds:
+ wait: PT30S
\ No newline at end of file
diff --git a/schema/workflow.yaml b/schema/workflow.yaml
index 8be7af58..1b47ec76 100644
--- a/schema/workflow.yaml
+++ b/schema/workflow.yaml
@@ -320,7 +320,6 @@ $defs:
title: WithHTTPHeaders
description: A name/value mapping of the headers, if any, of the HTTP request to perform.
body:
- type: object
title: WithHTTPBody
description: The body, if any, of the HTTP request to perform.
query:
@@ -1032,32 +1031,37 @@ $defs:
description: The type of the security token to use.
required: [ token, type ]
duration:
- type: object
- title: Duration
- description: The definition of a duration.
- minProperties: 1
- unevaluatedProperties: false
- properties:
- days:
- type: integer
- title: DurationDays
- description: Number of days, if any.
- hours:
- type: integer
- title: DurationHours
- description: Number of days, if any.
- minutes:
- type: integer
- title: DurationMinutes
- description: Number of minutes, if any.
- seconds:
- type: integer
- title: DurationSeconds
- description: Number of seconds, if any.
- milliseconds:
- type: integer
- title: DurationMilliseconds
- description: Number of milliseconds, if any.
+ oneOf:
+ - type: object
+ minProperties: 1
+ unevaluatedProperties: false
+ properties:
+ days:
+ type: integer
+ title: DurationDays
+ description: Number of days, if any.
+ hours:
+ type: integer
+ title: DurationHours
+ description: Number of days, if any.
+ minutes:
+ type: integer
+ title: DurationMinutes
+ description: Number of minutes, if any.
+ seconds:
+ type: integer
+ title: DurationSeconds
+ description: Number of seconds, if any.
+ milliseconds:
+ type: integer
+ title: DurationMilliseconds
+ description: Number of milliseconds, if any.
+ title: DurationInline
+ description: The inline definition of a duration.
+ - type: string
+ pattern: '^P(?!$)(\d+(?:\.\d+)?Y)?(\d+(?:\.\d+)?M)?(\d+(?:\.\d+)?W)?(\d+(?:\.\d+)?D)?(T(?=\d)(\d+(?:\.\d+)?H)?(\d+(?:\.\d+)?M)?(\d+(?:\.\d+)?S)?)?$'
+ title: DurationExpression
+ description: The ISO 8601 expression of a duration.
error:
type: object
title: Error
@@ -1098,7 +1102,7 @@ $defs:
type: string
title: ErrorDetails
description: A human-readable explanation specific to this occurrence of the error.
- required: [ type, status, instance ]
+ required: [ type, status ]
endpoint:
title: Endpoint
description: Represents an endpoint.
diff --git a/use-cases/README.md b/use-cases/README.md
new file mode 100644
index 00000000..b4f0810c
--- /dev/null
+++ b/use-cases/README.md
@@ -0,0 +1,50 @@
+# Use Cases
+
+This directory contains a collection of high-level use cases that demonstrate the capabilities and potential applications of the Serverless Workflow DSL. Each use case provides insights into how to effectively implement workflows in various scenarios, helping newcomers understand the framework's power and flexibility.
+
+## Purpose
+
+The primary purpose of these use cases is to:
+
+- **Educate Newcomers:** Provide clear examples of utilizing Serverless Workflow DSL for real-world applications.
+- **Inspire Innovation:** Showcase the diverse workflow automation and orchestration possibilities.
+- **Facilitate Best Practices:** Encourage consistent structure and documentation, making it easier to share knowledge and experiences within the community.
+
+## Structure
+
+Each use case in this directory MUST follow a specific structure to ensure clarity and consistency. The structure is as follows:
+
+### File Structure
+
+```
+./my-cool-use-case 👈 The name of the use case. It must be lowercase and contain exclusively alphanumeric characters, except for '-'.
+ /README.md 👈 Documentation of the use case's details and workflow.
+ /diagram.png 👈 Visual representation of the use case workflow (optional).
+ /... 👈 Additional files relevant to the use case documentation.
+```
+
+### Case Structure
+
+#### Overview
+
+- **System:** A brief description of the system involved in the use case.
+- **Actors:** Identify the main participants or roles interacting with the system.
+- **Goals:** Outline the objectives that the use case aims to achieve.
+- **Preconditions:** Any conditions that must be met before the workflow can be executed.
+
+#### Scenario
+
+- **Triggers:** Events that initiate the workflow.
+- **Flow Breakdown:** Detailed step-by-step workflow breakdown, including key actions and decisions made throughout the process.
+- **Visualization:** Optional diagrams or flowcharts that illustrate the workflow's structure and progression.
+- **Example:** A YAML example of the workflow using Serverless Workflow DSL, demonstrating how the concepts discussed are implemented.
+
+#### Conclusion
+
+- A summary of the benefits and insights gained from the use case, reinforcing why Serverless Workflow is a suitable choice for the described scenario.
+
+## Contributing
+
+We invite everyone to submit their own use cases to enrich this directory and help others learn from their experiences.
+
+If you would like to contribute, please refer to the [contributing.md](./contributing.md) for guidelines on how to contribute to the Serverless Workflow project.
\ No newline at end of file
diff --git a/use-cases/automated-data-backup/README.md b/use-cases/automated-data-backup/README.md
new file mode 100644
index 00000000..ed364efa
--- /dev/null
+++ b/use-cases/automated-data-backup/README.md
@@ -0,0 +1,103 @@
+# Use Case: Automated Data Backup
+
+## Overview
+
+### System
+
+This system automates the backup of an SQL Server database and uploads the backup file to a Minio object storage service on a regular schedule. The workflow consists of three main steps: exporting the database to a file, encoding the backup file in Base64 format, and uploading it to the Minio API.
+
+### Actors
+
+- **Database Administrator:** The user who configures and manages the workflow for database backups.
+- **SQL Server:** The database system from which the data is being exported.
+- **Minio Object Storage:** The service used for storing the backup files securely.
+- **Workflow Engine:** Orchestrates the execution of the defined tasks.
+
+### Goals
+
+- **Automated Backups:** To facilitate automated backups of critical database data without manual intervention, ensuring regular data protection.
+- **Data Security:** To ensure backup files are securely uploaded to a reliable storage solution (Minio).
+- **Efficiency:** To streamline the backup process, reducing the time and effort required to perform database backups.
+
+### Preconditions
+
+- The SQL Server instance is accessible from the container environment.
+- The Minio object storage service is running and accessible via the provided endpoint.
+- Necessary permissions and credentials for both SQL Server and Minio are available.
+
+## Scenario
+
+### Triggers
+
+The workflow is triggered automatically based on a cron schedule that executes the backup process daily at midnight.
+
+### Flow Breakdown
+
+1. **Export Database:**
+ - A container runs the `mcr.microsoft.com/mssql-tools` image to back up the specified database to a file located in a mounted volume. The command utilizes environment variables to securely provide the SQL Server connection details and the database name.
+
+2. **Read Backup File:**
+ - Another container, using the Alpine image, reads the backup file from the mounted volume and encodes it in Base64. The Base64 encoded content is then exported for use in the next step.
+
+3. **Upload to Minio:**
+ - An HTTP call is made to the Minio API to upload the Base64 encoded backup file. The request includes the necessary authentication and specifies the content type as `application/octet-stream`.
+
+### Visualization
+
+The following diagram represents the high-level flow of the workflow:
+
+
+
+*Visualization generated by Synapse.*
+
+### Example
+
+```yaml
+document:
+ dsl: 1.0.0-alpha1
+ namespace: default
+ name: sql-export-to-minio
+ version: 0.1.2
+do:
+- exportDatabase:
+ run:
+ container:
+ image: mcr.microsoft.com/mssql-tools
+ command: >
+ /bin/bash -c "sqlcmd -S $SQLSERVER_HOST -U $SQLSERVER_USER -P '$SQLSERVER_PASSWORD' -Q 'BACKUP DATABASE [$DATABASE_NAME] TO DISK = N\'/var/backup/db.bak\'' && echo 'Database backup completed'"
+ volumes:
+ /var/backup: /backup
+ environment:
+ SQLSERVERHOST: sqlserver
+ SQLSERVERUSER: SA
+ SQLSERVERPASSWORD: P@ssw0rd
+ DATABASENAME: YourDatabase
+- readBackupFile:
+ run:
+ container:
+ image: alpine
+ command: >
+ /bin/sh -c "cat /backup/YourDatabase.bak | base64"
+ volumes:
+ /var/backup: /backup
+ export:
+ as: '$context + { base64Backup: . }'
+- uploadToMinio:
+ call: http
+ with:
+ method: put
+ endpoint:
+ uri: https://minio.example.com/backups/db.bak
+ authentication:
+ bearer:
+ token: 2548qsd5a8qsd43a
+ headers:
+ contentType: application/octet-stream
+ body: ${ $context.base64Backup }
+schedule:
+ cron: 0 0 * * *
+```
+
+## Conclusion
+
+This workflow effectively automates the process of backing up an SQL Server database and securely uploading it to a Minio storage solution, enhancing data management and security for database administrators.
\ No newline at end of file
diff --git a/use-cases/automated-data-backup/diagram.png b/use-cases/automated-data-backup/diagram.png
new file mode 100644
index 00000000..c9d5246a
Binary files /dev/null and b/use-cases/automated-data-backup/diagram.png differ
diff --git a/use-cases/managing-ev-charging-stations/README.md b/use-cases/managing-ev-charging-stations/README.md
new file mode 100644
index 00000000..35e41091
--- /dev/null
+++ b/use-cases/managing-ev-charging-stations/README.md
@@ -0,0 +1,261 @@
+# Use Case: Managing EV Charging Stations
+
+## Overview
+
+### System
+
+This use case focuses on managing Electric Vehicle (EV) charging stations using a serverless workflow. The system handles various events related to the charging process, including card scanning, charging session management, and error handling. The system interacts with the EV power supplier's API to perform necessary operations like starting or ending sessions, locking and unlocking slots, processing payments, and handling errors.
+
+### Actors
+
+- **EV Owner:** The person using the charging station.
+- **Charging Station:** The physical unit where vehicles are charged.
+- **EV Power Supplier API:** The external system responsible for managing the charging process, slot availability, and session data.
+
+### Goals
+
+- **Automate Charging Station Operations:** Automate the process of handling charging sessions, from card scanning to payment processing and error management.
+- **Improve User Experience:** Provide a smooth and efficient charging experience by ensuring slots are managed effectively and errors are promptly addressed.
+- **Ensure System Integrity:** Implement robust error handling to maintain service continuity and prevent misuse or unauthorized access.
+
+### Preconditions
+
+- The charging station must be connected to the EV Power Supplier's network.
+- The card used for charging must be registered and valid.
+- The charging station has two available slots, each capable of handling one vehicle at a time.
+
+## Scenario
+
+### Triggers
+
+The workflow is triggered by two types of events:
+1. **Card Scanned Event:** Occurs when a user scans their card at the charging station.
+2. **Fault Event:** Occurs when the charging station reports an error or fault.
+
+### Flow Breakdown
+
+#### 1. **Initialization:**
+ - Capture the event details and store them in the workflow context.
+
+#### 2. **Handle Station Events:**
+ - Depending on the event type, the workflow either attempts to manage a charging session or handles an error.
+
+#### 3. **Try to Get Active Session:**
+ - Check if there is an active session for the scanned card.
+
+#### 4. **Handle Active Session:**
+ - If a session is in progress, attempt to end it. If no session is in progress, try to acquire an available slot.
+
+#### 5. **Try to Acquire Slot:**
+ - If an available slot is found, start a new charging session. If no slots are available, make the station’s LED flicker red and end the workflow.
+
+#### 6. **Start Session:**
+ - Initialize a new charging session, lock the slot, and start the charging process.
+
+#### 7. **End Session:**
+ - End the charging session, process the payment, unlock the slot, and notify the user by flickering the LED.
+
+#### 8. **Handle Error:**
+ - Contact support, activate the red LED, and notify the system about the error.
+
+### Visualization
+
+The following diagram represents the high-level flow of the workflow:
+
+
+
+*Visualization generated by Synapse.*
+
+### Example
+
+```yaml
+document:
+ dsl: '1.0.0'
+ namespace: default
+ name: manage-ev-charging-stations
+ version: '0.1.0'
+schedule:
+ on:
+ any:
+ - with:
+ type: com.ev-power-supplier.charging-station.card-scanned.v1
+ - with:
+ type: com.ev-power-supplier.charging-station.faulted.v1
+do:
+
+ - initialize:
+ set:
+ event: ${ $workflow.input[0].data }
+ export:
+ as: .event
+
+ - handleStationEvents:
+ switch:
+ - sessionStarted:
+ when: .event.type == "com.ev-power-supplier.charging-station.card-scanned.v1"
+ then: tryGetActiveSession
+ - stationError:
+ when: .event.type == "com.ev-power-supplier.charging.station-faulted.v1"
+ then: handleError
+ then: raiseUnsupportedEventError
+
+ - tryGetActiveSession:
+ try:
+ - getSessionForCard:
+ call: http
+ with:
+ method: get
+ endpoint: https://ev-power-supplier.com/api/v2/stations/{stationId}/session/{cardId}
+ - setSessionInfo:
+ set:
+ session: ${ .session }
+ catch:
+ errors:
+ with:
+ status: 404
+
+ - handleActiveSession:
+ switch:
+ - sessionInProgress:
+ when: .session != null
+ then: endSession
+ - noActiveSession:
+ then: tryAquireSlot
+
+ - tryAquireSlot:
+ try:
+ - acquireSlot:
+ call: http
+ with:
+ method: post
+ endpoint: https://ev-power-supplier.com/api/v2/stations/{stationId}
+ body:
+ card: ${ $context.card }
+ export:
+ as: '$context + { slot: .slot }'
+ catch:
+ errors:
+ with:
+ status: 400
+ when: .detail == "No charging slots available"
+ do:
+ - noSlotsAvailable:
+ call: http
+ with:
+ method: post
+ endpoint: https://ev-power-supplier.com/api/v2/stations/{stationId}/leds/main
+ body:
+ action: flicker
+ color: red
+ duration: 3000
+ then: end
+
+ - startSession:
+ do:
+ - initialize:
+ set:
+ session:
+ card: ${ $context.card }
+ slotNumber: ${ $context.slot.number }
+ export:
+ as: '$context + { session: . }'
+ - feedBack:
+ call: http
+ with:
+ method: post
+ endpoint: https://ev-power-supplier.com/api/v2/stations/{stationId}/leds/{slotNumber}
+ body:
+ action: 'on'
+ color: blue
+ - lockSlot:
+ call: http
+ with:
+ method: put
+ endpoint: https://ev-power-supplier.com/api/v2/stations/{stationId}/slot/{slotNumber}/lock
+ - start:
+ call: http
+ with:
+ method: put
+ endpoint: https://ev-power-supplier.com/api/v2/sessions/{sessionId}/start
+ - notify:
+ emit:
+ event:
+ with:
+ source: https://ev-power-supplier.com
+ type: com.ev-power-supplier.charging-station.session-started.v1
+ data: ${ $context.session }
+
+ - endSession:
+ do:
+ - end:
+ call: http
+ with:
+ method: put
+ endpoint: https://ev-power-supplier.com/api/v2/sessions/{sessionId}/end
+ - processPayment:
+ call: http
+ with:
+ method: put
+ endpoint: https://ev-power-supplier.com/api/v2/sessions/{sessionId}/pay
+ - unlockSlot:
+ call: http
+ with:
+ method: put
+ endpoint: https://ev-power-supplier.com/api/v2/stations/{stationId}/slot/{slotNumber}/unlock
+ - feedBack:
+ call: http
+ with:
+ method: post
+ endpoint: https://ev-power-supplier.com/api/v2/stations/{stationId}/leds/{slotNumber}
+ body:
+ action: flicker
+ color: white
+ duration: 3000
+ - notify:
+ emit:
+ event:
+ with:
+ source: https://ev-power-supplier.com
+ type: com.ev-power-supplier.charging-station.session-ended.v1
+ data: ${ $context.session }
+ then: end
+
+ - handleError:
+ do:
+ - contactSupport:
+ call: http
+ with:
+ method: post
+ endpoint: https://ev-power-supplier.com/api/v2/stations/{stationId}/support
+ body:
+ error: ${ $context.event.data.error }
+ - feedBack:
+ call: http
+ with:
+ method: post
+ endpoint: https://ev-power-supplier.com/api/v2/stations/{stationId}/leds/main
+ body:
+ action: 'on'
+ color: red
+ - notify:
+ emit:
+ event:
+ with:
+ source: https://ev-power-supplier.com
+ type: com.ev-power-supplier.charging-station.out-of-order.v1
+ data: ${ $context.event.data.error }
+ then: end
+
+ - raiseUnsupportedEventError:
+ raise:
+ error:
+ type: https://serverlessworkflow.io/spec/1.0.0/errors/runtime
+ status: 400
+ title: Unsupported Event
+ detail: ${ "The specified station event '\($context.event.type)' is not supported in this context" }
+ then: end
+```
+
+## Conclusion
+
+This use case demonstrates the automation of key tasks in managing EV charging stations. By integrating with the EV Power Supplier API, the workflow efficiently handles charging sessions, processes payments, manages slot availability, and responds to errors. This ensures a seamless and user-friendly experience while maintaining operational integrity.
\ No newline at end of file
diff --git a/use-cases/managing-ev-charging-stations/diagram.png b/use-cases/managing-ev-charging-stations/diagram.png
new file mode 100644
index 00000000..2cb37190
Binary files /dev/null and b/use-cases/managing-ev-charging-stations/diagram.png differ
diff --git a/use-cases/managing-github-issues/README.md b/use-cases/managing-github-issues/README.md
new file mode 100644
index 00000000..d320c4e5
--- /dev/null
+++ b/use-cases/managing-github-issues/README.md
@@ -0,0 +1,262 @@
+# Use Case: Managing GitHub Issues
+
+## Overview
+
+### System
+
+The system is a GitHub-based issue management workflow designed to automate the lifecycle of an issue. It leverages Serverless Workflow (SW) DSL to handle various stages, from assignment and development to review and closure.
+
+### Actors
+
+- **QA Team:** Creates and provides details for issues.
+- **Development Team:** Works on resolving issues.
+- **Reviewers:** Evaluate the work done by the development team.
+- **GitHub API:** External system for managing and updating issue states.
+
+### Goals
+
+- **Automate Issue Management:** Streamline the process from issue creation to closure, reducing manual tasks and ensuring consistent handling.
+- **Facilitate Collaboration:** Coordinate between different teams (QA, Dev, Reviewers) through automated task assignments and notifications.
+- **Ensure Integrity:** Implement error handling to avoid common pitfalls, like assigning reviewers who are also the developers of the issue.
+
+### Preconditions
+
+- The workflow assumes a GitHub repository where issues are tracked.
+- Teams and roles (QA, Dev, Reviewer) are predefined and recognized by the system.
+- Relevant GitHub events are configured to trigger the workflow.
+
+## Scenario
+
+### Triggers
+
+The workflow is triggered when a new issue is created in the GitHub repository by a member of the QA team.
+
+### Flow Breakdown
+
+1. **Initialization:**
+ - The workflow starts by capturing the issue details from the trigger event and storing them in the workflow context.
+
+2. **Assign to Development Team:**
+ - The issue is assigned to the development team, and a notification is emitted. The workflow then waits for the development work to be completed.
+
+3. **Evaluate Development Outcome:**
+ - The workflow evaluates the development outcome based on the data returned. It decides the next steps, such as sending the issue for review or requesting more details.
+
+4. **Review Process:**
+ - The issue is assigned to a reviewer (excluding the developer who worked on it). A notification is sent out, and the workflow waits for the review to be completed.
+
+5. **Issue Closure:**
+ - Upon successful review, the workflow triggers a GitHub API call to close the issue. A final notification is sent to confirm the closure.
+
+6. **Error Handling:**
+ - The workflow includes steps to handle errors, such as when an unsupported action is taken, or a developer is incorrectly assigned as a reviewer.
+
+### Visualization
+
+The following diagram represents the high-level flow of the workflow:
+
+
+
+*Visualization generated by Synapse.*
+
+### Example
+
+```yaml
+document:
+ dsl: '1.0.0'
+ namespace: default
+ name: manage-github-issues
+ version: '0.1.0'
+schedule:
+ on:
+ one:
+ with:
+ type: com.github.events.issues.opened.v1
+ data: ${ .data.author.team == "QA" }
+do:
+
+ - initialize:
+ set:
+ issue: ${ $workflow.input[0].data }
+ export:
+ as: .issue
+
+ - awaitForDevWork:
+ do:
+ - assign:
+ set:
+ issue:
+ assignedTo: DevTeam
+ status: inProgress
+ - notify:
+ emit:
+ event:
+ with:
+ source: https://serverlessworkflow.io
+ type: com.github.events.issues.assignedToDevTeam.v1
+ data:
+ issue: ${ .issue }
+ - await:
+ listen:
+ to:
+ one:
+ with:
+ type: com.github.events.issues.devWorkCompleted.v1
+ export:
+ as: '$context + { issue: ($context.issue + { action: .data.nextAction, dev: .data.dev }) }'
+ then: evaluateDevWorkOutcome
+
+ - evaluateDevWorkOutcome:
+ switch:
+ - review:
+ when: $context.issue.action == "review"
+ then: reviewIssue
+ - requestDetails:
+ when: $context.issue.action == "requestDetails"
+ then: awaitDetailsFromQA
+ - default:
+ then: raiseUnsupportedActionError
+
+ - awaitDetailsFromQA:
+ do:
+ - assign:
+ set:
+ issue:
+ assignedTo: QA
+ status: awaitingDetails
+ assignTo: ${ $context.issue.author }
+ - notify:
+ emit:
+ event:
+ with:
+ source: https://serverlessworkflow.io
+ type: com.github.events.issues.assignedToQATeam.v1
+ data:
+ issue: ${ $context.issue }
+ - await:
+ listen:
+ to:
+ one:
+ with:
+ type: com.github.events.issues.detailsProvided.v1
+ export:
+ as: '$context + { issue: ($context.issue + { action: .data.nextAction }) }'
+ then: awaitForDevWork
+
+ - reviewIssue:
+ do:
+ - assign:
+ set:
+ issue:
+ assignedTo: DevTeam
+ status: reviewing
+ - notify:
+ emit:
+ event:
+ with:
+ source: https://serverlessworkflow.io
+ type: com.github.events.issues.pendingReview.v1
+ data:
+ issue: ${ $context.issue }
+ review:
+ exclude: ${ $context.issue.dev }
+ - await:
+ listen:
+ to:
+ one:
+ with:
+ type: com.github.events.issues.reviewed.v1
+ export:
+ as: '$context + { issue: ($context.issue + { reviewer: .data.reviewer }) }'
+
+ - validateReview:
+ switch:
+ - reviewerIsNotAssignedDev:
+ when: $context.issue.reviewer != $context.issue.dev
+ then: evaluateReview
+ - reviewerIsAssignedDev:
+ then: raiseAssignedDevCannotBeReviewer
+
+ - evaluateReview:
+ do:
+ - assign:
+ set:
+ issue:
+ assignedTo: QA
+ status: evaluating
+ - notify:
+ emit:
+ event:
+ with:
+ source: https://serverlessworkflow.io
+ type: com.github.events.issues.evaluateReview.v1
+ data:
+ issue: ${ $context.issue }
+ assignTo: ${ $context.issue.author }
+ - await:
+ listen:
+ to:
+ one:
+ with:
+ type: com.github.events.issues.evaluated.v1
+ export:
+ as: '$context + { issue: ($context.issue + { action: .data.nextAction }) }'
+ - evaluate:
+ switch:
+ - closeIssue:
+ when: $context.issue.action == "close"
+ then: closeIssue
+ - default:
+ then: exit
+ - closeIssue:
+ do:
+ - initialize:
+ set:
+ organization: ${ $context.issue.repository.organization }
+ repository: ${ $context.issue.repository.name }
+ issueNumber: ${ $context.issue.number }
+ - closeIssueOnGithub:
+ call: http
+ with:
+ endpoint: https://api.github.com/repos/{organization}/{repository}/issues/{issueNumber}
+ method: patch
+ body:
+ state: closed
+ - setIssueInfo:
+ set:
+ issue:
+ status: closed
+ - notify:
+ emit:
+ event:
+ with:
+ source: https://serverlessworkflow.io
+ type: com.github.events.issues.closed.v1
+ data:
+ issue: ${ $context.issue }
+ then: end
+ then: awaitForDevWork
+
+ - raiseUnsupportedActionError:
+ raise:
+ error:
+ type: https://serverlessworkflow.io/spec/1.0.0/errors/runtime
+ status: 400
+ title: Unsupported Action
+ detail: The specified action is not supported in this context
+ then: end
+
+ - raiseAssignedDevCannotBeReviewer:
+ raise:
+ error:
+ type: https://serverlessworkflow.io/spec/1.0.0/errors/runtime
+ status: 400
+ title: Invalid Reviewer
+ detail: The developer that has performed the work associated with the issue cannot be the reviewer of its own work
+ then: end
+
+```
+
+## Conclusion
+
+This use case illustrates the powerful capabilities of Serverless Workflow in automating complex processes such as GitHub issue management. The workflow is flexible, scalable, and easy to maintain, making it an ideal choice for orchestrating tasks in modern development environments. By leveraging Serverless Workflow, teams can ensure efficient and consistent handling of issues, improving productivity and achieving better project outcomes.
\ No newline at end of file
diff --git a/use-cases/managing-github-issues/diagram.png b/use-cases/managing-github-issues/diagram.png
new file mode 100644
index 00000000..ba0d0af4
Binary files /dev/null and b/use-cases/managing-github-issues/diagram.png differ
diff --git a/use-cases/multi-agent-ai-content-generation/README.md b/use-cases/multi-agent-ai-content-generation/README.md
new file mode 100644
index 00000000..abb633fd
--- /dev/null
+++ b/use-cases/multi-agent-ai-content-generation/README.md
@@ -0,0 +1,175 @@
+# Use Case: Multi-Agent Collaboration for AI Content Generation
+
+## Overview
+
+### System
+
+The system is designed to facilitate collaboration between multiple AI agents, each specializing in different aspects of content creation, such as text generation, image generation, and quality evaluation. The workflow coordinates these agents to produce high-quality, refined AI content.
+
+### Actors
+
+- **Text Generator Agent:** Generates initial text content based on provided prompts.
+- **Image Generator Agent:** Creates images based on the generated text.
+- **Quality Evaluator Agent:** Assesses the quality of the generated text and images, providing feedback for improvements.
+- **Refinement Agent:** Makes adjustments to the content based on the evaluator’s feedback.
+- **User:** The end user who initiates the content generation process and provides the initial prompts.
+
+### Goals
+
+- **Streamline AI Collaboration:** Facilitate efficient communication and collaboration between AI agents to generate cohesive and high-quality content.
+- **Improve Content Quality:** Utilize iterative feedback and refinement cycles to enhance the quality of the generated content.
+- **User Satisfaction:** Ensure that the final output meets high standards and aligns with the user’s expectations.
+
+### Preconditions
+
+- The system has access to pre-trained AI models for text generation, image generation, and quality evaluation.
+- A user-provided prompt initiates the content generation process.
+
+## Scenario
+
+### Triggers
+
+The workflow is triggered when a user submits a prompt to generate AI content.
+
+### Flow Breakdown
+
+1. **Initialize Workflow:**
+ - The workflow begins by capturing the user prompt and storing it in the workflow context.
+
+2. **Generate Initial Text:**
+ - The Text Generator Agent creates initial text content based on the user prompt.
+
+3. **Generate Associated Image:**
+ - The Image Generator Agent generates an image that corresponds to the text.
+
+4. **Evaluate Quality:**
+ - The Quality Evaluator Agent assesses the generated text and image, providing feedback on areas for improvement.
+
+5. **Refine Content:**
+ - The Refinement Agent adjusts the text and image based on the evaluator’s feedback.
+
+6. **Final Evaluation:**
+ - The refined content is re-evaluated to ensure that it meets quality standards. If further refinement is needed, the workflow loops back to the refinement step.
+
+7. **Content Delivery:**
+ - Once the content passes the final evaluation, it is delivered to the user.
+
+### Visualization
+
+The following diagram represents the high-level flow of the workflow:
+
+
+
+*Visualization generated by Synapse.*
+
+### Example
+
+```yaml
+document:
+ dsl: '1.0.0'
+ namespace: default
+ name: multi-agent-collaboration-for-ai-content
+ version: '0.1.0'
+input:
+ schema:
+ document:
+ type: object
+ properties:
+ prompt:
+ type: string
+ required: [ prompt ]
+do:
+
+ - initialize:
+ set:
+ prompt: ${ $workflow.input.prompt }
+ export:
+ as: .prompt
+
+ - generateText:
+ call: http
+ with:
+ method: post
+ endpoint: https://ai-content-generator.com/api/v1/generate-text
+ body:
+ prompt: ${ .prompt }
+ export:
+ as: $context + { text: .text }
+
+ - generateImage:
+ call: http
+ with:
+ method: post
+ endpoint: https://ai-content-generator.com/api/v1/generate-image
+ body:
+ text: ${ .text }
+ export:
+ as: $context + { image: .image }
+
+ - evaluateQuality:
+ call: http
+ with:
+ method: post
+ endpoint: https://ai-content-generator.com/api/v1/evaluate
+ body:
+ text: ${ .text }
+ image: ${ .image }
+ export:
+ as: $context + { evaluation: .evaluation }
+
+ - refineContent:
+ switch:
+ - needsRefinement:
+ when: .evaluation.needsRefinement == true
+ then: refine
+ - noRefinementNeeded:
+ when: .evaluation.needsRefinement == false
+ then: deliverContent
+
+ - refine:
+ do:
+ - refineText:
+ call: http
+ with:
+ method: post
+ endpoint: https://ai-content-generator.com/api/v1/refine-text
+ body:
+ text: ${ .text }
+ feedback: ${ .evaluation.text_feedback }
+ - refineImage:
+ call: http
+ with:
+ method: post
+ endpoint: https://ai-content-generator.com/api/v1/refine-image
+ body:
+ image: ${ .image }
+ feedback: ${ .evaluation.image_feedback }
+ - reevaluate:
+ call: http
+ with:
+ method: post
+ endpoint: https://ai-content-generator.com/api/v1/evaluate
+ body:
+ text: ${ .refined_text }
+ image: ${ .refined_image }
+ export:
+ as: .evaluation
+ then: evaluateQuality
+
+ - deliverContent:
+ do:
+ - notify:
+ emit:
+ event:
+ with:
+ source: https://ai-content-generator.com
+ type: com.ai-content-generator.content.ready.v1
+ data:
+ text: ${ .text }
+ image: ${ .image }
+ then: end
+```
+
+## Conclusion
+
+This use case demonstrates how multiple AI agents can collaborate efficiently to generate high-quality content. By leveraging the Serverless Workflow DSL, the system ensures that each agent’s output is evaluated and refined in a coordinated manner, leading to superior results. This approach allows for iterative improvements, making it an ideal solution for complex content generation tasks.
\ No newline at end of file
diff --git a/use-cases/multi-agent-ai-content-generation/diagram.png b/use-cases/multi-agent-ai-content-generation/diagram.png
new file mode 100644
index 00000000..9b0a4931
Binary files /dev/null and b/use-cases/multi-agent-ai-content-generation/diagram.png differ