CrewAI Powered RAG Agent - CrewAI_Tools PDFSearchTool
Fully working Python Example in Jupyter Notebooks to standup a CrewAI RAG Agent. Python syntax is slightly different, this is Jupyter syntax.
This tutorial presents a complete, end-to-end implementation of an Agentic Retrieval-Augmented Generation (RAG) System built with CrewAI and optimized for execution within Jupyter Notebooks.
Instead of relying on standard naive RAG—where every input query blindly searches a single vector database—this architecture uses an intelligent multi-agent framework to dynamically evaluate, route, and execute information retrieval based on query intent.
Technical Architecture & Core Design
The system decouples intent evaluation from data fetching through specialized agent roles executed sequentially:
-
Query Router Agent: Evaluates incoming user prompts and classifies them into three explicit execution paths:
- PDF: Routes queries requiring proprietary or domain-specific static knowledge (e.g., technical whitepapers) to local vector document search tools.
- WEB: Routes queries asking for live news, real-time events, or external data to the Tavily Web Search API.
- DIRECT: Handles broad world knowledge, conversational inputs, or general facts directly via the LLM, skipping retrieval entirely to save API latency and compute costs.
-
Information Retriever & Formatter Agent: Consumes the routing classification alongside the original prompt, executes the designated search tool (
PDFSearchToolor customTavilyWebSearchTool), synthesizes raw contexts, and yields a grounded final response.
Key Technical Highlights in the Code
- Jupyter Async Handling (
nest_asyncio): Appliesnest_asyncio.apply()early in the workflow to resolve event loop conflicts inherent when executing asynchronous orchestration methods likekickoff_async()inside interactive Jupyter kernels. - Custom Tool Wrapping (
BaseTool): Demonstrates how to create custom CrewAI tool wrappers using Pydantic models to encapsulate third-party search APIs like Tavily. - Context Passing Between Tasks: Utilizes CrewAI's
context=[routing_task]parameter in the retrieval task definition to pass upstream routing decisions directly into the downstream agent’s execution phase without manual state tracking. - Traceability & Auditing: Captures both the synthesized user answer (
result.raw) and full execution logs (routing_task.output.raw), enabling granular inspection of agent decision-making.
Cell 1: Install Dependencies
!pip install crewai crewai[tools] langchain-community langchain-openai pydantic tavily-python
!pip install pywin32
!pip install nest-asyncio
Cell 2: Import Libraries and Setup Environment
import os
import nest_asyncio
nest_asyncio.apply()
from crewai.tools import BaseTool
from langchain_community.tools import TavilySearchResults
from pydantic import Field
from crewai import Agent, Task, Crew, Process
from crewai_tools import PDFSearchTool
from langchain_community.tools.tavily_search import TavilySearchResults
# Configure API Keys (Replace with your actual keys)
os.environ["TAVILY_API_KEY"] = "your_key_here"
os.environ["OPENAI_API_KEY"] = "your_key_here"
Cell 3: Initialize Tools
# The PDF search tool processes static domain knowledge
pdf_search_tool = PDFSearchTool(pdf='trasformer_research_paper-dataset.pdf')
# 1. Define custom CrewAI BaseTool class wrapping Tavily
class TavilyWebSearchTool(BaseTool):
name: str = "Tavily Web Search"
description: str = (
"Useful for searching the live web, news, and current events."
)
tavily: TavilySearchResults = Field(
default_factory=lambda: TavilySearchResults(max_results=5)
)
def _run(self, query: str) -> str:
try:
return str(self.tavily.invoke({"query": query}))
except Exception as e:
return f"Error executing web search: {str(e)}"
# 2. Instantiate the tool
web_search_tool = TavilyWebSearchTool()
Cell 4: Define Agents
router_agent = Agent(
role="Query Router",
goal="Analyze the user's question and strictly determine the optimal retrieval path: 'PDF', 'WEB', or 'DIRECT'.",
backstory=(
"You are a routing specialist for a highly advanced RAG system. "
"The PDF contains specialized internal company/domain knowledge. "
"The WEB contains real-time news, current events, and live data. "
"DIRECT is for basic greetings or standard facts requiring no lookup. "
"Your job is to read the query, decide the route, and pass the instruction forward."
),
verbose=True,
allow_delegation=False
)
retriever_agent = Agent(
role="Information Retriever and Formatter",
goal="Retrieve information using the exact tool indicated by the Router Agent, and synthesize a grounded final answer.",
backstory=(
"You are a meticulous researcher. You strictly follow the Router Agent's instructions. "
"If instructed to use PDF, you use the PDFSearchTool. If instructed to use WEB, you use the Tavily tool. "
"You never guess facts; you only answer based on the retrieved context."
),
tools=[pdf_search_tool, web_search_tool],
verbose=True,
allow_delegation=False
)
Cell 5: Define Tasks
routing_task = Task(
description=(
"Analyze this user question: '{query}'.\n"
"1. Decide if it needs internal PDF knowledge, current WEB data, or a DIRECT answer.\n"
"2. Output the routing decision and a brief reasoning."
),
expected_output="A short text specifying the route (e.g., 'ROUTE: WEB') and the reasoning.",
agent=router_agent
)
retrieval_task = Task(
description=(
"Answer this user question: '{query}'.\n"
"Use the output from the routing task to determine your action. "
"Execute the appropriate tool to find the information, then write a comprehensive, accurate answer."
),
expected_output="A detailed, accurate answer grounded in the retrieved data, with no mention of the internal routing process.",
agent=retriever_agent,
context=[routing_task] # This natively passes the Router's output to the Retriever
)
Cell 6: Orchestrate the Crew
agentic_rag_crew = Crew(
agents=[router_agent, retriever_agent],
tasks=[routing_task, retrieval_task],
process=Process.sequential, # Ensures Router finishes before Retriever starts
verbose=True, # Enables detailed interaction logging
output_log_file="rag_execution.log",
)
Cell 7: Execute and View Results
############################################################
#Example question related to the PDF to enter
#How many identical layers is an encoder stack composed of?
############################################################
#Example question related to web search
#What are the different types of corgis?
############################################################
raw_input = input("Enter your question (leave blank for default): ").strip()
user_question = raw_input if raw_input else "What is the attention mechanism?"
print(f"Selected Query: '{user_question}'")
#execute and view
print(f"\nProcessing query: '{user_question}'\n")
# Run crew asynchronously
result = await agentic_rag_crew.kickoff_async(inputs={"query": user_question})
print("\n" + "=" * 50)
print("FINAL ANSWER:")
print("=" * 50)
print(result.raw) # Use .raw for clean string output
print("\n" + "=" * 50)
print("ROUTING LOG / TRACEABILITY:")
print("=" * 50)
print(f"Router Decision: {routing_task.output.raw}")
Output:
╭─────────────────────────────────────────── 🚀 Crew Execution Started ───────────────────────────────────────────╮
│
│ Crew Execution Started
│ Name: crew
│ ID: d1576a57-4890-4961-87e0-8ea11f475e6f
│
│
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭──────────────────────────────────────────────── 📋 Task Started ────────────────────────────────────────────────╮
│
│ Task Started
│ Name: Analyze this user question: 'What are the different types of corgis?'.
│ 1. Decide if it needs internal PDF knowledge, current WEB data, or a DIRECT answer.
│ 2. Output the routing decision and a brief reasoning.
│ ID: d5431b68-1e01-4fe6-88d1-eaf221aa20fe
│
│
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─────────────────────────────────────────────── 🤖 Agent Started ────────────────────────────────────────────────╮
│
│ Agent: Query Router
│
│ Task: Analyze this user question: 'What are the different types of corgis?'.
│ 1. Decide if it needs internal PDF knowledge, current WEB data, or a DIRECT answer.
│ 2. Output the routing decision and a brief reasoning.
│
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── ✅ Agent Final Answer ─────────────────────────────────────────────╮
│
│ Agent: Query Router
│
│ Final Answer:
│ ROUTE: DIRECT
│ Reasoning: The question about the different types of corgis is general knowledge about dog breeds and does
│ not require specialized internal company knowledge or real-time data. It can be answered directly from common
│ factual information.
│
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭────────────────────────────────────────────── 📋 Task Completion ───────────────────────────────────────────────╮
│
│ Task Completed
│ Name: Analyze this user question: 'What are the different types of corgis?'.
│ 1. Decide if it needs internal PDF knowledge, current WEB data, or a DIRECT answer.
│ 2. Output the routing decision and a brief reasoning.
│ Agent: Query Router
│
│
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭──────────────────────────────────────────────── 📋 Task Started ────────────────────────────────────────────────╮
│
│ Task Started
│ Name: Answer this user question: 'What are the different types of corgis?'.
│ Use the output from the routing task to determine your action. Execute the appropriate tool to find the
│ information, then write a comprehensive, accurate answer.
│ ID: 32ab02b3-7da1-488d-ab92-adfd4eedf0a9
│
│
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─────────────────────────────────────────────── 🤖 Agent Started ────────────────────────────────────────────────╮
│
│ Agent: Information Retriever and Formatter
│
│ Task: Answer this user question: 'What are the different types of corgis?'.
│ Use the output from the routing task to determine your action. Execute the appropriate tool to find the
│ information, then write a comprehensive, accurate answer.
│
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────── ✅ Agent Final Answer ─────────────────────────────────────────────╮
│
│ Agent: Information Retriever and Formatter
│
│ Final Answer:
│ The different types of corgis primarily refer to two distinct breeds:
│
│ 1. Pembroke Welsh Corgi: This breed is known for its shorter tail or sometimes a docked tail and slightly
│ smaller stature compared to the other type. Pembroke Welsh Corgis typically have a more fox-like appearance
│ with erect ears and a more pointed face. They are one of the most popular corgi breeds and are known for
│ their friendly and outgoing nature.
│
│ 2. Cardigan Welsh Corgi: This breed has a longer tail and ears that are more rounded at the tips. Cardigans
│ are generally a bit larger and have a more robust build compared to Pembrokes. They have a longer body and
│ come in a wider variety of coat colors and patterns.
│
│ Both types of corgis are herding dogs originally from Wales, but they have distinct lineage and physical
│ characteristics that differentiate them.
│
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭────────────────────────────────────────────── 📋 Task Completion ───────────────────────────────────────────────╮
│
│ Task Completed
│ Name: Answer this user question: 'What are the different types of corgis?'.
│ Use the output from the routing task to determine your action. Execute the appropriate tool to find the
│ information, then write a comprehensive, accurate answer.
│ Agent: Information Retriever and Formatter
│
│
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Output to User Chat Window:
==================================================
FINAL ANSWER:
==================================================
The different types of corgis primarily refer to two distinct breeds:
1. Pembroke Welsh Corgi: This breed is known for its shorter tail or sometimes a docked tail and slightly smaller stature compared to the other type. Pembroke Welsh Corgis typically have a more fox-like appearance with erect ears and a more pointed face. They are one of the most popular corgi breeds and are known for their friendly and outgoing nature.
2. Cardigan Welsh Corgi: This breed has a longer tail and ears that are more rounded at the tips. Cardigans are generally a bit larger and have a more robust build compared to Pembrokes. They have a longer body and come in a wider variety of coat colors and patterns.
Both types of corgis are herding dogs originally from Wales, but they have distinct lineage and physical characteristics that differentiate them.
==================================================
ROUTING LOG / TRACEABILITY:
==================================================
Router Decision: ROUTE: DIRECT
Reasoning: The question about the different types of corgis is general knowledge about dog breeds and does not require specialized internal company knowledge or real-time data. It can be answered directly from common factual information.