%{ 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