datarekha

LlamaIndex Workflows (event-driven)

Workflows are how modern LlamaIndex composes multi-step LLM apps: typed Events flowing between async Steps. The recommended way to build everything — including agents — on LlamaIndex.

8 min read Intermediate Agentic AI Lesson 21 of 42

What you'll learn

  • The event-driven model — Steps consume and emit typed Events
  • Why this beats hand-wired chains for branching, loops, and concurrency
  • That LlamaIndex agents and query engines are built on Workflows

Before you start

Once your LLM app has more than one step — retrieve, then check, then maybe re-retrieve, then answer — you need a way to wire those steps together that handles branching, loops, and concurrency without turning into spaghetti. LlamaIndex’s answer is Workflows, and as of 2026 it’s the recommended way to build everything on the framework, agents included.

Steps consume Events, and emit Events

A Workflow is an event-driven graph. You don’t draw nodes and edges by hand; instead you write Steps (async functions), and each step declares which Event type it consumes and which it emits. The framework routes events to the steps that handle them. The flow emerges from the event types — not from wiring.

StartEventretrieve()stepcheck()stepStopEventRetrievedgoodRedo (loop back) — emit an event, no rewiring
A Workflow: steps consume and emit typed events. A loop is just a step emitting an event an earlier step handles.

Why events beat hand-wired chains

  • Branching is natural — a step emits one of several event types; whichever step handles that type runs next. No giant if/else router.
  • Loops are trivial — emit an event that an earlier step consumes, and you have a loop (with a step counter as the guard).
  • Concurrency is built in — emit several events and multiple steps run concurrently; a collector step waits for them. Great for fan-out/fan-in.
  • Observable — every event is a typed, loggable object, so tracing a run is reading the event stream.
from llama_index.core.workflow import Workflow, step, StartEvent, StopEvent, Event

class Retrieved(Event):
    nodes: list

class RAGFlow(Workflow):
    @step
    async def retrieve(self, ev: StartEvent) -> Retrieved:
        nodes = self.index.as_retriever().retrieve(ev.query)
        return Retrieved(nodes=nodes)

    @step
    async def synthesize(self, ev: Retrieved) -> StopEvent:
        answer = synthesize(ev.nodes)        # compose from the retrieved Nodes
        return StopEvent(result=answer)

# result = await RAGFlow(index=index).run(query="refund window?")

retrieve consumes the StartEvent and emits a Retrieved; synthesize consumes Retrieved and emits the StopEvent. Add a check step that emits either Retrieved (redo) or StopEvent (done) and you’ve got a self-correcting loop — no graph wiring, just event types.

Quick check

Quick check

0/3
Q1How is control flow expressed in a LlamaIndex Workflow?
Q2How do you create a loop in a Workflow?
Q3Why does learning Workflows matter beyond your own pipelines?

Next

Built on Workflows: LlamaIndex agents — FunctionAgent and ReActAgent that use tools over your indexes.

Sign in to track your progress

Completed lessons, your XP, level, and streak save to your account — it's free and takes a few seconds.

Practice this in an interview

All questions
How do function/tool calling and LLM agents work at a high level?

Tool calling extends the LLM's output space to include structured function invocations. The model emits a JSON object naming a tool and its arguments; the runtime executes the tool and feeds the result back as a new message. An agent is a loop that repeats this cycle — observe, think, act — until the task is complete or a stopping condition is met.

In LlamaIndex, what are nodes and query engines, and how is RAG exposed as a tool to an agent?

In LlamaIndex a Node is a chunk of a source document with metadata and relationships, indexed for retrieval; a query engine wraps an index to take a natural-language query, retrieve relevant nodes, and synthesize an answer. RAG-as-a-tool wraps a query engine in a QueryEngineTool so an agent can call it like any other tool, deciding when to retrieve from that knowledge source as part of its reasoning loop.

What is tool use or function calling in LLMs, and how do you design good tools for an agent?

Function calling lets an LLM output a structured request to invoke an external function with arguments, which the runtime executes and feeds back, enabling agents to act in the world. Good tool design uses clear names and descriptions, minimal well-typed parameters, narrow single-purpose scope, least privilege, and informative error messages so the model can choose and call them reliably.

What is an AI agent, and how does it differ from a single LLM call?

An agent is an LLM placed in a loop where it reasons, chooses and calls tools or actions, observes the results, and repeats until a goal is met, rather than producing one response and stopping. The key differences are autonomy, tool use, memory and state, and multi-step control flow driven by the model's own decisions.

Related lessons

Explore further

Skip to content