Full source code
Copy the complete source code below. Install the required packages listed in the comments at the top.
# Complete working AI agent with tools
# Uses OpenAI function calling (works with Claude tool use too)
import openai
import json
import requests
from datetime import datetime
client = openai.OpenAI() # Replace with Anthropic client for Claude
# ── DEFINE TOOLS ────────────────────────────────────────────────────
tools = [
{
"type": "function",
"function": {
"name": "search_web",
"description": "Search the web for current information",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"}
},
"required": ["query"]
}
}
},
{
"type": "function",
"function": {
"name": "get_stock_price",
"description": "Get current stock price for NSE/BSE stocks",
"parameters": {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Stock symbol like RELIANCE, TCS, INFY"}
},
"required": ["symbol"]
}
}
},
{
"type": "function",
"function": {
"name": "calculate",
"description": "Perform mathematical calculations",
"parameters": {
"type": "object",
"properties": {
"expression": {"type": "string", "description": "Math expression to evaluate"}
},
"required": ["expression"]
}
}
}
]
# ── IMPLEMENT TOOLS ──────────────────────────────────────────────────
def search_web(query):
"""Search using Perplexity API (free tier available)"""
response = requests.post(
"https://api.perplexity.ai/chat/completions",
headers={"Authorization": f"Bearer {PERPLEXITY_API_KEY}"},
json={"model": "sonar", "messages": [{"role": "user", "content": query}]}
)
return response.json()["choices"][0]["message"]["content"]
def get_stock_price(symbol):
"""Get stock price using yfinance"""
import yfinance as yf
stock = yf.Ticker(f"{symbol}.NS") # .NS for NSE, .BO for BSE
info = stock.info
return {
"symbol": symbol,
"price": info.get("currentPrice"),
"pe_ratio": info.get("trailingPE"),
"52w_high": info.get("fiftyTwoWeekHigh"),
"52w_low": info.get("fiftyTwoWeekLow"),
"market_cap": info.get("marketCap")
}
def calculate(expression):
"""Safely evaluate math expressions"""
import ast
try:
tree = ast.parse(expression, mode='eval')
result = eval(compile(tree, '<string>', 'eval'))
return {"result": result, "expression": expression}
except Exception as e:
return {"error": str(e)}
def execute_tool(name, arguments):
"""Route tool calls to implementations"""
if name == "search_web":
return search_web(**arguments)
elif name == "get_stock_price":
return get_stock_price(**arguments)
elif name == "calculate":
return calculate(**arguments)
# ── AGENT LOOP ───────────────────────────────────────────────────────
def run_agent(user_query, max_iterations=10):
"""
The ReAct loop: Reason → Act → Observe → Repeat
Keeps running until the agent has a final answer or hits max_iterations
"""
messages = [
{
"role": "system",
"content": """You are a helpful AI assistant for Indian investors and professionals.
You have access to web search, stock prices, and calculation tools.
Use tools when you need current information. Think step by step."""
},
{"role": "user", "content": user_query}
]
print(f"\n🤖 Agent started for: {user_query}\n")
for i in range(max_iterations):
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
messages.append(message)
# No tool calls = agent has final answer
if not message.tool_calls:
print(f"\n✅ Final Answer:\n{message.content}")
return message.content
# Execute each tool call
for tool_call in message.tool_calls:
name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
print(f" 🔧 Using tool: {name}({args})")
result = execute_tool(name, args)
print(f" 📊 Result: {str(result)[:100]}...")
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result)
})
return "Max iterations reached"
# ── TEST IT ──────────────────────────────────────────────────────────
if __name__ == "__main__":
# Example queries
run_agent("What is the current P/E ratio of Reliance Industries and is it overvalued compared to sector average?")
run_agent("Search for latest news on SEBI regulations and summarise key points for a retail investor")
run_agent("If I invest ₹10,000/month with 12% annual return for 15 years, what's my final corpus?")