datarekha

LlamaIndex agents: FunctionAgent & ReActAgent

Turn a LlamaIndex index into a tool an agent can call. FunctionAgent (native function-calling) vs ReActAgent (text-based ReAct), both built on Workflows, plus the QueryEngineTool that makes RAG agentic.

7 min read Intermediate Agentic AI Lesson 22 of 42

What you'll learn

  • How to expose an index to an agent as a QueryEngineTool
  • FunctionAgent vs ReActAgent — when to use each
  • Why both are Workflows under the hood

Before you start

A plain query engine answers a single question from your data. An agent can decide when to query, query multiple sources, call other tools, and loop until it has a complete answer. LlamaIndex makes that jump small: wrap your index as a tool, hand it to an agent, done. This is how RAG becomes agentic.

Your index becomes a tool

The bridge is the QueryEngineTool — it turns any query engine into a callable tool with a name and description the agent reads to decide when to use it.

Agent loopdecides which toolQueryEngineToolwraps an index → searches docsother tools (web, calc…)another index as a toolanswertool result loops back to the agent
Wrap each index as a QueryEngineTool; the agent loops, choosing tools until it can answer.

Two agent types

LlamaIndex gives you two agents, differing only in how they decide on actions:

  • FunctionAgent — uses the model’s native function/tool calling. Cleaner, more reliable, and the default for any model that supports tool calling (most do now). Reach for this first.
  • ReActAgent — uses text-based ReAct (Thought / Action / Observation written as text). Useful for models without native tool calling, or when you want the reasoning trace visible as text.

Both are Workflows under the hood — the agent loop is a Workflow with steps for “call the LLM,” “run the tool,” and “check if done.” So everything you learned about Workflows applies: you can add custom steps, stream events, and trace the run.

from llama_index.core.agent.workflow import FunctionAgent
from llama_index.core.tools import QueryEngineTool

# Wrap two indexes as tools the agent can choose between
docs_tool = QueryEngineTool.from_defaults(
    docs_index.as_query_engine(),
    name="product_docs",
    description="Answers questions about product features and pricing.",
)
policy_tool = QueryEngineTool.from_defaults(
    policy_index.as_query_engine(),
    name="policies",
    description="Answers questions about refunds, SLAs, and terms.",
)

agent = FunctionAgent(tools=[docs_tool, policy_tool], llm=llm)
# response = await agent.run("Is the Pro plan refundable after 20 days?")
# → the agent picks 'policies', queries it, and answers — citing the source nodes.

The agent reads each tool’s description to decide which to call — so write descriptions like you’re writing for a smart colleague: clear, specific, and honest about what each tool does and doesn’t cover.

Quick check

Quick check

0/3
Q1What does a QueryEngineTool do?
Q2When should you use FunctionAgent vs ReActAgent?
Q3Why does writing good tool descriptions matter for a LlamaIndex agent?

Next

Agents are only as good as the documents they index. LlamaParse solves the messy-PDF problem that wrecks naive ingestion.

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
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.

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.

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