Overview
The Flow Context (ctx) is passed as the second argument to every step handler. It provides utilities for:
- Enqueuing events to other steps
- Managing state with key-value storage
- Logging structured logs
- Accessing streams for real-time data
- Trigger information about how the step was invoked
Context Structure
motia-js/packages/motia/src/types.ts:58-92, motia-py/packages/motia/src/motia/types.py:36-114
ctx.enqueue()
Enqueue events to trigger other steps asynchronously.Basic Usage
Type Safety
Enqueue topics are type-checked against the step’senqueues configuration:
motia-js/packages/motia/src/types.ts:28-29, motia-js/playground/steps/hello/hello-api.step.ts:31-39
ctx.state
Access the distributed key-value state management system.State Operations
State Structure
State is organized hierarchically:State Triggers
State changes automatically fire state triggers:motia-js/packages/motia/src/types.ts:19-26, motia-js/playground/steps/multi-trigger-example.step.ts:79, motia-py/packages/motia/src/motia/types.py:21-31
ctx.logger
Structured logging with automatic trace correlation.Logging Levels
Automatic Trace Correlation
All logs are automatically tagged with:- traceId: Unique identifier for the entire workflow
- spanId: Identifier for the current operation
- trigger metadata: Type, path, topic, etc.
motia-js/packages/motia/src/types.ts:62, engine/src/engine/mod.rs:67-75
ctx.streams
Access real-time data streams for collaborative applications.Stream Operations
Streams vs State
| Feature | Streams | State |
|---|---|---|
| Use Case | Real-time collaboration, UI sync | Backend data storage |
| Persistence | Optional (configurable) | Always persisted |
| WebSocket Updates | Yes (live updates to clients) | No |
| Access Control | Per-stream auth | Global |
| Triggers | Stream triggers | State triggers |
motia-js/playground/steps/todo/create-todo.step.ts:47, engine/src/modules/stream/mod.rs
ctx.trigger
Information about how the step was triggered.Trigger Info Structure
Usage Example
motia-js/packages/motia/src/types.ts:98-105
ctx.traceId
Unique identifier for distributed tracing across the workflow.motia-js/packages/motia/src/types.ts:60, engine/src/protocol.rs:75-80
Type Guards (ctx.is)
Check which trigger type invoked the step.motia-js/packages/motia/src/types.ts:66-72
ctx.getData()
Extract the data payload regardless of trigger type.motia-js/packages/motia/src/types.ts:74-88, motia-py/packages/motia/src/motia/types.py:69-83
ctx.match()
Handle multiple trigger types with pattern matching.motia-js/packages/motia/src/types.ts:91, motia-js/playground/steps/multi-trigger-example.step.ts:70-152, motia-py/packages/motia/src/motia/types.py:84-113
Best Practices
Use structured logging
Use structured logging
Always include relevant context in logs. Avoid plain string messages:
Type-safe enqueuing
Type-safe enqueuing
Declare all topics in the
enqueues array for compile-time validation:Group state logically
Group state logically
Use meaningful group IDs for state organization:
Handle errors in async operations
Handle errors in async operations
Wrap state, stream, and enqueue operations in try-catch blocks:
Next Steps
State Management
Deep dive into state operations
Streams
Learn about real-time streams
Observability
Explore logs, traces, and metrics
Workflows
Organize steps into workflows