Motia Icon

Dynamic Sentiment Analysis

Sometimes you don't just want a simple "prompt => response." Instead, you want the LLM to decide how to proceed. Below is a minimal example that:

  1. Receives user input via POST /api/analyze-sentiment
  2. Calls OpenAI and instructs the LLM to return JSON with a sentiment field
  3. Parses that JSON and emits different events depending on whether sentiment is "positive" or "negative" (or anything else)
  4. Two specialized responders handle each sentiment separately

The Steps

analyzeSentimentApi.step.ts
openAiAnalyzeSentiment.step.ts
handlePositive.step.ts
handleNegative.step.ts
// Receives user text, emits "openai.analyzeSentimentRequest".
import { ApiRouteConfig, StepHandler } from 'motia'
import { z } from 'zod'
 
export const config: ApiRouteConfig = {
  type: 'api',
  name: 'Analyze Sentiment (API)',
  path: '/api/analyze-sentiment',
  method: 'POST',
  emits: ['openai.analyzeSentimentRequest'],
  bodySchema: z.object({
    text: z.string().min(1, 'text is required'),
  }),
  flows: ['sentiment-demo'],
}
 
export const handler: StepHandler<typeof config> = async (req, { emit, logger }) => {
  const { text } = req.body
 
  logger.info('[AnalyzeSentimentAPI] Received text', { text })
 
  // Emit an event to call OpenAI
  await emit({
    topic: 'openai.analyzeSentimentRequest',
    data: { text },
  })
 
  // Return right away
  return {
    status: 200,
    body: { status: 'Accepted', message: 'Your text is being analyzed' },
  }
}

Visual Overview

Here's how the events chain together:

Flow: Sentiment Analysis Steps
  1. Analyze Sentiment (API) → emits openai.analyzeSentimentRequest
  2. OpenAI Sentiment Analyzer → calls OpenAI, parses JSON →
    • If sentiment: "positive" → emits openai.positiveSentiment
    • Else → emits openai.negativeSentiment
  3. Positive Sentiment Responder or Negative Sentiment Responder

Trying It Out

Install Dependencies

pnpm install motia openai

Create Project Structure

analyzeSentimentApi.step.ts
openAiAnalyzeSentiment.step.ts
handlePositive.step.ts
handleNegative.step.ts

Set Environment Variables

export OPENAI_API_KEY="sk-..."

Run the Project

pnpm motia dev

Test the API

curl -X POST http://localhost:3000/api/analyze-sentiment \
  -H "Content-Type: application/json" \
  -d '{"text":"I absolutely love this new device!"}'

Check your logs - you should see either the [Positive Responder] or [Negative Responder] step firing, depending on the LLM's JSON output.

Extend Further

Here are some ways to build upon this example:

  • Tweak the system instructions to force certain outputs or include more details
  • Create more specialized responders (like "neutralSentiment")
  • Integrate a notification step (Slack, database, etc.)

Try it out, see the branching logic in action, and enjoy skipping all the boring boilerplate!

Need help? See our Community Resources for questions, examples, and discussions.

On this page