Following the pandemic, the travel industry is experiencing a surge in travel and flight bookings. The aviation industry involves massive amounts of fast-changing data, like flight schedules, delays, and thus accessing accurate and up-to-date information with the help of an AI Agent provides insights for real-world applications. AI Agent broadens the possibilities for real-world usage for aviation data in flight bookings at the cheapest price, route optimization, and alerts about any flight delay, gate change, or cancellation. It saves time, enables automation, and improves travel experience for passengers and businesses. In this article, we will learn how an AI Agent helps in decision-making for booking a flight by searching for the cheapest flight to the specified route. We will be using AGNO framework to develop a full-fledged AI Agent with access to GroqCloud to run LLM and connect to Avaition Stack API to extract aviation details. Let’s see the various tools used and their step-by-step implementation in Python. What is an AI Agent? An AI Agent that takes a prompt as input, thinks, and acts to complete the task autonomously and independently with minimum human intervention using tools, memory, and knowledge. AI Agents are used to simplify complex environments and automate narrow tasks. In various business domains like AI chatbot, human assistance, travel assistance, healthcare assistance, finance trading systems, custom AI agents can be built, which can improve the performance efficiency by approximately 70%. At the core of AI agents are large language models (LLMs), but LLMs are limited to the data they are trained on. But AI Agents are LLM at heart and call various tools in the backend to obtain up-to-date information, optimize workflows, and create subtasks autonomously to achieve complex goals without human intervention. In this process, the autonomous AI agent learns to adapt to user expectations over time. AI Agent vs Generative AI The first question that arises in our mind when we read, think, or discuss an AI Agent is how the AI Agent is different from Generative AI. Let’s summarize it in tabular format for easy understanding. TypeGenerative AIAI AgentTechnologyLLM onlyLLM + Tools + KnowledgeCapabilityTakes prompt as input and answers based on pre-trained data only.Takes input prompt, connects with tools and data, makes autonomous decisions, and performs actions.Tools usageNo external tools usedUsage of external tools via APIsDecision MakingNo decision-makingAutonomous secession making TypeGenerative AIAI AgentTechnologyLLM onlyLLM + Tools + KnowledgeCapabilityTakes prompt as input and answers based on pre-trained data only.Takes input prompt, connects with tools and data, makes autonomous decisions, and performs actions.Tools usageNo external tools usedUsage of external tools via APIsDecision MakingNo decision-makingAutonomous secession making TypeGenerative AIAI AgentTechnologyLLM onlyLLM + Tools + KnowledgeCapabilityTakes prompt as input and answers based on pre-trained data only.Takes input prompt, connects with tools and data, makes autonomous decisions, and performs actions.Tools usageNo external tools usedUsage of external tools via APIsDecision MakingNo decision-makingAutonomous secession making TypeGenerative AIAI Agent Type Type Type Generative AI Generative AI Generative AI AI Agent AI Agent AI Agent TechnologyLLM onlyLLM + Tools + Knowledge Technology Technology Technology LLM only LLM only LLM only LLM + Tools + Knowledge LLM + Tools + Knowledge LLM + Tools + Knowledge CapabilityTakes prompt as input and answers based on pre-trained data only.Takes input prompt, connects with tools and data, makes autonomous decisions, and performs actions. Capability Capability Capability Takes prompt as input and answers based on pre-trained data only. Takes prompt as input and answers based on pre-trained data only. Takes prompt as input and answers based on pre-trained data only. Takes input prompt, connects with tools and data, makes autonomous decisions, and performs actions. Takes input prompt, connects with tools and data, makes autonomous decisions, and performs actions. Takes input prompt, connects with tools and data, makes autonomous decisions, and performs actions. Tools usageNo external tools usedUsage of external tools via APIs Tools usage Tools usage Tools usage No external tools used No external tools used No external tools used Usage of external tools via APIs Usage of external tools via APIs Usage of external tools via APIs Decision MakingNo decision-makingAutonomous secession making Decision Making Decision Making Decision Making No decision-making No decision-making No decision-making Autonomous secession making Autonomous secession making Autonomous secession making Understanding and Setting up Agno Understanding and Setting up Agno We are using the Agno framework to implement our AI Agent. Agno (formerly known as Phi Data) is an open-source, full-stack, and lightweight framework to build AI Agents and Agentic AI applications. Agno Why Agno? Agno is known for its speed and efficient performance.Easy to implement AI Agents with Agno.Agno framework is very intuitive.It supports complex workflows.It is compatible with various tools and easily connects with them. Agno is known for its speed and efficient performance. Easy to implement AI Agents with Agno. Agno framework is very intuitive. It supports complex workflows. It is compatible with various tools and easily connects with them. Agno Setup Simply install the Python module of Agno(Phi Data) by running the command mentioned below : pip install phidata Understanding and Setup GroqCloud We are using GroqCloud to run an LLM model in the cloud, which saves all the processing setup required on a local system. GroqCloud is a cloud-based platform for accessing Groq's ultra-fast AI inference services, offering developers a serverless API for running large language models (LLMs) with extremely low latency. It makes building and deploying AI applications more efficient, faster, cost-effective, and computationally less expensive. Follow the steps below to set up GroqCloud services: GroqCloud Open the GroqCloud website by clicking here and sign up for GroqCloud.Create an API Key by clicking on the Create API Key button in the API Keys tab, as shown below. (Don’t share your API key with anyone.) Open the GroqCloud website by clicking here and sign up for GroqCloud. here Create an API Key by clicking on the Create API Key button in the API Keys tab, as shown below. (Don’t share your API key with anyone.) 3.In the playground tab, select and copy the LLM model to be used in the code. 4.Save the API key generated and the LLM server to be used. We are using “openai/gpt-oss-20b” for our AI Agent application. 5.Now, install the Python module of Groq by running the command below: pip install groq Understanding the Aviation Stack and API Key Creation Understanding the Aviation Stack and API Key Creation As our AI Agent needs real-time updated aviation data to extract required information, we will be using the AviationStack API as a tool. It provides comprehensive data on flights, routes, and various airlines across the globe. Follow the steps below to create an API key for Aviation Stack: Open https://aviationstack.com/ and sign up for Aviation Stack.Click on the “Get Free API Key” button to get the API Key as shown below: Open https://aviationstack.com/ and sign up for Aviation Stack. https://aviationstack.com/ Click on the “Get Free API Key” button to get the API Key as shown below: 3.Your API Access key will be generated 4.Save this key for use in AI Agent implementation. Implementing an AI Agent to Extract Aviation Details Let's go step by step to understand how to extract aviation details using the Aviation Stack API with Phidata. Step 1: Install Required Libraries As we have seen earlier, the first step is to install required libraries like phidata, grog, and python-dotenv. pip install phidatapip install groqpip install python-dotenv #library to load .env file pip install phidatapip install groqpip install python-dotenv #library to load .env file pip install phidatapip install groqpip install python-dotenv #library to load .env file pip install phidatapip install groqpip install python-dotenv #library to load .env file pip install phidatapip install groqpip install python-dotenv #library to load .env file pip install phidata pip install phidata pip install groq pip install groq pip install python-dotenv #library to load .env file pip install python-dotenv #library to load .env file Step 2: Set up Environment File Step 2: Set up Environment File Create a Project Folder and under that create an environmental file “.env” to store GROQ_API_KEY and AVIATIONSTACK_KEY. Create a Project Folder and under that create an environmental file “.env” to store GROQ_API_KEY and AVIATIONSTACK_KEY. GROQ_API_KEY="your_groq_api_key_here"AVIATIONSTACK_KEY = your_aviationstack_api_key_here" GROQ_API_KEY="your_groq_api_key_here"AVIATIONSTACK_KEY = your_aviationstack_api_key_here" GROQ_API_KEY="your_groq_api_key_here"AVIATIONSTACK_KEY = your_aviationstack_api_key_here" GROQ_API_KEY="your_groq_api_key_here"AVIATIONSTACK_KEY = your_aviationstack_api_key_here" GROQ_API_KEY="your_groq_api_key_here"AVIATIONSTACK_KEY = your_aviationstack_api_key_here" GROQ_API_KEY="your_groq_api_key_here"AVIATIONSTACK_KEY = your_aviationstack_api_key_here" GROQ_API_KEY= "your_groq_api_key_here" AVIATIONSTACK_KEY = your_aviationstack_api_key_here" Step 3: Create an AviationStackTool class Now we need to create a Phidata tool class for AviationStack to extract aviation details. Phidata tools are Pydantic-based classes that define: a metadata (name, description, type, function, etc.) a metadata (name, description, type, function, etc.) callable methods (search_flights) callable methods (search_flights) a specification for LLMs (like _to_openai_tool or tool_spec) a specification for LLMs (like _to_openai_tool or tool_spec) Create an AviationStackTool class with a function search_flights to search flights for countries defined in the CITY_TO_IATA dictionary, as shown below in code: from typing import ClassVarimport requestsfrom phi.tools import ToolCITY_TO_IATA = { "new york": "JFK", "london": "LHR", "paris": "CDG", "delhi": "DEL", "tokyo": "HND", "los angeles": "LAX",}class AviationStackTool(Tool): name: ClassVar[str] = "aviationstack" description: ClassVar[str] = "Get flight data (real-time, schedules, airlines) from AviationStack API." type: str = "function" function: dict = { "name": "aviationstack", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "User input like 'Find flights from New York to London'" } }, "required": ["query"] } } # Custom fields must be declared api_key: str base_url: str = "http://api.aviationstack.com/v1" def search_flights(self, query: str): """Parse user text, resolve city names → IATA, then search flights.""" dep_iata, arr_iata = None, None query_lower = query.lower() for city, code in CITY_TO_IATA.items(): if city in query_lower: if not dep_iata: dep_iata = code else: arr_iata = code if not dep_iata or not arr_iata: return {"error": "Could not detect departure or arrival city"} """Search flights between departure and arrival airports by IATA codes.""" url = f"{self.base_url}/flights" params = { "access_key": self.api_key, "dep_iata": dep_iata, "arr_iata": arr_iata, } resp = requests.get(url, params=params) print(resp.status_code) if resp.status_code == 200: print(resp.json()) return resp.json() return {"error": resp.text} from typing import ClassVarimport requestsfrom phi.tools import ToolCITY_TO_IATA = { "new york": "JFK", "london": "LHR", "paris": "CDG", "delhi": "DEL", "tokyo": "HND", "los angeles": "LAX",}class AviationStackTool(Tool): name: ClassVar[str] = "aviationstack" description: ClassVar[str] = "Get flight data (real-time, schedules, airlines) from AviationStack API." type: str = "function" function: dict = { "name": "aviationstack", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "User input like 'Find flights from New York to London'" } }, "required": ["query"] } } # Custom fields must be declared api_key: str base_url: str = "http://api.aviationstack.com/v1" def search_flights(self, query: str): """Parse user text, resolve city names → IATA, then search flights.""" dep_iata, arr_iata = None, None query_lower = query.lower() for city, code in CITY_TO_IATA.items(): if city in query_lower: if not dep_iata: dep_iata = code else: arr_iata = code if not dep_iata or not arr_iata: return {"error": "Could not detect departure or arrival city"} """Search flights between departure and arrival airports by IATA codes.""" url = f"{self.base_url}/flights" params = { "access_key": self.api_key, "dep_iata": dep_iata, "arr_iata": arr_iata, } resp = requests.get(url, params=params) print(resp.status_code) if resp.status_code == 200: print(resp.json()) return resp.json() return {"error": resp.text} from typing import ClassVarimport requestsfrom phi.tools import ToolCITY_TO_IATA = { "new york": "JFK", "london": "LHR", "paris": "CDG", "delhi": "DEL", "tokyo": "HND", "los angeles": "LAX",}class AviationStackTool(Tool): name: ClassVar[str] = "aviationstack" description: ClassVar[str] = "Get flight data (real-time, schedules, airlines) from AviationStack API." type: str = "function" function: dict = { "name": "aviationstack", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "User input like 'Find flights from New York to London'" } }, "required": ["query"] } } # Custom fields must be declared api_key: str base_url: str = "http://api.aviationstack.com/v1" def search_flights(self, query: str): """Parse user text, resolve city names → IATA, then search flights.""" dep_iata, arr_iata = None, None query_lower = query.lower() for city, code in CITY_TO_IATA.items(): if city in query_lower: if not dep_iata: dep_iata = code else: arr_iata = code if not dep_iata or not arr_iata: return {"error": "Could not detect departure or arrival city"} """Search flights between departure and arrival airports by IATA codes.""" url = f"{self.base_url}/flights" params = { "access_key": self.api_key, "dep_iata": dep_iata, "arr_iata": arr_iata, } resp = requests.get(url, params=params) print(resp.status_code) if resp.status_code == 200: print(resp.json()) return resp.json() return {"error": resp.text} from typing import ClassVarimport requestsfrom phi.tools import ToolCITY_TO_IATA = { "new york": "JFK", "london": "LHR", "paris": "CDG", "delhi": "DEL", "tokyo": "HND", "los angeles": "LAX",}class AviationStackTool(Tool): name: ClassVar[str] = "aviationstack" description: ClassVar[str] = "Get flight data (real-time, schedules, airlines) from AviationStack API." type: str = "function" function: dict = { "name": "aviationstack", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "User input like 'Find flights from New York to London'" } }, "required": ["query"] } } # Custom fields must be declared api_key: str base_url: str = "http://api.aviationstack.com/v1" def search_flights(self, query: str): """Parse user text, resolve city names → IATA, then search flights.""" dep_iata, arr_iata = None, None query_lower = query.lower() for city, code in CITY_TO_IATA.items(): if city in query_lower: if not dep_iata: dep_iata = code else: arr_iata = code if not dep_iata or not arr_iata: return {"error": "Could not detect departure or arrival city"} """Search flights between departure and arrival airports by IATA codes.""" url = f"{self.base_url}/flights" params = { "access_key": self.api_key, "dep_iata": dep_iata, "arr_iata": arr_iata, } resp = requests.get(url, params=params) print(resp.status_code) if resp.status_code == 200: print(resp.json()) return resp.json() return {"error": resp.text} from typing import ClassVarimport requestsfrom phi.tools import ToolCITY_TO_IATA = { "new york": "JFK", "london": "LHR", "paris": "CDG", "delhi": "DEL", "tokyo": "HND", "los angeles": "LAX",}class AviationStackTool(Tool): name: ClassVar[str] = "aviationstack" description: ClassVar[str] = "Get flight data (real-time, schedules, airlines) from AviationStack API." type: str = "function" function: dict = { "name": "aviationstack", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "User input like 'Find flights from New York to London'" } }, "required": ["query"] } } # Custom fields must be declared api_key: str base_url: str = "http://api.aviationstack.com/v1" def search_flights(self, query: str): """Parse user text, resolve city names → IATA, then search flights.""" dep_iata, arr_iata = None, None query_lower = query.lower() for city, code in CITY_TO_IATA.items(): if city in query_lower: if not dep_iata: dep_iata = code else: arr_iata = code if not dep_iata or not arr_iata: return {"error": "Could not detect departure or arrival city"} """Search flights between departure and arrival airports by IATA codes.""" url = f"{self.base_url}/flights" params = { "access_key": self.api_key, "dep_iata": dep_iata, "arr_iata": arr_iata, } resp = requests.get(url, params=params) print(resp.status_code) if resp.status_code == 200: print(resp.json()) return resp.json() return {"error": resp.text} from typing import ClassVarimport requestsfrom phi.tools import ToolCITY_TO_IATA = { "new york": "JFK", "london": "LHR", "paris": "CDG", "delhi": "DEL", "tokyo": "HND", "los angeles": "LAX",}class AviationStackTool(Tool): name: ClassVar[str] = "aviationstack" description: ClassVar[str] = "Get flight data (real-time, schedules, airlines) from AviationStack API." type: str = "function" function: dict = { "name": "aviationstack", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "User input like 'Find flights from New York to London'" } }, "required": ["query"] } } # Custom fields must be declared api_key: str base_url: str = "http://api.aviationstack.com/v1" def search_flights(self, query: str): """Parse user text, resolve city names → IATA, then search flights.""" dep_iata, arr_iata = None, None query_lower = query.lower() for city, code in CITY_TO_IATA.items(): if city in query_lower: if not dep_iata: dep_iata = code else: arr_iata = code if not dep_iata or not arr_iata: return {"error": "Could not detect departure or arrival city"} """Search flights between departure and arrival airports by IATA codes.""" url = f"{self.base_url}/flights" params = { "access_key": self.api_key, "dep_iata": dep_iata, "arr_iata": arr_iata, } resp = requests.get(url, params=params) print(resp.status_code) if resp.status_code == 200: print(resp.json()) return resp.json() return {"error": resp.text} from typing import ClassVar import requests from phi.tools import Tool CITY_TO_IATA = { "new york" : "JFK" , "london" : "LHR" , "paris" : "CDG" , "delhi" : "DEL" , "tokyo" : "HND" , "los angeles" : "LAX" , } class AviationStackTool (Tool) : name: ClassVar[str] = "aviationstack" description: ClassVar[str] = "Get flight data (real-time, schedules, airlines) from AviationStack API." type: str = "function" function: dict = { "name" : "aviationstack" , "parameters" : { "type" : "object" , "properties" : { "query" : { "type" : "string" , "description" : "User input like 'Find flights from New York to London'" } }, "required" : [ "query" ] } } # Custom fields must be declared api_key: str base_url: str = "http://api.aviationstack.com/v1" def search_flights (self, query: str) : """Parse user text, resolve city names → IATA, then search flights.""" dep_iata, arr_iata = None , None query_lower = query.lower() for city, code in CITY_TO_IATA.items(): if city in query_lower: if not dep_iata: dep_iata = code else : arr_iata = code if not dep_iata or not arr_iata: return { "error" : "Could not detect departure or arrival city" } """Search flights between departure and arrival airports by IATA codes.""" url = f"{self.base_url}/flights" params = { "access_key" : self.api_key, "dep_iata" : dep_iata, "arr_iata" : arr_iata, } resp = requests.get(url, params=params) print(resp.status_code) if resp.status_code == 200 : print(resp.json()) return resp.json() return { "error" : resp.text} Step 4: Create your Agent with Groq + Tool Step 4: Create your Agent with Groq + Tool Define a Phidata agent and create a Groq model "openai/gpt-oss-20b" in it with instructions to ‘use tables to display data’. Load the Environment file and integrate AviationStackTool with your Groq model and Phidata agent, as shown in the code below. from phi.agent import Agent from phi.model.groq import Groq from dotenv import load_dotenv from aviation_agent import AviationStackTool load_dotenv() aviation_tool = AviationStackTool(api_key=AVIATIONSTACK_KEY) agent = Agent( model=Groq(id="openai/gpt-oss-20b"), tools=[aviation_tool], show_tool_calls=True, markdown=True, instructions=["use tables to display data."] ) # ------------------------------ # Test Agent Call # ------------------------------ agent.print_response("Search flight from New York to London") #agent.print_response("Search flight from New York to London and arrange the result in ascending order of price") Step 5: AI Agent Working Explanation Step 5: AI Agent Working Explanation Steps to explain the AI Agent working in detail: Agno(Phidata) receives a text prompt from the user. Agno(Phidata) receives a text prompt from the user. It activates the Phidata AI Agent, which calls the LLM model for task understanding. It activates the Phidata AI Agent, which calls the LLM model for task understanding. For LLM, we have configured the Groq model, which analyzes the prompt and decides to call your Aviation Stack tool (search_flights). For LLM, we have configured the Groq model, which analyzes the prompt and decides to call your Aviation Stack tool (search_flights). Phidata automatically passes the parsed query "Search flight from New York to London". Phidata automatically passes the parsed query "Search flight from New York to London". AviationStackTool runs the AviationStack API request and generates a response. AviationStackTool runs the AviationStack API request and generates a response. The response is in JSON format and returned to the Agent. The response is in JSON format and returned to the Agent. The model interprets the response and formats it into a tabular format. The model interprets the response and formats it into a tabular format. Agno stores the information in memory as well for future use. Agno stores the information in memory as well for future use. Step 6: Run Prompt to Extract Flight Details Step 6: Run Prompt to Extract Flight Details We are running two prompts to extract flight details separately and will compare their outputs in the next sections: Prompt 1: agent.print_response("Search flight from New York to London") Prompt 2: agent.print_response("Search flight from New York to London and arrange the result in ascending order of price") Results Comparison of Two Different Prompts to the AI Agent Results Comparison of Two Different Prompts to the AI Agent Let’s compare the output of two different prompts given to the AI Agent: Prompt 1 Output: Prompt 1 Output: Below is the output of the prompt "Search flight from New York to London”. It gives a response in tabular format with different airlines' departure and arrival time and their prices in USD. Prompt 2 Output: Prompt 2 Output: Below is the output of the prompt "Search flight from New York to London and arrange the result in ascending order of price ”. It gives a response in tabular format with different airlines' departure and arrival times, and is arranged in ascending order according to their price in USD. Potential Limitations Potential Limitations Every new technology and advancement comes with its own limitations and challenges to deal with. Here is the list of some limitations that can be faced by our Aviation Agent as well: API Constraints: Some constraints for API usage, such as AviationStack’s free tier, enforce rate limits of 100 requests/month.Response Latency: In AI Agents, external API’s are called, and they can add seconds of delay, especially when they are dealing with multiple tools.Prompt Dependency: Model performance accuracy depends on well-phrased prompts; a vague input prompt may result in an inappropriate response.Cost & Scaling: API overuse and Groq inference time may result in high cost and challenges while scaling to an agentic system.Security Issue: API keys must be stored with precautions; otherwise, their insecure storage may lead to leakage of sensitive credentials. API Constraints: Some constraints for API usage, such as AviationStack’s free tier, enforce rate limits of 100 requests/month. Response Latency: In AI Agents, external API’s are called, and they can add seconds of delay, especially when they are dealing with multiple tools. Prompt Dependency: Model performance accuracy depends on well-phrased prompts; a vague input prompt may result in an inappropriate response. Cost & Scaling: API overuse and Groq inference time may result in high cost and challenges while scaling to an agentic system. Security Issue: API keys must be stored with precautions; otherwise, their insecure storage may lead to leakage of sensitive credentials. Final thoughts Final thoughts Get your hands dirty and try to implement this aviation AI agent and scale it further across a wide range of aviation applications, including travel booking apps, travel query chatbots, intelligent airline dashboards, aviation analytics platforms, and logistics platforms. By combining real-time flight data with structured information extraction, it delivers low-latency, high-reliability insights that directly assist operational decision-making and automation at scale. An agentic AI architecture can be developed for the Aviation domain using this AI Agent as a base and integrating more domain-specific AI agents and external tools. Such a comprehensive Agentic system must be designed while considering various limitations, including API rate limits, network latency, data consistency, and prompt reliability, to ensure reliable and scalable performance in production environments with adaptability to fault tolerance.