We’ve explored two of the most powerful concepts in Agentic AI: Retrieval-Augmented Generation (RAG), which gives an agent deep knowledge from an “open-book exam,” and Tool Use, which gives an agent hands to act upon the world.
But what happens when you combine these two superpowers? You get an agent that can not only answer questions about your private data but can then act on that data.
A simple RAG system is a Q&A bot. A simple tool-using agent can act, but it doesn’t know the specifics of your internal inventory or documents. The RAG-powered agent bridges this gap. It can find a specific product in your database based on a vague description and then add it to a user’s shopping cart.
In this hands-on project, we will build a “Travel Assistant” agent that demonstrates this powerful Retrieve -> Reason -> Act
pattern.
The Project: A Smart Travel Assistant
Our goal is to build an agent that can:
- Retrieve: Search a private knowledge base of travel packages based on a user’s natural language query (e.g., “I want a short trip to the mountains”).
- Reason: Understand the details of the retrieved package, including its unique booking code.
- Act: Use a second tool to “book” the travel package once the user confirms, using the specific booking code it just learned.
Part 1: Setting Up the Knowledge Base (The “R” in RAG)
First, we need to create our “private data”—a simple text file with our travel package information.
1. Create travel_packages.txt
In your project folder, create this file:
Package Name: Himalayan Escape
Booking Code: HE-101
Destination: Darjeeling, West Bengal
Duration: 5 days
Description: A serene 5-day trip to the queen of hills, Darjeeling. Enjoy breathtaking views of Kanchenjunga, visit historic tea gardens, and ride the famous toy train. Perfect for a short mountain getaway.
---
Package Name: Coastal Serenity
Booking Code: CS-202
Destination: Goa, India
Duration: 7 days
Description: A relaxing 7-day vacation on the sandy beaches of Goa. Explore vibrant markets, enjoy delicious seafood, and soak up the sun. Ideal for beach lovers.
---
Package Name: Royal Rajasthan
Booking Code: RR-303
Destination: Jaipur & Udaipur, Rajasthan
Duration: 8 days
Description: An 8-day journey through the majestic forts and palaces of Rajasthan. Experience the rich culture and history of the land of kings.
2. The Indexing Pipeline
Now, we’ll write a one-time script to process this file and store it in a vector database. For this local project, we’ll use ChromaDB.
First, install the necessary libraries:
pip install langchain-chroma langchain-community sentence-transformers
Create a script setup_vector_store.py
:
# setup_vector_store.py
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import CharacterTextSplitter
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_chroma import Chroma
import os
# Define the path for the persistent vector store
db_path = "travel_db"
if not os.path.exists(db_path):
print("Creating vector store...")
# 1. Load the document
loader = TextLoader("travel_packages.txt")
documents = loader.load()
# 2. Split the document into chunks
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = text_splitter.split_documents(documents)
# 3. Create embeddings (using a free, local model)
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
# 4. Store chunks in a Chroma vector store
db = Chroma.from_documents(chunks, embeddings, persist_directory=db_path)
print("Vector store created successfully.")
else:
print("Vector store already exists.")
Run this script once: python setup_vector_store.py
. It will create a travel_db
folder containing your indexed knowledge base.
Part 2: Building the Agent’s Tools
Our agent needs two tools: one to retrieve and one to act.
# tools.py
import os
from langchain_core.tools import tool
from langchain_chroma import Chroma
from langchain_community.embeddings import HuggingFaceEmbeddings
db_path = "travel_db"
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
db = Chroma(persist_directory=db_path, embedding_function=embeddings)
retriever = db.as_retriever()
@tool
def search_travel_packages(query: str) -> str:
"""
Searches the travel package knowledge base to find relevant packages
based on a user's description or query. Returns the most relevant package's full details.
"""
print(f"--- Searching for packages with query: {query} ---")
results = retriever.invoke(query)
# Assuming the most relevant result is the first one
return results[0].page_content if results else "No relevant travel packages found."
@tool
def book_travel_package(booking_code: str) -> str:
"""
Books a travel package using its unique booking code after the user has confirmed.
Use this tool ONLY when you know the specific booking_code and the user wants to book.
"""
print(f"--- Booking package with code: {booking_code} ---")
# This is a mock function. A real one would call a booking API.
if booking_code in ["HE-101", "CS-202", "RR-303"]:
return f"Success! The package with code '{booking_code}' has been booked for you. An email confirmation will be sent shortly."
else:
return f"Error: The booking code '{booking_code}' is invalid. Please find a valid code first using the search tool."
Part 3: Assembling and Running the RAG-Powered Agent
Now we combine everything into our main agent file. The structure should be very familiar.
# main.py
from dotenv import load_dotenv
from tools import search_travel_packages, book_travel_package
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain.memory import ConversationBufferMemory
# --- SETUP ---
load_dotenv()
tools = [search_travel_packages, book_travel_package]
llm = ChatOpenAI(model="gpt-4o", temperature=0)
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
# --- PROMPT ---
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful travel assistant. You search for travel packages and can book them for the user."),
MessagesPlaceholder(variable_name="chat_history"),
("user", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
])
# --- AGENT ---
agent = create_tool_calling_agent(llm, tools, prompt)
# --- EXECUTOR ---
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# --- RUN ---
def run_conversation():
print("Travel Assistant is ready. How can I help you today?")
while True:
user_input = input("Human: ")
if user_input.lower() == 'exit':
break
chat_history = memory.load_memory_variables({})["chat_history"]
response = agent_executor.invoke({
"input": user_input,
"chat_history": chat_history
})
memory.save_context({"input": user_input}, {"output": response["output"]})
print("AI:", response["output"])
if __name__ == "__main__":
run_conversation()
The Two-Step Conversation in Action
Run python main.py
and have this exact conversation to see the magic.
Turn 1: Retrieval
Human: I’m looking for a short trip to the mountains.
(Check your verbose output. You will see the agent call
search_travel_packages(query='short trip to the mountains')
. It will find the ‘Himalayan Escape’ package.)AI: I found a great option for you: The “Himalayan Escape.” It’s a serene 5-day trip to Darjeeling, West Bengal, perfect for a short mountain getaway. It includes views of Kanchenjunga and a ride on the toy train. The booking code is HE-101. Would you like to book this trip?
Turn 2: Action
Human: That sounds perfect, please book it for me.
(Check your verbose output again. The agent, remembering the context, will now call
book_travel_package(booking_code='HE-101')
.)AI: Success! The package with code ‘HE-101’ has been booked for you. An email confirmation will be sent shortly.
Conclusion
You have just built an agent that demonstrates one of the most powerful patterns in modern AI. It doesn’t just answer questions; it intelligently interacts with a knowledge base to gather the specific information it needs to take meaningful action.
This Retrieve -> Reason -> Act cycle is the foundation for countless real-world applications, from e-commerce bots that find products and add them to a cart, to internal support agents that find troubleshooting guides and then execute diagnostic commands. You have now truly combined knowledge with action.
Author

Experienced Cloud & DevOps Engineer with hands-on experience in AWS, GCP, Terraform, Ansible, ELK, Docker, Git, GitLab, Python, PowerShell, Shell, and theoretical knowledge on Azure, Kubernetes & Jenkins. In my free time, I write blogs on ckdbtech.com