Skip to main content
Every handler runs against one entity, the record moving through the flow. Most handlers inherit it from the event that triggered them and declare nothing. But the handler that receives a flow’s first event has no entity yet, so it must say where one comes from. Declare exactly one of the three modes. Declaring none, or declaring more than one, is a boot error: the package refuses to load, and swarm verify catches it before you deploy.

create_entity

Create (“mint”) a new entity at the flow’s initial state. Use it when the event starts a new item in this flow (a fresh ticket arriving):
The new entity gets an auto-generated id, and the inbound event’s entity_id is ignored for state operations. Every declared field already has a value the moment the entity exists — its initial: value, or the type default — so a guard in the same handler can read any field immediately.
  • Cannot be combined with accumulate — an accumulator targets one entity, but create_entity mints a new one each time.
  • Can be combined with fan_out — one entity is created and every fanned-out event shares it.

select_entity

Attach to one existing entity, matched by a business key. The by map pairs entity fields with payload.* values from the triggering event:
Exactly one entity must match. Zero matches, or more than one, both stop the handler with an error rather than letting it guess (that is what “fail closed” means throughout these docs). This is the mode you use when a result arrives from another flow and has to re-attach to the right entity; see Composing flows.

select_or_create_entity

Resolve one existing entity by the key, or mint a fresh one from that key if none matches. Use it when an event might be the first the flow has seen for a given key, or a follow-up:
On the create path the entity is minted at the initial stage; the key field is not written for you — write it in data_accumulation, as the accordion below shows.

Complete flows

Both examples below pass swarm verify.
The first event mints the order; every later event finds that same order by its business key. This is the most common shape: one handler creates, the rest select.
package.yaml
schema.yaml
entities.yaml
events.yaml
nodes.yaml
What happens: order.placed runs create_entity, so it mints a fresh order at the placed state and records order_id and customer. When order.shipped arrives later, the handler has no entity of its own, so select_entity finds the existing order whose order_id matches the event’s payload.order_id, then advances it to shipped. order.delivered does the same and moves it to the terminal delivered state. The order_id field is what links every later event back to the order it created.
Use select_or_create_entity when an event might be the first the flow has seen for a key, or a follow-up, and you do not want to handle the two cases separately.
package.yaml
schema.yaml
entities.yaml
events.yaml
nodes.yaml
What happens: the very first page.viewed for a session_id finds no matching session, so select_or_create_entity mints one at active; every later view for that id finds the existing session. Either way the handler then writes session_id and increments view_count, so the count rises with each view. session.ended uses plain select_entity (the session must already exist by then) and moves it to ended. The computed write reads entity.view_count as it stood before this handler, which is why it increments cleanly across events.

Flows and entities

What an entity is, and how instances give each work item its own.