---
url: https://node-ts.github.io/bus/guide/workflows/starting.md
description: Start a new instance of a workflow when a message arrives.
---

# Starting

A workflow is started by one or more types of message. When one arrives, a new instance of the workflow state is created and the message is passed to its `startedBy` handler. This page shows how to declare one.

The handler returns the initial state of the new instance. It can send commands through its context, which carry the new workflow's id so that their replies come back to it.

::: code-group

```ts \[Functions]
export const fulfilmentWorkflow = defineWorkflow(FulfilmentWorkflowState)
  // Start a new workflow when an ItemPurchased event is received
  .startedBy(ItemPurchased, async ({ itemId, customerId }, _state, ctx) => {
    await ctx.send(new ShipItem(itemId, customerId))
    // The initial state of the new workflow
    return { itemId, customerId, status: 'shipping-item' as const }
  })
```

```ts \[Class]
export class FulfilmentWorkflow extends Workflow<FulfilmentWorkflowState> {
  configureWorkflow(
    mapper: WorkflowMapper<FulfilmentWorkflowState, FulfilmentWorkflow>
  ): void {
    mapper
      .withState(FulfilmentWorkflowState)
      // Start a new workflow when an ItemPurchased event is received
      .startedBy(ItemPurchased, 'shipItem')
  }

  async shipItem(
    { itemId, customerId }: ItemPurchased,
    _state: FulfilmentWorkflowState,
    _attributes: MessageAttributes,
    ctx: HandlerContext
  ) {
    await ctx.send(new ShipItem(itemId, customerId))
    return { itemId, customerId, status: 'shipping-item' as const }
  }
}
```

:::

Here, each `ItemPurchased` event starts a new fulfilment workflow, which sends `ShipItem` and saves the item and customer in its state.

A function handler is called with the message, the state and a `WorkflowContext`. A class handler is called with the message, the state, the message attributes and a `HandlerContext`, and can declare fewer parameters. In a `startedBy` handler the state is new, with only its `$` fields set.

A `startedBy` handler that returns nothing starts the workflow with that empty state. To not start a workflow at all for some messages, [discard](/guide/workflows/state#discarding-state) it.

## See also

* [Handling](/guide/workflows/handling) the messages that follow
* [State](/guide/workflows/state)
