Learn · 01 of 5

The five elements

Five recurring pieces appear across the four workflow patterns.

Event — a fact that already happened

An Event is a concrete fact in the domain, named in the past tense: Appointment Added, Pet Added, Payment Received, Weather Forecast Changed.

In .em.hcl, Events are canonical contracts owned by a bounded context:

bounded_context "appointments" { event "appointment_added" { } }

The label is the identity. appointment_added gets the derived title Appointment Added; add title only for different wording.

Rule of thumb: if the thing can still be rejected, it is probably not an Event yet.

Command — an intent to make something happen

A Command represents a request or intent. It can succeed or fail: Add Appointment, Add Pet, Cancel Subscription.

Commands live inside workflows and point to the Event(s) they may produce:

bounded_context "appointments" { aggregate "appointment" { } event "appointment_added" { aggregate = aggregate.appointment } } state_change "schedule_appointment" { screen "schedule_appointment_ui" { to = [command.add_appointment] } command "add_appointment" { aggregate = aggregate.appointments.appointment to = [event.appointments.appointment_added] } }

A Command needs an incoming flow, an api_endpoint, or external_trigger. Otherwise the validator reports EM404.

Read Model — an answer to a concrete question

A Read Model answers one concrete question.

No question, no Read Model.

The language makes that discipline explicit by requiring question:

bounded_context "appointments" { event "appointment_added" { } } state_view "view_calendar" { readmodel "calendar" { question = "Which appointments are on the calendar?" from = [event.appointments.appointment_added] to = [screen.calendar_ui] } screen "calendar_ui" { } }

"What data is needed?" is vague. "Which appointments do not yet have a weather forecast?" defines the projection.

Screen — where an actor observes or initiates behavior

A Screen is a UI, rough wireframe, or other human-facing interaction point.

bounded_context "appointments" { event "appointment_added" { } } actor "calendar_user" { auth_required = true } state_view "view_calendar" { readmodel "calendar" { question = "Which appointments are on the calendar?" from = [event.appointments.appointment_added] to = [screen.calendar_ui] } screen "calendar_ui" { actor = actor.calendar_user } }

Actors are reusable catalog declarations referenced with traversals such as actor.calendar_user.

Automation / gear — a machine reaction

The gear on the visual cheat sheet means the computer reacts instead of a human.

Visual gear concept → processor block.
Automation pattern → automation workflow block.

bounded_context "appointments" { event "appointment_added" { } } bounded_context "weather" { event "weather_predicted_for_appointment" { } } automation "add_weather_forecast" { readmodel "appointments_without_weather_forecast" { question = "Which appointments still need a weather forecast?" from = [event.appointments.appointment_added] to = [processor.weather_processor] } processor "weather_processor" { to = [command.add_weather_forecast] } command "add_weather_forecast" { to = [event.weather.weather_predicted_for_appointment] } }

automation is a top-level workflow kind. Its machine reaction is a processor.