A Step-by-Step Tutorial: From Basic API to Streaming AI Agents
This comprehensive tutorial demonstrates building an intelligent pet management system with Motia, progressively introducing concepts from simple REST APIs to advanced streaming AI agents. Each section builds upon the previous, showcasing real-world patterns across TypeScript, JavaScript, and Python.
This tutorial is structured as a progressive learning path where each level adds complexity and demonstrates new Motia capabilities:
Level 1: API Endpoints β Basic CRUD operations
β
Level 2: Background Jobs β Async processing (Queue + Cron)
β
Level 3: Workflow Orchestrator β Centralized state management
β
Level 4: AI Agents β Intelligent decision making
β
Level 5: Streaming AI Agents β Real-time updates with SSE
By the end of this tutorial, you'll have a complete pet management system with:
- β RESTful APIs - Full CRUD operations for pet records
- β Background Jobs - Queue-based and scheduled async processing
- β Workflow Orchestration - Automated lifecycle management with guard enforcement
- β AI Decision Making - OpenAI-powered health and adoption reviews
- β Real-Time Streaming - Server-Sent Events for live progress updates
- β Multi-Language Support - Identical functionality in TypeScript, JavaScript, and Python
- Multi-language support (TypeScript, JavaScript, Python)
- RESTful API design with proper HTTP methods
- Request validation using Zod
- File-based JSON storage
- Standard error handling
- Queue-Based Jobs: Event-triggered async processing
- Cron-Based Jobs: Scheduled maintenance tasks
- Soft delete pattern with 30-day retention
- Non-blocking API responses
- Event-driven job triggering
- Centralized state management
- Automated lifecycle transitions
- Guard enforcement for valid transitions
- Staff decision points vs automatic progressions
- Status validation and rejection handling
- AI Profile Enrichment: Automatic pet profile generation using OpenAI
- Health Review Agent: AI-driven health assessments with emit selection
- Adoption Review Agent: AI-driven adoption readiness evaluation
- Structured decision artifacts with rationale
- Idempotent decision caching
- Real-Time SSE Streaming: Live progress updates during pet creation
- Progressive Updates: Stream messages as background jobs execute
- AI Enrichment Streaming: Real-time AI profile generation progress
- Health Check Streaming: Live quarantine and health status updates
- Orchestrator Streaming: Status transition notifications
- Non-Blocking UX: Immediate API response with ongoing updates
-
Install Dependencies
npm install pip install -r requirements.txt
-
Set Up Environment Variables
Create a
.envfile in the project root:# .env OPENAI_API_KEY=your_openai_api_key_hereGet your OpenAI API key:
- Visit OpenAI Platform
- Create an account or sign in
- Generate a new API key
- Copy the key and add it to your environment
-
Start Motia Server
npm run dev # or motia dev -
Open Workbench
- Navigate to Motia Workbench in your browser
- Select the appropriate workflow (
TsPetManagement,JsPetManagement, orPyPetManagement) - View the visual workflow diagram showing all steps and connections
The foundation of our system is a RESTful API for pet management. This level demonstrates basic API design, validation, and data persistence.
All three languages provide identical CRUD functionality:
| Method | Endpoint | Description |
|---|---|---|
| POST | /ts/pets |
Create a new pet |
| GET | /ts/pets |
List all pets |
| GET | /ts/pets/:id |
Get pet by ID |
| PUT | /ts/pets/:id |
Update pet |
| DELETE | /ts/pets/:id |
Soft delete pet |
| Method | Endpoint | Description |
|---|---|---|
| POST | /js/pets |
Create a new pet |
| GET | /js/pets |
List all pets |
| GET | /js/pets/:id |
Get pet by ID |
| PUT | /js/pets/:id |
Update pet |
| DELETE | /js/pets/:id |
Soft delete pet |
| Method | Endpoint | Description |
|---|---|---|
| POST | /py/pets |
Create a new pet |
| GET | /py/pets |
List all pets |
| GET | /py/pets/:id |
Get pet by ID |
| PUT | /py/pets/:id |
Update pet |
| DELETE | /py/pets/:id |
Soft delete pet |
{
"id": "1",
"name": "Buddy",
"species": "dog",
"ageMonths": 24,
"status": "new",
"createdAt": 1640995200000,
"updatedAt": 1640995200000,
"weightKg": 15.5,
"symptoms": ["coughing", "lethargy"],
"notes": "Welcome to our pet store!",
"nextFeedingAt": 1641081600000,
"deletedAt": null,
"purgeAt": null,
"profile": {
"bio": "Buddy is a friendly and energetic golden retriever...",
"breedGuess": "Golden Retriever Mix",
"temperamentTags": ["friendly", "energetic", "loyal"],
"adopterHints": "Perfect for active families..."
}
}# Create a pet
curl -X POST http://localhost:3000/ts/pets \
-H "Content-Type: application/json" \
-d '{
"name": "Buddy",
"species": "dog",
"ageMonths": 24
}'
# List all pets
curl http://localhost:3000/ts/pets
# Get specific pet
curl http://localhost:3000/ts/pets/1
# Update pet
curl -X PUT http://localhost:3000/ts/pets/1 \
-H "Content-Type: application/json" \
-d '{"ageMonths": 25}'
# Soft delete pet
curl -X DELETE http://localhost:3000/ts/pets/1Building on Level 1, we add asynchronous background processing to handle time-consuming tasks without blocking API responses.
Triggered by: Creating a pet via any POST /*/pets endpoint
Purpose: Sets next feeding reminder and adds welcome notes after pet creation
Process:
- Pet creation API completes immediately with
status: 201 - API emits language-specific event (e.g.,
ts.feeding.reminder.enqueued) - Background job picks up the event and processes asynchronously
- Job adds welcome notes, calculates next feeding time, and sets status to
in_quarantine - Job emits completion event with processing metrics
Console Output:
πΎ Pet created { petId: '1', name: 'Buddy', species: 'dog', status: 'new' }
π Setting next feeding reminder { petId: '1', enqueuedAt: 1640995200000 }
β
Next feeding reminder set { petId: '1', notes: 'Welcome to our pet store!...', nextFeedingAt: '2022-01-02T00:00:00.000Z' }
Schedule: Daily at 2:00 AM (0 2 * * *)
Purpose: Permanently removes pets that have been soft deleted and are past their purge date
Process:
- Scans for pets with
status="deleted"andpurgeAt <= now - Permanently removes matching pets from the datastore
- Emits audit events for each purged pet
- Reports completion statistics
Console Output:
π Deletion Reaper started - scanning for pets to purge
π Pet permanently purged { petId: '1', name: 'Buddy', deletedAt: '2022-01-01T00:00:00.000Z', purgeAt: '2022-01-31T00:00:00.000Z' }
β
Deletion Reaper completed { totalScanned: 5, purgedCount: 2, failedCount: 0 }
# Create a pet and watch console for background job processing
curl -X POST http://localhost:3000/ts/pets \
-H "Content-Type: application/json" \
-d '{"name": "Whiskers", "species": "cat", "ageMonths": 12}'
# Check pet record after job completion (wait a few seconds)
curl http://localhost:3000/ts/pets/1
# Test soft delete
curl -X DELETE http://localhost:3000/ts/pets/1
# Verify pet is marked as deleted but still exists
curl http://localhost:3000/ts/pets/1Level 3 introduces a Pet Lifecycle Orchestrator that manages all status transitions through a realistic shelter workflow with guard enforcement.
Centralized Control: Only the orchestrator can modify pet.status. All other components emit events.
Staff-Driven Workflow: Status changes require staff decisions through the existing PUT API.
Event-Driven: Orchestrator subscribes to domain events and validates transition rules.
Language Isolation: Each language has its own orchestrator with language-specific event namespaces.
new- Initial status when pet is createdin_quarantine- Pet is in quarantine after feeding reminder setuphealthy- Pet is healthy and cleared from quarantineavailable- Pet is ready for adoptionpending- Adoption application in progressadopted- Pet has been adoptedill- Pet is identified as illunder_treatment- Pet is receiving medical treatmentrecovered- Pet has recovered from illnessdeleted- Pet is soft deleted (outside orchestrator)
| Trigger Event | From Status | To Status | Action Type |
|---|---|---|---|
feeding.reminder.completed |
new |
in_quarantine |
Automatic |
status.update.requested |
in_quarantine |
healthy |
Staff Decision |
status.update.requested |
healthy |
available |
Automatic Progression |
status.update.requested |
healthy, in_quarantine, available |
ill |
Staff Assessment |
status.update.requested |
ill |
under_treatment |
Automatic Progression |
status.update.requested |
under_treatment |
recovered |
Staff Decision |
status.update.requested |
recovered |
healthy |
Automatic Progression |
status.update.requested |
available |
pending |
Staff Decision |
status.update.requested |
pending |
adopted |
Staff Decision |
POST /pets β new
β (SetNextFeedingReminder completes - automatic)
in_quarantine
β (Staff health check via PUT API)
healthy
β (AUTOMATIC - orchestrator progression)
available
β (Staff adoption process via PUT API)
pending β adopted
Illness Can Happen Anytime:
in_quarantine β ill (Staff finds illness)
healthy β ill (Staff assessment)
available β ill (Staff discovers illness)
β (AUTOMATIC - orchestrator starts treatment)
under_treatment
β (Staff marks recovered via PUT API)
recovered
β (AUTOMATIC - orchestrator clears recovery)
healthy
β (AUTOMATIC - orchestrator marks ready)
available
# 1. Create a pet - starts with status=new, automatically moves to in_quarantine
curl -X POST http://localhost:3000/ts/pets \
-H "Content-Type: application/json" \
-d '{"name": "Buddy", "species": "dog", "ageMonths": 24}'
# 2. Check current status (should be in_quarantine after feeding reminder)
curl http://localhost:3000/ts/pets/1
# 3. Staff health check - clear from quarantine to healthy
curl -X PUT http://localhost:3000/ts/pets/1 \
-H "Content-Type: application/json" \
-d '{"status": "healthy"}'
# 4. Check status (should be available - automatic progression)
curl http://localhost:3000/ts/pets/1
# 5. Mark as ill
curl -X PUT http://localhost:3000/ts/pets/1 \
-H "Content-Type: application/json" \
-d '{"status": "ill"}'
# 6. Check status (should be under_treatment - automatic progression)
curl http://localhost:3000/ts/pets/1Level 4 introduces AI-powered agents that make intelligent decisions based on pet context using OpenAI.
Trigger: Automatic on pet.created event
Purpose: Generate detailed pet profiles using AI
AI-Generated Fields:
bio- Warm, engaging 2-3 sentence descriptionbreedGuess- AI's best guess at breed or breed mixtemperamentTags- Array of 3-5 personality traitsadopterHints- Practical advice for potential adopters
Example Output:
{
"profile": {
"bio": "Luna is a graceful and independent cat with striking green eyes who enjoys sunny windowsills and gentle head scratches.",
"breedGuess": "Domestic Shorthair",
"temperamentTags": ["independent", "calm", "affectionate", "observant"],
"adopterHints": "Ideal for singles or couples seeking a low-maintenance companion. Prefers quiet environments."
}
}Endpoint: POST /ts/pets/:id/health-review
Purpose: AI evaluates pet health and chooses appropriate action
Available Decisions:
emit.health.treatment_requiredβ Pet needs medical treatmentemit.health.no_treatment_neededβ Pet is healthy
Decision Process:
- Analyze pet symptoms, age, species, current status
- LLM chooses appropriate emit based on context
- Provides structured rationale for decision
- Orchestrator consumes emit and applies transitions
Endpoint: POST /ts/pets/:id/adoption-review
Purpose: AI evaluates adoption readiness
Available Decisions:
emit.adoption.needs_dataβ Pet needs additional dataemit.adoption.readyβ Pet is ready for adoption
Decision Artifact:
{
"petId": "1",
"agentType": "health-review",
"timestamp": 1640995200000,
"parsedDecision": {
"chosenEmit": "emit.health.treatment_required",
"rationale": "Pet shows concerning symptoms of coughing and lethargy that require veterinary evaluation."
},
"success": true
}# Test AI Profile Enrichment (automatic)
curl -X POST http://localhost:3000/ts/pets \
-H "Content-Type: application/json" \
-d '{"name": "Luna", "species": "cat", "ageMonths": 18}'
# Wait 2-3 seconds, then check for AI-generated profile
curl http://localhost:3000/ts/pets/1
# Test Health Review Agent with symptoms
curl -X POST http://localhost:3000/ts/pets \
-H "Content-Type: application/json" \
-d '{
"name": "Max",
"species": "dog",
"ageMonths": 36,
"symptoms": ["coughing", "lethargy", "fever"]
}'
# Trigger health review
curl -X POST http://localhost:3000/ts/pets/2/health-review
# Test Adoption Review Agent
curl -X POST http://localhost:3000/ts/pets/1/adoption-reviewThe Final Level: Building on all previous levels, we add real-time streaming to provide immediate user feedback while background processes execute.
Traditional APIs return a single response after all processing completes. With Motia's native Streams API, your API can return immediately with a stream that updates in real-time as background jobs, AI agents, and orchestrators process asynchronously.
The streaming feature is defined in pet-creation.stream.ts:
import { StreamConfig } from 'motia'
import { z } from 'zod'
export const config: StreamConfig = {
name: 'petCreation',
schema: z.object({
message: z.string()
}),
baseConfig: {
storageType: 'default',
},
}This stream is available as context.streams.petCreation in all steps within the flow.
// create-pet.step.ts
const result = await streams.petCreation.set(traceId, 'message', {
message: `Pet ${pet.name} (ID: ${pet.id}) created successfully`
});
return {
status: 201,
body: result // Returns stream immediately
};// set-next-feeding-reminder.job.step.ts
await streams.petCreation.set(traceId, 'message', {
message: `Pet ${pet.name} entered quarantine period`
});
await streams.petCreation.set(traceId, 'message', {
message: `Health check passed for ${pet.name} - no symptoms found`
});
await streams.petCreation.set(traceId, 'message', {
message: `${pet.name} is healthy and ready for adoption! β
`
});// ai-profile-enrichment.step.ts
await streams.petCreation.set(traceId, 'enrichment_started', {
message: `AI enrichment started for ${pet.name}`
});
await streams.petCreation.set(traceId, `progress_bio`, {
message: `Generated bio for ${pet.name}`
});
await streams.petCreation.set(traceId, 'completed', {
message: `AI enrichment completed for ${pet.name}`,
profile: generatedProfile
});// pet-lifecycle-orchestrator.step.ts
await streams.petCreation.set(traceId, transitionTo, {
message: `Status transition: ${currentStatus} β ${transitionTo}`,
petId,
timestamp: Date.now()
});When you create a pet, the API returns a stream object immediately:
{
"streamId": "trace-abc123",
"updates": [
{
"type": "message",
"timestamp": 1640995200000,
"data": {
"message": "Pet Buddy (ID: 1) created successfully - Species: dog, Age: 24 months, Status: new"
}
}
]
}As background jobs execute, the stream receives real-time updates:
{
"streamId": "trace-abc123",
"updates": [
{
"type": "message",
"timestamp": 1640995200000,
"data": { "message": "Pet Buddy (ID: 1) created successfully..." }
},
{
"type": "message",
"timestamp": 1640995201500,
"data": { "message": "Pet Buddy entered quarantine period" }
},
{
"type": "message",
"timestamp": 1640995203000,
"data": { "message": "Health check passed for Buddy - no symptoms found" }
},
{
"type": "enrichment_started",
"timestamp": 1640995201000,
"data": { "message": "AI enrichment started for Buddy" }
},
{
"type": "progress_bio",
"timestamp": 1640995202500,
"data": { "message": "Generated bio for Buddy" }
},
{
"type": "completed",
"timestamp": 1640995204000,
"data": {
"message": "AI enrichment completed for Buddy",
"profile": { "bio": "...", "breedGuess": "...", ... }
}
},
{
"type": "message",
"timestamp": 1640995205000,
"data": { "message": "Buddy is healthy and ready for adoption! β
" }
}
]
}# Create a healthy pet without symptoms
curl -X POST http://localhost:3000/ts/pets \
-H "Content-Type: application/json" \
-d '{
"name": "Luna",
"species": "cat",
"ageMonths": 18
}'Expected Stream Updates:
- β "Pet Luna (ID: X) created successfully"
- π "Pet Luna entered quarantine period"
- π€ "AI enrichment started for Luna"
- π "Generated bio for Luna"
- π "Generated breed guess for Luna"
- β "AI enrichment completed for Luna"
- β "Health check passed for Luna - no symptoms found"
- β "Luna is healthy and ready for adoption! β "
# Create a pet with symptoms
curl -X POST http://localhost:3000/ts/pets \
-H "Content-Type: application/json" \
-d '{
"name": "Max",
"species": "dog",
"ageMonths": 36,
"symptoms": ["coughing", "lethargy", "fever"],
"weightKg": 25.5
}'Expected Stream Updates:
- β "Pet Max (ID: X) created successfully"
- π "Pet Max entered quarantine period"
- π€ "AI enrichment started for Max"
- π AI profile generation progress updates
- β "AI enrichment completed for Max"
β οΈ "Health check failed for Max - symptoms detected: coughing, lethargy, fever"- β "Max needs medical treatment β"
You can also fetch the stream directly to see updates:
# Get stream updates (replace STREAM_ID with actual streamId from response)
curl http://localhost:3000/streams/STREAM_ID| Traditional API | Streaming API |
|---|---|
| β³ Wait for all processing | β Immediate response |
| π€· No progress visibility | π Real-time progress updates |
| β Timeout on long operations | β No timeout issues |
| π΄ Poor user experience | π Engaging user experience |
| π Silent background jobs | π’ Visible workflow execution |
- Order Processing: Show shipping, payment, fulfillment status in real-time
- Document Generation: Stream progress as AI generates reports/documents
- Data Import: Show validation, processing, completion status
- ML Model Training: Stream training progress, metrics, completion
- Video Processing: Stream transcoding, quality checks, upload progress
The Motia Workbench provides a visual representation of the entire workflow showing all 5 levels:
This screenshot shows the complete TsPetManagement workflow including:
- API Steps (Left side) - Create, Read, Update, Delete operations
- Background Jobs -
set-next-feeding-reminder(queue-based),deletion-reaper(cron-based) - Orchestrator (Center) -
pet-lifecycle-orchestratormanaging all state transitions - AI Agents -
health-review-agent,adoption-review-agent,ai-profile-enrichment - Stream β -
pet-creation.streamproviding real-time SSE updates - Staff Actions -
treatment-scheduler,adoption-posting,recovery-monitor - Event Connections - Visual arrows showing data flow between all components
The diagram clearly visualizes how the progressive tutorial builds from simple APIs (Level 1) through background jobs (Level 2), orchestration (Level 3), AI agents (Level 4), and finally streaming (Level 5).
steps/
βββ javascript/
β βββ create-pet.step.js # POST /js/pets (with streaming)
β βββ get-pets.step.js # GET /js/pets
β βββ get-pet.step.js # GET /js/pets/:id
β βββ update-pet.step.js # PUT /js/pets/:id
β βββ delete-pet.step.js # DELETE /js/pets/:id
β βββ set-next-feeding-reminder.job.step.js # Background job (streams updates)
β βββ deletion-reaper.cron.step.js # Cron job (daily cleanup)
β βββ pet-lifecycle-orchestrator.step.js # Workflow orchestrator (streams transitions)
β βββ ai-profile-enrichment.step.js # AI profile generation (streams progress)
β βββ health-review-agent.step.js # POST /js/pets/:id/health-review
β βββ adoption-review-agent.step.js # POST /js/pets/:id/adoption-review
β βββ treatment-scheduler.step.js # Staff action automation
β βββ adoption-posting.step.js # Staff action automation
β βββ recovery-monitor.step.js # Staff action automation
β βββ pet-creation.stream.js # Stream configuration β
β βββ js-store.js # Data persistence layer
β
βββ typescript/
β βββ create-pet.step.ts # POST /ts/pets (with streaming)
β βββ get-pets.step.ts # GET /ts/pets
β βββ get-pet.step.ts # GET /ts/pets/:id
β βββ update-pet.step.ts # PUT /ts/pets/:id
β βββ delete-pet.step.ts # DELETE /ts/pets/:id
β βββ set-next-feeding-reminder.job.step.ts # Background job (streams updates)
β βββ deletion-reaper.cron.step.ts # Cron job (daily cleanup)
β βββ pet-lifecycle-orchestrator.step.ts # Workflow orchestrator (streams transitions)
β βββ ai-profile-enrichment.step.ts # AI profile generation (streams progress)
β βββ health-review-agent.step.ts # POST /ts/pets/:id/health-review
β βββ adoption-review-agent.step.ts # POST /ts/pets/:id/adoption-review
β βββ treatment-scheduler.step.ts # Staff action automation
β βββ adoption-posting.step.ts # Staff action automation
β βββ recovery-monitor.step.ts # Staff action automation
β βββ pet-creation.stream.ts # Stream configuration β
β βββ agent-decision-framework.ts # Shared agent decision logic
β βββ ts-store.ts # Data persistence layer
β
βββ python/
β βββ create_pet_step.py # POST /py/pets (with streaming)
β βββ get_pets_step.py # GET /py/pets
β βββ get_pet_step.py # GET /py/pets/:id
β βββ update_pet_step.py # PUT /py/pets/:id
β βββ delete_pet_step.py # DELETE /py/pets/:id
β βββ set_next_feeding_reminder.job_step.py # Background job (streams updates)
β βββ deletion_reaper.cron_step.py # Cron job (daily cleanup)
β βββ pet_lifecycle_orchestrator_step.py # Workflow orchestrator (streams transitions)
β βββ ai_profile_enrichment_step.py # AI profile generation (streams progress)
β βββ health_review_agent_step.py # POST /py/pets/:id/health-review
β βββ adoption_review_agent_step.py # POST /py/pets/:id/adoption-review
β βββ treatment_scheduler_step.py # Staff action automation
β βββ adoption_posting_step.py # Staff action automation
β βββ recovery_monitor_step.py # Staff action automation
β βββ pet_creation.stream.py # Stream configuration β
β βββ services/
β βββ pet_store.py # Data persistence layer
β βββ types.py # Type definitions
β
βββ motia-workbench.json # Workflow configuration
Follow this step-by-step guide to experience all 5 levels in sequence:
# Create a healthy pet
curl -X POST http://localhost:3000/ts/pets \
-H "Content-Type: application/json" \
-d '{"name": "Buddy", "species": "dog", "ageMonths": 24}'
# Expected: Immediate API response with stream
# Expected: Background job processes feeding reminder (watch console)
# Expected: AI enrichment generates profile (watch console)# Get the pet to see final state
curl http://localhost:3000/ts/pets/1
# Expected: Pet with status "available", complete profile, notes, nextFeedingAt# Try invalid transition
curl -X PUT http://localhost:3000/ts/pets/1 \
-H "Content-Type: application/json" \
-d '{"status": "adopted"}'
# Expected: Transition rejected (can't go directly from available to adopted)
# Valid transition: pending adoption
curl -X PUT http://localhost:3000/ts/pets/1 \
-H "Content-Type: application/json" \
-d '{"status": "pending"}'
# Valid transition: complete adoption
curl -X PUT http://localhost:3000/ts/pets/1 \
-H "Content-Type: application/json" \
-d '{"status": "adopted"}'# Create a pet with symptoms
curl -X POST http://localhost:3000/ts/pets \
-H "Content-Type: application/json" \
-d '{
"name": "Max",
"species": "dog",
"ageMonths": 36,
"symptoms": ["coughing", "lethargy", "fever"],
"weightKg": 25.5
}'
# Wait for pet to reach "healthy" or "available" status
# Then trigger AI health review
curl -X POST http://localhost:3000/ts/pets/2/health-review
# Expected: AI agent chooses "treatment_required"
# Expected: Orchestrator automatically transitions: healthy β ill β under_treatment# Trigger adoption review on available pet
curl -X POST http://localhost:3000/ts/pets/2/adoption-review
# Expected: AI agent evaluates readiness
# Expected: Decision artifact with rationale# Test JavaScript implementation
curl -X POST http://localhost:3000/js/pets \
-H "Content-Type: application/json" \
-d '{"name": "JS_Pet", "species": "cat", "ageMonths": 12}'
curl -X POST http://localhost:3000/js/pets/1/health-review
# Test Python implementation
curl -X POST http://localhost:3000/py/pets \
-H "Content-Type: application/json" \
-d '{"name": "Py_Pet", "species": "bird", "ageMonths": 6}'
curl -X POST http://localhost:3000/py/pets/1/health-review
# Expected: Identical behavior across all three languagesThis progressive tutorial demonstrates:
β
RESTful API design with proper HTTP methods
β
Request validation using Zod
β
File-based data persistence
β
Multi-language implementation (TypeScript, JavaScript, Python)
β
Queue-based jobs (event-triggered)
β
Cron-based jobs (scheduled)
β
Non-blocking API responses
β
Event-driven job triggering
β
Soft delete pattern with cleanup
β
Centralized state management
β
Guard enforcement for valid transitions
β
Automatic progressions vs staff decisions
β
Status validation and rejection handling
β
Event-driven workflow control
β
AI Profile Enrichment (content generation)
β
Agentic Decision Making (routing decisions)
β
Structured decision artifacts with rationale
β
Idempotent decision caching
β
OpenAI integration patterns
β
Real-time Server-Sent Events (SSE)
β
Progressive updates during async processing
β
Stream initialization and management
β
Multi-step workflow streaming
β
Non-blocking user experience
β
Visible workflow execution
By completing this tutorial, you've learned:
- Progressive Complexity: How to build from simple APIs to advanced streaming AI agents
- Motia Patterns: API steps, event steps, cron steps, streams, and agent patterns
- Real-World Architecture: Orchestrators, background jobs, AI integration, streaming
- Multi-Language Development: Identical functionality across TypeScript, JavaScript, Python
- Production-Ready Features: Validation, error handling, idempotency, guard enforcement
- Modern UX: Real-time feedback and progressive updates
Now that you've completed the tutorial, you can:
- Customize the Workflow: Add your own status states and transition rules
- Extend AI Agents: Create new agent endpoints with custom decision logic
- Add More Streams: Implement streaming in other workflows
- Build Your Own: Apply these patterns to your own domain and use cases
- Explore Motia Docs: Learn about advanced features and patterns
- Motia Documentation
- Motia Examples Repository
- OpenAI API Documentation
- Server-Sent Events (SSE) Guide
This is a demonstration project for Motia workflow capabilities. Feel free to use it as a template for your own projects!
Built with β€οΈ using Motia - The Modern Workflow Platform
