How does LlamaIndex AgentRunner add structure over a bare ReAct loop?
AgentWorker decides one step; AgentRunner owns the Task, persists state between steps, and exposes pause resume inspect controls a bare ReAct while-loop cannot offer.
Imagine a chess engine and a chess clock. The engine knows how to pick the next move given the current board. The clock knows whose turn it is, when to pause, and how to resume a game from a saved position. If you smash both into one program, you have a chess bot that always plays start to finish in one go. You cannot stop it mid-game, you cannot review the moves before the next one, and you cannot swap in a different engine without rewriting the clock. LlamaIndex's AgentWorker is the engine; AgentRunner is the clock plus the saved-game folder. Keeping them separate lets you do things a bot smashed into one program cannot.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Early agent frameworks shipped one abstraction: an agent class with a run(query) method that internally looped until done. That abstraction worked for demos and failed for production. You could not pause it, inspect it mid-run, or resume after a crash.
LlamaIndex's response is the runner/worker split. AgentRunner orchestrates Tasks, AgentWorker decides one step. The same response shows up across mature agent runtimes: LangGraph splits executor and node, OpenAI Agents SDK separates the loop and handoffs, Mastra typed workflows split runtime and step handlers.
Understanding why this split exists, and what bare while-loops cannot do, is the difference between a candidate who has demoed an agent and one who has shipped one.
AgentWorker. The per-step decision
An AgentWorker has one job. Given current state and message history, return the next action. Think, call tool, finalise. Built-in implementations include ReActAgentWorker (reasoning then action loop) and FunctionCallingAgentWorker (native tool calls on supported models).
The key surface is run_step(task). Advance the task by exactly one decision. The worker does not loop, does not own state across calls, does not know when to stop.
This narrowness is the point. A worker is a pure function of state in, decision out, with no opinion about the rest of the loop. That makes workers swappable and testable in isolation.
Situations where this technique stops working.
2–4 min · Everything important, quickly.
from llama_index.core.agent import ReActAgentWorker, AgentRunner
from llama_index.llms.openai import OpenAI
worker = ReActAgentWorker.from_tools(tools, llm=OpenAI(model="gpt-5.5"))
runner = AgentRunner(worker)
# Create the task; do not drive to completion yet
task = runner.create_task("Research X, draft a one-page brief.")
# Advance one step at a time, interleaving human review
step_output = runner.run_step(task.task_id)
print("after step:", runner.get_completed_steps(task.task_id))
if user_approves(step_output):
while not step_output.is_last:
step_output = runner.run_step(task.task_id)
result = runner.finalize_response(task.task_id)
Real products, models, and research that use this idea.
- LlamaIndex's official ReActAgent demos use the runner/worker split as the canonical pattern. The bare loop only appears in 'minimal' examples
- Production document-QA agents pair LlamaIndex AgentRunner for stepped tool-use with custom human-approval gates between steps
What an interviewer would ask next. Try answering before peeking at the approach.
QHow does LlamaIndex Workflows generalise the runner/worker pattern?
Walk through the event-driven Step decorator model, typed StartEvent/StopEvent flow, and how Steps replace AgentWorker as the per-decision unit while the Workflow runtime replaces AgentRunner.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Treating AgentRunner as 'just a wrapper around the worker'. The real value is the Task abstraction with pause resume inspect on persisted state, which a bare while-loop cannot offer.
60 second bullets to scan on the way to the call.
Role of AgentWorker. Per-step decision
Role of AgentRunner. Task orchestration, persistence, resumption
Primary sources. Browse if you want the original framing.
Same topic, related formats. Practice these next.