Skip to content

Lesson 2: Module 02: Your First Reasoning Step

Build a machine that uses an LLM to analyze text and return structured data.

Learning Objectives

  • Write an ask step with model, prompt, and structured output
  • Choose the right model tier for a task
  • Use returns to get predictable, typed results

Complexity Ladder: Level 1 (Linear), single-step reasoning with no branching or looping.

The Concept: Structured AI Reasoning

If you have used ChatGPT or Claude, you already understand the core idea behind an ask step. When you type a message in ChatGPT, you are sending a prompt to an LLM (large language model, an AI like Claude or GPT) and getting text back. An ask step does the same thing, but with structure and guardrails.

Think of it like ordering at a restaurant. In a normal ChatGPT conversation, you ask for “something good” and the chef improvises. With an ask step, you hand the chef a specific order form: “I want a sentiment field that must be one of these four values, a category from this list, and a confidence score between 0 and 1.” The chef (the LLM) still uses creativity and intelligence, but the shape of what comes back is guaranteed.

The ask step is mashin’s primitive for LLM inference (sending a prompt to an AI model and getting a response back). Every agent and AI workflow you build starts here.

Here is how an ask step maps to concepts you may already know:

ChatGPT / Claude Mashin ask Step
┌──────────────────┐ ┌──────────────────────────────────┐
│ System prompt │ ──────────► │ with role "..." │
│ User message │ ──────────► │ with task "..." │
│ JSON mode │ ──────────► │ returns │
│ Model selection │ ──────────► │ ask name, using: "model" │
└──────────────────┘ └──────────────────────────────────┘

If you have used ChatGPT’s JSON mode or function calling, returns is the same idea: you tell the AI the exact shape of the response you want, and the runtime enforces it.

An ask step has three key parts:

  • using: which LLM to use (e.g., "anthropic:claude-haiku-4")
  • with role the system prompt (instructions that set the LLM’s role and personality, like “You are a customer feedback analyst”)
  • with task the user prompt (the specific task or question for this call)
  • returns the shape of the response (types and constraints), also called structured output (a response forced into a specific format rather than free-form text)

The returns block is what makes mashin ask steps reliable. Instead of hoping the LLM returns JSON (a text format for structured data, like {"key": "value"}) in the right format, you declare the schema and the runtime enforces it.

Start With Koda

Koda requires a free account. Sign in or create an account to use Koda exercises throughout this course. If you’re not signed in yet, read on; the exercises will be here when you’re ready.

Before writing code by hand, try building this with Koda (Mashin’s intelligent development environment):

Ask Koda:

“Build a machine that classifies customer feedback into categories (product, service, pricing, shipping) with sentiment (positive, negative, neutral) and a confidence score. Use a fast model.”

Examine the machine Koda generates. Check that it uses claude-haiku-4 (fast tier), has a low temperature (how creative vs consistent the AI is; low means consistent, high means creative), and uses returns with typed fields. If Koda uses Sonnet, ask: “Can we use Haiku since this is a classification task?”

This gives you a working starting point. The rest of this module explains every part of what Koda generated, so you understand it fully.

Building It: Sentiment Analyzer

Let’s build a machine that classifies customer feedback into categories with a confidence score.

machine sentiment_analyzer "Sentiment Analyzer"
// What the machine receives when invoked
accepts
feedback as string, is required
// What the machine returns when it finishes
responds with
sentiment as string
category as string
confidence as decimal
summary as string
implements
// An ask step sends a prompt to an LLM and gets structured output back
ask classify, using: "anthropic:claude-haiku-4"
// with role = the system prompt (sets the LLM's role, stays the same across calls)
with role "You are a customer feedback analyst. Classify feedback accurately and concisely. Base your confidence score on how clear the sentiment is."
// with task = the user prompt (the specific task, changes with each input)
with task "Classify this customer feedback:\n\n${input.feedback}"
// returns = the exact shape of the response the LLM must return
returns
sentiment as string, is required
category as string, is required
confidence as decimal, is required
summary as string, is required

Breaking It Down

Model selection: We use anthropic:claude-haiku-4 because classification is a fast-tier task. It doesn’t need the reasoning power of Sonnet or Opus. Haiku is cheaper and faster.

Temperature: 0.1 keeps output consistent. For classification, you want the same input to produce the same output. Higher temperatures add randomness, useful for creative tasks but harmful for analysis.

with role vs with task: The with role block sets the LLM’s role (system prompt). The with task block provides the specific task (user prompt). Keep with role stable across calls; vary with task with each input.

returns: Each field has a name, type, and optional constraints. The is required modifier ensures the field is always present.

Variable Access

Mashin provides helper functions to access data from inputs and previous steps:

ExpressionPurposeExample
input.<field>Read machine inputinput.feedback
steps.<name>.<field>Read a step’s output fieldsteps.classify.sentiment
steps.<name>Read a step’s entire outputsteps.classify
state.<field>Read machine statestate.counter

These expressions work in with task strings via ${expr} interpolation and in compute expressions.

Multi-Step Reasoning

One powerful pattern: chain multiple ask steps together, each focused on a single task.

implements
// Step 1: Extract key entities using a fast (cheap) model
ask extract, using: "anthropic:claude-haiku-4"
with task "Extract named entities from: ${input.text}"
returns
entities as list
// Step 2: Analyze relationships using a balanced (smarter) model
ask analyze, using: "anthropic:claude-sonnet-4"
with task "Given these entities: ${steps.extract.entities}\nFrom this text: ${input.text}\n\nDescribe the relationships between them."
returns
relationships as list
summary as string

Each step does one thing well. The fast model handles extraction; the balanced model handles analysis. This is cheaper and more reliable than asking one model to do everything at once.

Key Syntax

ask name, using: "provider:model-name"
with role "system prompt" // Optional: LLM role/personality
with task "user prompt with ${input.field} interpolation" // Required: the task
returns // Optional but recommended: enforces response shape
field_name as type // string, number, decimal, boolean, map, list

Model Tiers

TierModelsUse For
Fastanthropic:claude-haiku-4, openai:gpt-4o-miniClassification, extraction, validation
Balancedanthropic:claude-sonnet-4, openai:gpt-4oSummarization, generation, reasoning
Powerfulanthropic:claude-opus-4, openai:o1Complex research, multi-document analysis

Temperature Guide

TaskTemperatureWhy
Classification0.0-0.2Consistency matters
Extraction0.1-0.3Accuracy over creativity
Content writing0.5-0.8Creative variety
Brainstorming0.8-1.0Maximum exploration

Common Mistakes

  1. Using one model for everything. Match the model to the task. A 10-step machine using Sonnet everywhere costs 30x more than using Haiku where appropriate.

  2. Putting too much in one ask step. “Analyze, extract entities, classify sentiment, summarize, and rate importance”: split this into 5 focused steps. Each step should do one thing.

  3. Skipping returns. Without it, you get unstructured text. With it, you get typed, validated data you can pass to the next step reliably.

What’s Next

In Module 03, you’ll learn the key insight that turns an ask step into an agent: giving it tools.