> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devset.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Devset Workflows: DSL Structure, Fields, and Execution

> A workflow is a JSON document that combines broker configuration, payload schema, and an ordered pipeline of stages into a single executable unit.

A workflow is the fundamental building block in Devset. It describes everything the engine needs to produce and dispatch events: which broker to target, how to connect to it, what the payload looks like, and the exact sequence of steps to execute. You define workflows as JSON documents, and Devset compiles them into an asynchronous execution plan that runs your pipeline as many times as you specify.

## Complete Example

The following workflow produces ten `order.created` events to a Kafka topic, with a randomised order ID and a line-item count driven by workflow state:

```json theme={null}
{
  "id": "order-created-load",
  "messageType": "kafka",
  "contentType": "application/json",
  "producerName": "local-kafka",
  "topic": "orders",
  "schemaId": "order-schema",
  "executions": 10,
  "state": {
    "sequence": {
      "index": 0
    }
  },
  "pipeline": [
    {
      "stage": "build-order",
      "event": "order.created",
      "source": "none",
      "set": {
        "orderId": { "$fn": "uuid()" },
        "createdAt": { "$fn": "now()" },
        "itemCount": { "$fn": "int(1, 20)" },
        "status": { "$fn": "choice(pending, confirmed, processing)" }
      },
      "state": {
        "sequence.index": { "$fn": "add(state.sequence.index, 1)" }
      },
      "emit": true
    }
  ]
}
```

## Field Reference

<ParamField path="id" type="string" required>
  A unique identifier for this workflow. Used to reference the workflow in the UI and API. Choose a short, descriptive slug such as `"order-created-load"`.
</ParamField>

<ParamField path="messageType" type="&#x22;kafka&#x22; | &#x22;rabbit&#x22;" default="&#x22;kafka&#x22;">
  The target broker type. Set to `"kafka"` for Apache Kafka or `"rabbit"` for RabbitMQ. This determines which broker-specific fields are required (`topic` for Kafka; `exchange` and `routingKey` for RabbitMQ). Defaults to `"kafka"` when omitted.
</ParamField>

<ParamField path="contentType" type="&#x22;application/json&#x22; | &#x22;application/x-protobuf&#x22;" default="&#x22;application/json&#x22;">
  The serialisation format for the event payload. Use `"application/json"` for human-readable JSON payloads or `"application/x-protobuf"` for binary Protobuf payloads. Defaults to `"application/json"` when omitted. When using Protobuf, you must also configure `wireFormat` on the relevant stage.
</ParamField>

<ParamField path="producerName" type="string" required>
  The name of the connector this workflow uses to reach the broker. The value must exactly match the `name` field of a configured Kafka or RabbitMQ connector. See [Connectors](/concepts/connectors) for details.
</ParamField>

<ParamField path="topic" type="string">
  *(Kafka only)* The Kafka topic to which all events in this workflow are published. Required when `messageType` is `"kafka"`.
</ParamField>

<ParamField path="exchange" type="string">
  *(RabbitMQ only)* The RabbitMQ exchange to which events are published. Required when `messageType` is `"rabbit"`.
</ParamField>

<ParamField path="routingKey" type="string">
  *(RabbitMQ only)* The routing key attached to every published message. Required when `messageType` is `"rabbit"`.
</ParamField>

<ParamField path="schemaId" type="string">
  The default schema applied to all stages in this workflow. Individual stages can override this with their own `schemaId`. Schemas are managed in the [Schema Repo](/concepts/schemas) and drive field validation and the Function Studio field picker.
</ParamField>

<ParamField path="executions" type="integer" default="1">
  The number of times the full pipeline runs. Setting `executions: 10` causes the engine to run the entire pipeline — every stage in order — ten times. Each execution is independent and receives the same initial state seed. Defaults to `1` when omitted.
</ParamField>

<ParamField path="state" type="object">
  The initial mutable state for the workflow. State is seeded once per execution and is readable and writable by every stage in the pipeline. Use dot-notation keys inside stage `state` blocks to update nested paths. For example:

  ```json theme={null}
  {
    "state": {
      "entity": { "count": 0 },
      "session": { "active": true }
    }
  }
  ```
</ParamField>

<ParamField path="pipeline" type="Stage[]" required>
  An ordered array of stage objects. The engine executes stages sequentially within each execution. See [Pipeline Stages](/concepts/pipeline-stages) for the full stage field reference.
</ParamField>

## Execution Model

When you run a workflow, Devset compiles the JSON document into an internal execution plan and schedules it asynchronously. Here is what happens for each execution:

1. **State is seeded.** The `state` object from the workflow definition is copied into the execution context. Every execution starts with the same initial state, so executions are isolated from one another.
2. **The pipeline runs sequentially.** Each stage is executed in array order. A stage can read the payload produced by the previous stage, mutate state, and conditionally emit an event to the broker.
3. **Events are dispatched.** Stages with `emit: true` (or a truthy conditional emit) publish their payload to the configured broker using the named connector.
4. **The execution completes.** After the last stage finishes, the execution is recorded in the run log. The engine starts the next execution until the `executions` count is exhausted.

<Tip>
  Use `state` to carry counters, sequence numbers, or flags between stages within a single execution. Because each execution reseeds state from the workflow definition, state does not accumulate across executions.
</Tip>

<Note>
  The engine runs executions asynchronously and may parallelise them. If ordering across executions matters for your test scenario, design your pipeline so that ordering is enforced by the broker consumer under test rather than by Devset itself.
</Note>

## Broker-Specific Layouts

**Kafka workflow** — requires `topic`:

```json theme={null}
{
  "id": "payment-events",
  "messageType": "kafka",
  "contentType": "application/json",
  "producerName": "local-kafka",
  "topic": "payments",
  "executions": 5,
  "state": {},
  "pipeline": []
}
```

**RabbitMQ workflow** — requires `exchange` and `routingKey`:

```json theme={null}
{
  "id": "notification-events",
  "messageType": "rabbit",
  "contentType": "application/json",
  "producerName": "local-rabbit",
  "exchange": "notifications",
  "routingKey": "user.notify",
  "executions": 5,
  "state": {},
  "pipeline": []
}
```

## Next Steps

* [Pipeline Stages](/concepts/pipeline-stages) — learn how to build each step in your pipeline
* [Expressions](/concepts/expressions) — use dynamic values, functions, and state references in your stages
