The AI Swiss Army Knife: How to Give Your Agent Multiple Tools to Choose From
Alright, awesome work on Part 2! You built your first AI agent, and you saw that incredible "aha!" moment when Gemini used your get_current_weather tool to fetch data. That's a huge step – you've basically taught an AI how to do something outside of just chatting. High five! You went from a static chatbot to an AI that could actually perform an action in the "real world" (even if it was a simulated one!). That fundamental concept of function calling is the bedrock for all the really exciting agentic AI stuff.
But what if your agent could do more than just tell you the weather? What if it could also check stock prices, solve complex math problems, or even search the web, all from the same conversation? Imagine the possibilities! That's precisely what we're tackling today. We're going to transform your simple weather reporter into a real AI Swiss Army Knife, equipped with a whole arsenal of tools to tackle diverse requests. This is where your agent starts to feel less like a simple script and more like a genuinely intelligent assistant.
Why More Tools? Because Versatility Rocks!
Think about it: a human assistant isn't limited to just one task, right? If you ask them to book a meeting, they use a calendar tool. If you ask for a report, they might use a spreadsheet tool or a data analysis tool. They probably use a web browser for research, and perhaps a calculator for quick sums. The more diverse tools they have at their disposal, and the better they are at choosing the right tool for the job, the more valuable and indispensable they become to you.
It's absolutely the same for AI agents! Giving your agent multiple tools makes it incredibly versatile and powerful, massively expanding its practical applications. This means several key advantages:
- Handling Diverse Requests: Your agent can respond intelligently to a much wider array of user queries without needing to be redesigned for each new task. Instead of just "What's the weather?", it can handle "How much is Apple stock?", "What's 10 times 25?", or "Find me the current news headlines." This dramatically increases its usefulness.
- Increased Utility: The agent transitions from being a niche helper to a general-purpose assistant. In a business context, this could mean one agent handling customer inquiries, sales data analysis, and even internal administrative tasks, rather than needing separate, specialized bots for each. For personal use, it means one AI companion for many of your digital needs.
- Intelligent Routing (The Coolest Part!): Here's the magic. You don't have to tell the agent which specific tool to use. You don't have to say, "Hey Gemini, use the
get_stock_pricefunction for AAPL." Instead, you simply say, "What's Apple's stock price?" Gemini, with its powerful Large Language Model (LLM) reasoning capabilities, will look at your natural language input, compare it against the descriptions of all the tools it knows about, and then intelligently figure out that theget_stock_pricetool is the best fit. It then formulates the correct arguments (liketicker='AAPL') and tells your code to execute that tool. This level of semantic understanding and autonomous decision-making is what truly makes an AI agent feel "smart" and intuitive to use. It reduces the burden on the user, making interactions feel more natural and human-like.
Equipping Our Agent with New Gear!
We'll start with our trusty get_current_weather function from Part 2. It’s a perfect example of a function that fetches external information. Then, we'll add two exciting new functions to our agent's repertoire: one to get a simulated stock price (because connecting to a live financial API directly in a tutorial can be tricky with authentication, rate limits, etc.) and another to solve a math problem. This diversity will really showcase Gemini's ability to choose the right tool for the job.
Our Updated "Toolbox" Functions
import google.generativeai as genai
import json # Still useful for pretty-printing results and making them readable!
# --- Our Existing Weather Tool (slightly adjusted for clarity and error message) ---
def get_current_weather(location: str, unit: str = "celsius"):
"""
Gets the current weather conditions for a specified location.
In a real application, this function would make an HTTP request to a weather API
(e.g., OpenWeatherMap, AccuWeather) to fetch real-time data. For this tutorial,
we simulate that interaction with a predefined dictionary.
Args:
location (str): The city or location (e.g., "London", "Tokyo").
Gemini will extract this from the user's query.
unit (str, optional): The unit for temperature. Can be "celsius" or "fahrenheit".
Gemini will try to infer this; defaults to "celsius" if not specified.
Returns:
dict: A dictionary containing weather information (temperature, conditions, unit).
Returns an error dictionary if the location is not recognized in our mock data
or if an unsupported unit is requested.
"""
print(f"\nDEBUG: get_current_weather called for {location} in {unit}")
weather_data = {
"London": {"temperature": {"celsius": 18, "fahrenheit": 64}, "conditions": "Partly cloudy"},
"Tokyo": {"temperature": {"celsius": 25, "fahrenheit": 77}, "conditions": "Sunny"},
"New York": {"temperature": {"celsius": 22, "fahrenheit": 72}, "conditions": "Light rain"},
"Mumbai": {"temperature": {"celsius": 30, "fahrenheit": 86}, "conditions": "Humid and hot"},
"Berlin": {"temperature": {"celsius": 15, "fahrenheit": 59}, "conditions": "Overcast"},
}
if location in weather_data:
temp_value = weather_data[location]["temperature"].get(unit, None)
if temp_value is not None:
return {
"location": location,
"temperature": temp_value,
"unit": unit,
"conditions": weather_data[location]["conditions"]
}
else:
return {"error": f"Invalid temperature unit '{unit}' specified for {location}. Please choose 'celsius' or 'fahrenheit'."}
else:
return {"error": f"Weather data not available for '{location}'. Please try a major city from our list (London, Tokyo, New York, Mumbai, Berlin)."}
# --- New Tool 1: Get Stock Price ---
def get_stock_price(ticker: str):
"""
Gets the current simulated stock price for a given stock ticker symbol.
In a real-world scenario, this would integrate with a financial data API
(e.g., Alpha Vantage, Finnhub, Polygon.io) to retrieve live stock quotes.
Args:
ticker (str): The stock ticker symbol (e.g., "GOOG" for Google, "AAPL" for Apple, "MSFT" for Microsoft).
Gemini will identify this from phrases like "price of Apple stock."
Returns:
dict: A dictionary with the stock ticker and its simulated price.
Returns an error dictionary if the ticker is not in our mock data.
"""
print(f"\nDEBUG: get_stock_price called for {ticker}")
# Simulate stock prices for demonstration purposes
stock_prices = {
"GOOG": 175.50,
"AAPL": 210.25,
"MSFT": 450.70,
"AMZN": 190.10,
"NVDA": 1300.00 # Wow, NVDA! A hot stock in 2025!
}
price = stock_prices.get(ticker.upper()) # .upper() ensures consistent lookup, e.g., 'aapl' becomes 'AAPL'
if price:
return {"ticker": ticker.upper(), "price": price}
else:
return {"error": f"Stock price data not available for '{ticker}'. Try GOOG, AAPL, MSFT, AMZN, or NVDA."}
# --- New Tool 2: Solve Math Problem ---
def solve_math_problem(expression: str):
"""
Solves a simple mathematical expression provided as a string.
This tool uses Python's `eval()` function, which can be risky with untrusted input.
For production environments, consider using a safer mathematical expression parser library.
Args:
expression (str): The mathematical expression to solve (e.g., "5 + 3", "10 * 2 / 4", "(100 - 20) / 4").
Gemini will try to convert natural language math problems into this format.
Returns:
dict: A dictionary containing the original expression and its calculated result.
Returns an error dictionary if the expression cannot be solved.
"""
print(f"\nDEBUG: solve_math_problem called for '{expression}'")
try:
# WARNING: Using eval() with arbitrary user input can be a severe security risk!
# An attacker could potentially execute malicious code.
# For a real application, consider safer alternatives like `ast.literal_eval`
# for simple literals, or a dedicated math parsing library like `sympy` or `numexpr`
# if more complex expressions are needed, combined with strict input validation.
result = eval(expression)
return {"expression": expression, "result": result}
except Exception as e:
return {"error": f"Could not solve expression: '{expression}'. Please provide a simple, valid mathematical expression (e.g., '2 + 2', '10 * 5', '20 / 4'). Error details: {e}"}
# --- End of Tool Functions --You can see we've kept the structure similar for each tool: a clear Python function, a detailed docstring (which is crucial for us, and implicitly, for Gemini's understanding of the tool!), and a print statement for debugging. The docstrings for these functions are particularly important because they directly inform the description field when we declare them to Gemini. The clearer your description, the better Gemini will be at figuring out when to use that tool.
Registering ALL the Tools with Gemini!
This is the cool trick and where the real "Swiss Army Knife" magic happens! Instead of just passing one FunctionDeclaration (like in Part 2), we now create a list of them. Each item in this list describes a different tool that your agent can use. Gemini is super smart; it will then look through this entire list of tool descriptions and figure out which one (or ones!) to use based on the nuances of the user's natural language request.
# --- Tool Declarations for Gemini ---
# Weather tool declaration (same as before)
weather_tool_declaration = genai.GenerativeModel.FunctionDeclaration(
name="get_current_weather", # This name *must* exactly match your Python function name
description="Gets the current weather conditions for a specified location.", # Clear, concise description helps Gemini decide when to use it!
parameters=genai.GenerativeModel.Schema( # Defines the arguments our Python function expects
type=genai.GenerativeModel.Type.OBJECT,
properties={
"location": genai.GenerativeModel.Schema(
type=genai.GenerativeModel.Type.STRING,
description="The city or location (e.g., London, Tokyo)" # Description for this specific parameter
),
"unit": genai.GenerativeModel.Schema(
type=genai.GenerativeModel.Type.STRING,
description="The unit for temperature. Can be 'celsius' or 'fahrenheit'.",
enum=["celsius", "fahrenheit"] # `enum` is great for restricting valid inputs Gemini can generate
)
},
required=["location"] # 'location' is a mandatory argument for this function
)
)
# Stock tool declaration - A new declaration for our new tool!
stock_tool_declaration = genai.GenerativeModel.FunctionDeclaration(
name="get_stock_price",
description="Gets the current simulated stock price for a given stock ticker.",
parameters=genai.GenerativeModel.Schema(
type=genai.GenerativeModel.Type.OBJECT,
properties={
"ticker": genai.GenerativeModel.Schema(
type=genai.GenerativeModel.Type.STRING,
description="The stock ticker symbol (e.g., GOOG, AAPL, MSFT)"
)
},
required=["ticker"] # 'ticker' is mandatory for this function
)
)
# Math tool declaration - Another new declaration!
math_tool_declaration = genai.GenerativeModel.FunctionDeclaration(
name="solve_math_problem",
description="Solves a simple mathematical expression.",
parameters=genai.GenerativeModel.Schema(
type=genai.GenerativeModel.Type.OBJECT,
properties={
"expression": genai.GenerativeModel.Schema(
type=genai.GenerativeModel.Type.STRING,
description="The mathematical expression to solve (e.g., '5 + 3', '10 * 2 / 4')"
)
},
required=["expression"] # 'expression' is mandatory
)
)
# Initialize the Gemini model with ALL our tools!
# This list tells Gemini about every function it can potentially use.
# Gemini will then dynamically decide which function to call based on the user's intent.
model = genai.GenerativeModel(
model_name="gemini-pro", # Still using 'gemini-pro', 'gemini-2.0-flash' is also an option
tools=[
genai.GenerativeModel.Tool(function_declarations=[weather_tool_declaration]),
genai.GenerativeModel.Tool(function_declarations=[stock_tool_declaration]),
genai.GenerativeModel.Tool(function_declarations=[math_tool_declaration])
]
)
# Note: You can also combine all function declarations into a single Tool object if preferred:
# tools=[genai.GenerativeModel.Tool(function_declarations=[
# weather_tool_declaration,
# stock_tool_declaration,
# math_tool_declaration
# ])]
# Both ways work perfectly! The key is that Gemini receives a comprehensive list of all callable functions.This section is crucial because it's where you define the contract between your Python code and Gemini. The name must match your function, the description is how Gemini understands its purpose, and parameters (type, properties, required, enum) are how Gemini knows what information to extract from the user's query to correctly call your function. Well-defined tool declarations are paramount for robust agent behavior!
The Agent's Intelligence in Action: Picking the Right Tool
Now, for the true magic of the multi-tool agent! Our handle_agent_query function (which we updated from get_weather_report for a more general name) will stay largely the same in its core logic, but it now has the smarts to handle any tool request. The amazing thing is that Gemini will analyze your input, compare it to the description of each tool you've provided, and then, with its advanced reasoning, tell your script precisely which tool to call and with what arguments. It's like having a brilliant, invisible dispatcher for your entire toolbox!
Since we're handling multiple tools, we'll use a simple but effective Python dictionary to map the tool names (as declared to Gemini in our FunctionDeclaration objects) to our actual Python functions. This makes it super easy and clean to dynamically call the correct function without needing a long chain of if/else statements.
# --- Chat Interaction Loop (now handles multiple tools dynamically!) ---
chat = model.start_chat(enable_automatic_function_calling=False)
# We keep `enable_automatic_function_calling=False` so you can clearly see the
# intermediate step where Gemini *requests* a tool call before we execute it.
# This makes the learning process very transparent!
# A dictionary to map Gemini's tool requests (by name) to our actual Python functions.
# This allows us to look up and execute the right function dynamically.
available_functions = {
"get_current_weather": get_current_weather,
"get_stock_price": get_stock_price,
"solve_math_problem": solve_math_problem,
}
def handle_agent_query(user_query: str):
"""
Sends a user query to the AI agent and orchestrates the processing of potential tool calls.
This function demonstrates the core loop of an AI agent with multiple tools:
1. Send user query to Gemini.
2. Check if Gemini recommends a tool call.
3. If yes, execute the specified tool (Python function) with the arguments provided by Gemini.
4. Send the tool's result back to Gemini.
5. Gemini generates the final, human-readable response based on the tool's output.
6. If no tool is needed, Gemini responds directly.
"""
print(f"\n--- User: {user_query} ---")
response = chat.send_message(user_query)
# First, we check if Gemini has suggested any function calls in its response candidate.
if response.candidates and response.candidates[0].function_calls:
print("DEBUG: Gemini wants to call a tool(s)!")
# For simplicity in this tutorial, we'll process only the *first* tool call suggested.
# More advanced scenarios might involve sequential tool calls or parallel calls.
function_call = response.candidates[0].function_calls[0]
tool_name = function_call.name # Extract the name of the tool Gemini wants to use
tool_args = function_call.args # Extract the arguments Gemini wants to pass to the tool
print(f"DEBUG: Tool requested: {tool_name} with args: {tool_args}")
# Now, we look up the requested tool name in our `available_functions` dictionary.
if tool_name in available_functions:
tool_function = available_functions[tool_name] # Get the actual Python function
try:
# Execute the Python function using the arguments provided by Gemini.
# The `**tool_args` syntax unpacks the dictionary `tool_args` into keyword arguments.
tool_result = tool_function(**tool_args)
print(f"DEBUG: Tool result: {json.dumps(tool_result, indent=2)}")
# CRITICAL STEP: Send the tool's result *back* to Gemini.
# This is the "feedback loop." Without this, Gemini wouldn't know
# what happened after its tool request and couldn't formulate a proper response.
final_response = chat.send_message(
genai.protos.Part(
function_response=genai.protos.FunctionResponse(
name=tool_name, # The name of the function that was called
response=tool_result # The actual result data from our Python function
)
)
)
print(f"--- Agent: {final_response.text}")
except Exception as e:
# Handle any runtime errors that occur when executing our Python tool function.
print(f"ERROR: Error executing tool '{tool_name}': {e}")
print(f"--- Agent: I encountered an error while trying to complete your request using the '{tool_name}' tool. Please try again or rephrase your request.")
else:
# This case handles if Gemini suggests a tool name that we haven't actually
# defined or mapped in our `available_functions` dictionary.
print(f"ERROR: Unknown tool requested by Gemini: '{tool_name}'. This tool is not available in our Python code.")
print(f"--- Agent: I'm sorry, I seem to have been asked to use a tool I don't recognize. My apologies! Can I help with something else?")
else:
# If no tool call is detected in Gemini's response, it means Gemini
# generated a direct text response to the user's query.
print(f"--- Agent: {response.text}")
# --- Let's try out our AI Swiss Army Knife! ---
# Weather queries - testing various formats and an unknown city
handle_agent_query("What's the weather in Tokyo?")
handle_agent_query("Tell me the temperature in London in Fahrenheit.")
handle_agent_query("How's the weather in Berlin right now?")
handle_agent_query("What's the weather like in some faraway place like Atlantis?") # Should trigger an error from our mock data
# Stock queries - testing different tickers and an unknown one
handle_agent_query("What's the stock price of Apple?") # Should get AAPL
handle_agent_query("Can you give me the price of GOOG?")
handle_agent_query("How much is NVDA stock trading at?")
handle_agent_query("What's the current value of ZYX Corp?") # Should trigger an error from our mock data
# Math queries - testing simple math and a more complex/symbolic one our tool can't handle
handle_agent_query("What is 150 divided by 3 plus 10?") # Expects "150 / 3 + 10"
handle_agent_query("Calculate 25 times 4 minus 7.") # Expects "25 * 4 - 7"
handle_agent_query("What is (2+3)*4?") # Should work
handle_agent_query("Solve for x: 2x + 5 = 15") # This is symbolic algebra, our `eval()` tool can't handle it directly, expect an error
# General questions (should NOT trigger any tools, Gemini should respond directly)
handle_agent_query("Tell me a joke.")
handle_agent_query("What's the capital of Canada?")
handle_agent_query("Can you write a short poem about a cat?")
handle_agent_query("What are the benefits of learning Python?")The Full Code: Your Multi-Tool Agent!
Copy and paste this complete script into a Python file (e.g., multi_tool_agent.py) and run it from your terminal: python multi_tool_agent.py. Watch the debug messages in your console to see which tool Gemini intelligently picks for each query and the results it gets back – this is super helpful for understanding the entire flow from query to final answer!
import google.generativeai as genai
import json
# --- Our Tool Functions ---
def get_current_weather(location: str, unit: str = "celsius"):
"""
Gets the current weather conditions for a specified location.
Args:
location (str): The city or location (e.g., "London", "Tokyo").
unit (str, optional): The unit for temperature. Can be "celsius" or "fahrenheit".
Defaults to "celsius".
Returns:
dict: A dictionary containing weather information (temperature, conditions).
"""
print(f"\nDEBUG: get_current_weather called for {location} in {unit}")
weather_data = {
"London": {"temperature": {"celsius": 18, "fahrenheit": 64}, "conditions": "Partly cloudy"},
"Tokyo": {"temperature": {"celsius": 25, "fahrenheit": 77}, "conditions": "Sunny"},
"New York": {"temperature": {"celsius": 22, "fahrenheit": 72}, "conditions": "Light rain"},
"Mumbai": {"temperature": {"celsius": 30, "fahrenheit": 86}, "conditions": "Humid and hot"},
"Berlin": {"temperature": {"celsius": 15, "fahrenheit": 59}, "conditions": "Overcast"},
}
if location in weather_data:
temp_value = weather_data[location]["temperature"].get(unit, None)
if temp_value is not None:
return {
"location": location,
"temperature": temp_value,
"unit": unit,
"conditions": weather_data[location]["conditions"]
}
else:
return {"error": f"Invalid unit specified for location."}
else:
return {"error": f"Weather data not available for {location}. Please try a major city from our list."}
def get_stock_price(ticker: str):
"""
Gets the current simulated stock price for a given stock ticker.
Args:
ticker (str): The stock ticker symbol (e.g., "GOOG", "AAPL", "MSFT").
Returns:
dict: A dictionary with the stock ticker and its simulated price.
"""
print(f"\nDEBUG: get_stock_price called for {ticker}")
stock_prices = {
"GOOG": 175.50,
"AAPL": 210.25,
"MSFT": 450.70,
"AMZN": 190.10,
"NVDA": 1300.00
}
price = stock_prices.get(ticker.upper())
if price:
return {"ticker": ticker.upper(), "price": price}
else:
return {"error": f"Stock price data not available for {ticker}. Try GOOG, AAPL, MSFT, AMZN, or NVDA."}
def solve_math_problem(expression: str):
"""
Solves a simple mathematical expression.
Args:
expression (str): The mathematical expression to solve (e.g., "5 + 3", "10 * 2 / 4").
Returns:
dict: A dictionary containing the expression and its calculated result.
"""
print(f"\nDEBUG: solve_math_problem called for '{expression}'")
try:
# WARNING: Using eval() with arbitrary user input can be a security risk.
# For a real application, consider a safer math evaluation library or strict parsing.
result = eval(expression)
return {"expression": expression, "result": result}
except Exception as e:
return {"error": f"Could not solve expression: '{expression}'. Please provide a simple, valid mathematical expression. Error: {e}"}
# --- Tool Declarations for Gemini ---
# Weather tool
weather_tool_declaration = genai.GenerativeModel.FunctionDeclaration(
name="get_current_weather",
description="Gets the current weather conditions for a specified location.",
parameters=genai.GenerativeModel.Schema(
type=genai.GenerativeModel.Type.OBJECT,
properties={
"location": genai.GenerativeModel.Schema(
type=genai.GenerativeModel.Type.STRING,
description="The city or location (e.g., London, Tokyo)"
),
"unit": genai.GenerativeModel.Schema(
type=genai.GenerativeModel.Type.STRING,
description="The unit for temperature. Can be 'celsius' or 'fahrenheit'.",
enum=["celsius", "fahrenheit"]
)
},
required=["location"]
)
)
# Stock tool
stock_tool_declaration = genai.GenerativeModel.FunctionDeclaration(
name="get_stock_price",
description="Gets the current simulated stock price for a given stock ticker.",
parameters=genai.GenerativeModel.Schema(
type=genai.GenerativeModel.Type.OBJECT,
properties={
"ticker": genai.GenerativeModel.Schema(
type=genai.GenerativeModel.Type.STRING,
description="The stock ticker symbol (e.g., GOOG, AAPL, MSFT)"
)
},
required=["ticker"]
)
)
# Math tool
math_tool_declaration = genai.GenerativeModel.FunctionDeclaration(
name="solve_math_problem",
description="Solves a simple mathematical expression.",
parameters=genai.GenerativeModel.Schema(
type=genai.GenerativeModel.Type.OBJECT,
properties={
"expression": genai.GenerativeModel.Schema(
type=genai.GenerativeModel.Type.STRING,
description="The mathematical expression to solve (e.g., '5 + 3', '10 * 2 / 4')"
)
},
required=["expression"]
)
)
# Initialize the Gemini model with ALL our tools!
model = genai.GenerativeModel(
model_name="gemini-pro", # Can also use 'gemini-2.0-flash'
tools=[
genai.GenerativeModel.Tool(function_declarations=[weather_tool_declaration]),
genai.GenerativeModel.Tool(function_declarations=[stock_tool_declaration]),
genai.GenerativeModel.Tool(function_declarations=[math_tool_declaration])
]
)
# --- Chat Interaction Loop ---
chat = model.start_chat(enable_automatic_function_calling=False)
# A dictionary to map Gemini's requested tool names to our actual Python functions
available_functions = {
"get_current_weather": get_current_weather,
"get_stock_price": get_stock_price,
"solve_math_problem": solve_math_problem,
}
def handle_agent_query(user_query: str):
"""
Sends a query to the AI agent and processes potential tool calls.
This function acts as the orchestrator, mediating between the user, Gemini, and the tools.
"""
print(f"\n--- User: {user_query} ---")
response = chat.send_message(user_query)
if response.candidates and response.candidates[0].function_calls:
print("DEBUG: Gemini wants to call a tool(s)!")
function_call = response.candidates[0].function_calls[0]
tool_name = function_call.name
tool_args = function_call.args
print(f"DEBUG: Tool requested: {tool_name} with args: {tool_args}")
if tool_name in available_functions:
tool_function = available_functions[tool_name]
tool_result = tool_function(**tool_args) # Execute the Python function
print(f"DEBUG: Tool result: {json.dumps(tool_result, indent=2)}")
# Send the result back to Gemini so it can formulate the final user-friendly response.
final_response = chat.send_message(
genai.protos.Part(
function_response=genai.protos.FunctionResponse(
name=tool_name,
response=tool_result
)
)
)
print(f"--- Agent: {final_response.text}")
else:
print(f"ERROR: Unknown tool requested: {tool_name} by Gemini. This tool is not available.")
print(f"--- Agent: I'm sorry, I seem to have been asked to use a tool I don't recognize. Can I help with something else?")
else:
# If no function call is detected, Gemini provides a direct text response.
print(f"--- Agent: {response.text}")
# --- Test Cases: Let's see our Swiss Army Knife in action! ---
print("\n--- Testing Weather Queries ---")
handle_agent_query("What's the weather like in Tokyo?")
handle_agent_query("Tell me the temperature in London in Fahrenheit.")
handle_agent_query("How's the weather in Berlin right now?")
handle_agent_query("What's the weather like in some faraway place like Atlantis?") # Expect an error from our mock data
print("\n--- Testing Stock Queries ---")
handle_agent_query("What's the stock price of Apple?")
handle_agent_query("Can you give me the price of GOOG?")
handle_agent_query("How much is NVDA stock trading at today?")
handle_agent_query("What's the current value of ZYX Corp?") # Expect an error from our mock data
print("\n--- Testing Math Queries ---")
handle_agent_query("What is 150 divided by 3 plus 10?")
handle_agent_query("Calculate 25 times 4 minus 7.")
handle_agent_query("What is (2+3)*4?") # Should work
handle_agent_query("Solve for x: 2x + 5 = 15") # This is symbolic, our `eval` tool can't handle it directly, expect an error
print("\n--- Testing General Questions (should NOT trigger tools) ---")
handle_agent_query("Tell me a joke.")
handle_agent_query("What's the capital of Canada?")
handle_agent_query("Can you write a short poem about a cat?")
handle_agent_query("What are the benefits of learning Python?")