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.
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.
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
Next
Built on Workflows: LlamaIndex agents — FunctionAgent and ReActAgent that use tools over your indexes.
Practice this in an interview
All questionsTool 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 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.
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.
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.