Powered by AppSignal & Oban Pro

Build Your First Workflow

first-workflow.livemd

%{ title: “Build Your First Workflow”, description: “Compose multiple actions into a single workflow using Jido.Plan for sequential and parallel execution.”, category: :docs, order: 13, prerequisites: [“docs/learn/first-llm-agent”], learning_outcomes: [

"Compose multiple actions into a single command",
"Use Plans to define execution order and dependencies",
"Handle directive output from multi-step workflows"

], tags: [:docs, :learn, :tutorial, :workflows, :wave_1] }


Build Your First Workflow

Overview

Real tasks involve more than one step. Jido lets you compose small Actions into workflows so you can keep each step focused and testable.

This tutorial shows how to pass multiple actions to cmd/2, then build a Jido.Plan for more explicit ordering. You will also see how directives accumulate into a single Jido.Instruction at the end of a workflow.

Prerequisites

Complete Build Your First Agent and review the basics of action execution. If you already worked through the previous tutorial, you have everything you need to continue.

Why Compose Actions?

A single large action is easy to start with, but it becomes hard to test and reuse. A workflow lets you isolate each step and still run them as one command.

This also gives you a clear place to express dependencies. In Jido.Plan, you build a small DAG that is executed by the runtime for you.

Create Multiple Actions

We will build a simple “health check” workflow. Each action does one job and returns a directive.

defmodule CheckConnectivityAction do
  use Jido.Action

  def run(_args) do
    {:ok, [:log, "Connectivity OK."]}
  end
end
defmodule CheckDiskSpaceAction do
  use Jido.Action

  def run(_args) do
    {:ok, [:log, "Disk space OK."]}
  end
end
defmodule GenerateStatusReportAction do
  use Jido.Action

  def run(_args) do
    {:ok, [:reply, "Server status: All systems nominal."]}
  end
end

Execute with Multiple Actions

You can pass multiple actions to cmd/2 as a simple list. The agent will execute them in order and return a single instruction.

# Assuming `agent_pid` is a running agent from the earlier tutorial
{:ok, instruction} =
  MyAgent.cmd(agent_pid, [
    CheckConnectivityAction,
    CheckDiskSpaceAction,
    GenerateStatusReportAction
  ])

instruction.directives

This is the quickest way to chain work. It is also the easiest place to start before you need branching or parallel steps.

Build a Plan

When you need clear dependencies, use Jido.Plan. A plan models a Directed Acyclic Graph, so you can mix sequential and parallel execution without hand wiring the flow.

In this workflow, the connectivity and disk checks can run in parallel. The report must wait for both, so it is placed after the parallel step in a sequential plan.

alias Jido.Plan

health_check_plan =
  Plan.sequential([
    Plan.parallel([
      CheckConnectivityAction,
      CheckDiskSpaceAction
    ]),
    GenerateStatusReportAction
  ])

You can nest Plan.sequential/1 and Plan.parallel/1 to express more complex dependencies. Each step can be an action module or another plan.

Execute the Workflow

Running a plan uses the same cmd/2 call. The agent interprets the plan and executes the steps in the correct order.

{:ok, instruction} = MyAgent.cmd(agent_pid, health_check_plan)
IO.inspect(instruction, label: "Workflow result")

This keeps your call site simple, while allowing a precise execution order. It also makes workflows easier to explain and review in code.

Handle Directives

Every action can emit directives, and the runtime collects them during the workflow. The final Jido.Instruction contains a flat list of all directives in execution order.

%Jido.Instruction{
  directives: [
    {:log, "Connectivity OK."},
    {:log, "Disk space OK."},
    {:reply, "Server status: All systems nominal."}
  ]
}

Parallel steps contribute directives as they complete. Sequential steps appear after the directives from any earlier steps.

Verify the Result

You can verify the workflow by inspecting instruction.directives and confirming you got three entries. If you want a quick check, compare the output to the expected list below.

expected = [
  {:log, "Connectivity OK."},
  {:log, "Disk space OK."},
  {:reply, "Server status: All systems nominal."}
]

if instruction.directives == expected do
  IO.puts("Workflow directives look correct.")
else
  IO.inspect(instruction.directives, label: "Unexpected directives")
end

Next Steps

Review Directives to see how to route each outcome. If you want to continue the onboarding sequence, build a Stateful Counter Agent.


Generated by Jido Documentation Writer Bot | Run ID: 1461064acb98