Skip to content
Developer Preview — APIs and language features may change before 1.0

Lesson 1: Module 01: What Are Agents?

Learn the difference between agents and workflows, and when NOT to use an agent.

  • Define what an AI agent is and how it differs from a workflow
  • Apply the Complexity Ladder to decide which pattern fits a task
  • Recognize signs of over-engineering

Complexity Ladder: This module introduces all five levels, from linear workflows to autonomous agents.

Think of a workflow (a predefined sequence of steps) like an assembly line in a factory. Every item follows the same path, every time. The conveyor belt doesn’t think about where to go next — the route is fixed when you build the factory.

An agent (software that uses an AI to make decisions) is more like a human worker with a checklist and a brain. They look at the situation, decide what to do next, and might take a completely different path depending on what they find. The key word is decide — an LLM (large language model — an AI like Claude or GPT) doesn’t just process data, it chooses what to do next based on the situation.

Here is the fundamental difference:

Workflow (fixed path, same every time) Agent (dynamic, AI chooses the path)
┌─────────────────────────────────────┐ ┌─────────────────────────────────────┐
│ │ │ │
│ ┌───┐ ┌───┐ ┌───┐ │ │ ┌───┐ ┌─────────┐ │
│ │ A │────►│ B │────►│ C │ │ │ │ A │────►│ AI │ │
│ └───┘ └───┘ └───┘ │ │ └───┘ │ Decides │ │
│ │ │ └────┬────┘ │
│ Always A → B → C. │ │ ┌──────┼──────┐ │
│ Every time. │ │ ▼ ▼ ▼ │
│ │ │ ┌───┐ ┌───┐ ┌───┐ │
│ │ │ │ B │ │ C │ │ D │ │
│ │ │ └───┘ └───┘ └───┘ │
│ │ │ │
│ │ │ Path depends on what AI finds. │
└─────────────────────────────────────┘ └─────────────────────────────────────┘

Most tasks you’ll encounter are workflows. A support ticket classifier, a data pipeline, a webhook router — these all follow predictable paths. Adding an agent to a predictable task doesn’t make it smarter. It makes it slower, more expensive, and less reliable.

mashin’s philosophy: mashin is the medium for governed intelligence, a deterministic foundation for governing intelligent software. Code computes. Machines act. All effects are governed. compute steps are pure (no network or file access by construction). All side effects go through action machines (dedicated machines that perform a single governed operation like an HTTP request or file read). This means even when you build an agent, its actions produce a complete audit trail (a log of every decision and action), intelligence you can understand, own, and trust.

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 diving into the details, try this with Koda (Mashin’s intelligent development environment):

Ask Koda:

“What kind of machine should I build to categorize incoming support tickets into billing, technical, and general categories, then forward them to the right team?”

Koda should recommend a simple workflow (Level 1-2), not an agent. The task is predictable — every ticket gets categorized and forwarded. If Koda suggests an agent pattern, push back: “This seems like a simple classification workflow. Can we keep it linear?”

This exercise illustrates the core lesson of this module: most tasks are workflows, and Koda should help you pick the simplest pattern that works.

Always start at Level 1 and only escalate when the task demands it:

Level Pattern Example
1. Linear A -> B -> C Receive webhook -> categorize -> forward
2. Conditional A -> if X then B else C Route to different APIs based on type
3. Iterative A -> for_each -> B Batch processing of records
4. Resilient A -> retry/fallback -> B API call with retry and cache fallback
5. Agentic Dynamic planning Research assistant, debugging helper
// Declare a machine, a self-contained unit of work with a name
machine ticket_router "Support Ticket Router"
// Define what this machine accepts as input
accepts
event_type as string, is required // The type of support event
payload as map, is required // The full event data (a key-value structure)
// Define what this machine returns when it finishes
responds with
forwarded as boolean // Whether the ticket was forwarded
destination as string // Where it was sent
// Steps run in order under behaves
behaves
// An ask step sends a prompt to an LLM and gets structured output back
ask categorize, using: "anthropic:claude-haiku-4"
with task "Categorize this event type: ${input.event_type}"
returns
// choices = a fixed list of allowed values
category as string
// An ask...from step invokes an action machine
ask forward, from: "@mashin/actions/http/post"
url: "https://api.example.com/${steps.categorize.category}/events"
body: input.payload
// A compute step is pure: it assembles the machine's declared outputs and does no I/O
compute report
{forwarded: true, destination: steps.categorize.category}
// A verifies block is the machine's own test suite. `assuming` stands in for a step's
// result, so this runs with no model and no network.
verifies
test "a payment event is categorized and forwarded to that category's endpoint"
assuming categorize {category: "payments"}
assuming forward {status: 202}
given {event_type: "payment.succeeded", payload: {id: "evt_1"}}
expect {forwarded: true, destination: "payments"}

This uses an LLM for classification, but it’s not an agent; the flow is fixed. Categorize, then forward. Every time. Steps under behaves run in order. @mashin/actions (the standard library, pre-built machines that ship with mashin) provides common action machines like @mashin/actions/http/post.

machine research_assistant "Research Assistant"
has agency
accepts
question as string, is required // The research question to answer
responds with
answer as string // The final synthesized answer
sources as list // List of URLs used as sources
behaves
// Cross-run state lives in a STORE; within a run, each step reads prior
// steps by name (steps.<name>.<field>). There is no separate state block.
ask reason, using: "anthropic:claude-sonnet-4"
with task "Question: ${input.question}\nPrevious actions: ${steps.dispatch.history}\n\nDecide: search the web, read a URL, or respond with your answer."
returns
action as string
action_input as map
response as string
// ... tool dispatch and loop back

This is an agent: the LLM decides what to do next based on what it’s already found. The path varies by input.

Task Agent Needed? Why
Webhook -> categorize -> forward No Predictable, linear
Parse CSV -> validate -> store No Deterministic pipeline
Answer question from knowledge base Yes Needs retrieval, grounding
Debug a failing test Yes Iterative analysis, varies by error
Generate report from data Depends Simple aggregation = No; AI synthesis = Yes
Research a topic Yes Open-ended, needs multiple searches

Stop and simplify if you’re:

  • Adding reflection steps to a 3-step workflow
  • Using knowledge retrieval when the logic is deterministic
  • Designing multi-agent systems for single-purpose tasks
  • Adding dynamic planning for predictable inputs
  • Adding memory to stateless transformations
  1. Building an agent when a workflow suffices. If you can enumerate every possible path at design time, it’s a workflow. Use chains and branching.

  2. Confusing “uses an LLM” with “is an agent.” A classification step uses an LLM but follows a fixed flow. An agent uses the LLM to choose its flow.

  3. Starting at Level 5. Build the simplest thing that works. You can always add complexity later.

In Module 02, you’ll build your first ask step, the fundamental building block for both workflows and agents.