In [ ]:
# Install (uncomment if running for the first time)
# !pip install langchain==1.3.6 langgraph==1.2.4 langchain-openai==1.2.2
In [10]:
import importlib.metadata
# List the distribution package names
packages = ["langchain", "langgraph", "langchain-openai", ]
for package in packages:
try:
version = importlib.metadata.version(package)
print(f"{package} version: {version}")
except importlib.metadata.PackageNotFoundError:
print(f"{package} is not installed in this environment.")
langchain version: 1.3.6 langgraph version: 1.2.4 langchain-openai version: 1.2.2
In [ ]:
1. Imports¶
In [1]:
import os, requests
from langchain_openai import ChatOpenAI
from langchain.agents import create_agent
from langchain.tools import tool
import getpass
In [2]:
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
# os.environ["OPENAI_API_KEY"] = "key here" # or uncomment and enter key here
# Initialize the LLM that will power the agent's reasoning
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
response = llm.invoke("Hello! Respond with the word 'Connected' if you can hear me.")
print("--- Connection Successful ---")
print(response.content)
--- Connection Successful --- Connected
In [ ]:
2. TOOLS¶
In [4]:
# TOOL 1: Calculator
@tool
def calculator(expression: str) -> str:
"""
Evaluates a basic math expression, e.g. '2 + 2', and returns the result.
"""
print("...Running calculator tool")
try:
result = eval(expression)
return str(result)
except Exception as e:
return f"Error: {e}"
# TOOL 2: Weather
@tool
def get_weather(city: str) -> str:
"""
Returns the current weather for a given city.
"""
print("...Running get_weather tool")
try:
# Step 1: Convert city → lat/lon
geo_url = f"https://geocoding-api.open-meteo.com/v1/search?name={city}"
geo_res = requests.get(geo_url).json()
# Check if the results list exists and is not empty
if "results" not in geo_res or not geo_res["results"]:
return "City not found"
# FIX: Ensure you keep the [0] index to pull from the first matching city search result
lat = geo_res["results"][0]["latitude"]
lon = geo_res["results"][0]["longitude"]
# Step 2: Get weather
weather_url = f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}¤t_weather=true"
weather_res = requests.get(weather_url).json()
temp = weather_res["current_weather"]["temperature"]
wind = weather_res["current_weather"]["windspeed"]
return f"Temperature: {temp}°C, Wind Speed: {wind} km/h"
except Exception as e:
# Better practice: Return or log the specific error string for easier debugging
return f"Error fetching weather: {e}"
In [15]:
print(calculator.invoke("3*5"))
...Running calculator tool 15
In [25]:
print(get_weather.invoke("Noida"))
...Running get_weather tool Temperature: 27.8°C, Wind Speed: 8.8 km/h
In [ ]:
3. Build the agent with tools¶
In [8]:
# Register both tools so the agent knows they exist and can pick between them
tools = [calculator, get_weather]
SYSTEM_PROMPT = (
"You are a helpful assistant with access to tools. "
"CRITICAL: Do NOT use markdown, bolding (**), italics (*), or LaTeX formatting like \\( \\) or \\[ \\]."
"Provide responses in raw, plain text only. Example: Write '1 + 2 * 4 = 9' instead of structural equations."
)
# Create the agent.
# docstring/description, whether to use a tool or just answer directly --
agent = create_agent(
model=llm,
tools=tools,
# Not needed. The agent figures out the tool based on docstring
system_prompt=SYSTEM_PROMPT
)
In [ ]:
4. RUN THE AGENT¶
Try¶
input1: What is 1 + 2 * 4 ?
input2: What is the current weather condition in Moscow ?
input3: I am trying to calculate this math expression: one plus two times four ?
input4: I am living in Moscow. I was thinking of going to the park. I wonder how is weather outside ? Is it going going to be nice today ?
In [9]:
# keeps asking until you type 'exit'
while True:
user_input = input("\nAsk something (or type 'q' to quit): ")
if user_input.lower() == "q":
break
# create_agent's graph expects/returns a list of chat-style messages
result = agent.invoke(
{"messages": [{"role": "user", "content": user_input}]}
)
# The final answer is the content of the last message in the returned state
final_answer = result["messages"][-1].content
print("\nFinal Answer:", final_answer)
...Running calculator tool Final Answer: 1 + 2 * 4 = 9
...Running get_weather tool Final Answer: The current weather in Moscow is 19.3°C with a wind speed of 6.6 km/h.
...Running calculator tool Final Answer: The result of the expression one plus two times four is 9.
...Running get_weather tool Final Answer: The current temperature in Moscow is 19.3°C with a wind speed of 6.6 km/h. It seems like a nice day to go to the park!
In [ ]:
Sample run¶
Ask something (or type 'q' to quit): What is 1 + 2 * 4 ?
...Running calculator tool
Final Answer: 1 + 2 * 4 = 9
Ask something (or type 'q' to quit): What is the current weather condition in Moscow ?
...Running get_weather tool
Final Answer: The current weather in Moscow is 19.3°C with a wind speed of 6.6 km/h.
Ask something (or type 'q' to quit): I am trying to calculate this math expression: one plus two times four ?
...Running calculator tool
Final Answer: The result of the expression one plus two times four is 9.
Ask something (or type 'q' to quit): I am living in Moscow. I was thinking of going to the park. I wonder how is weather outside ? Is it going going to be nice today ?
...Running get_weather tool
Final Answer: The current temperature in Moscow is 19.3°C with a wind speed of 6.6 km/h. It seems like a nice day to go to the park!
Ask something (or type 'q' to quit): q
In [ ]:
5. Memory¶
- Previously, agent did not possess memory. So, it would not remember previous chats
- Now we give it memory: this way, it remembers previous chat conversations
In [11]:
from langgraph.checkpoint.memory import InMemorySaver
# A checkpointer gives the agent memory: it stores the message history
# per "thread_id", so the same conversation can span multiple .invoke() calls.
checkpointer = InMemorySaver()
agent_with_memory = create_agent(
model=llm,
tools=tools,
system_prompt=SYSTEM_PROMPT,
checkpointer=checkpointer,
)
# Every conversation needs a thread_id — this is how the agent knows
# which conversation's memory to load. Different thread_ids = separate,
# isolated conversations (e.g. different users).
config = {"configurable": {"thread_id": "demo-conversation-1"}}
# Turn 1: mention the city explicitly
chat1 = "My name is Alex. What is 2 + 7 * 3 ?"
result1 = agent_with_memory.invoke(
{"messages": [{"role": "user", "content": chat1}]},
config=config,
)
print("Turn 1:", result1["messages"][-1].content)
# Turn 2: a follow-up that does NOT repeat the city.
# Without memory, the agent wouldn't know which city we're asking about.
# With the checkpointer, it recalls "New Delhi" from Turn 1 automatically.
chat2 = "What is my name ?"
result2 = agent_with_memory.invoke(
{"messages": [{"role": "user", "content": chat2}]},
config=config,
)
print("\nTurn 2:", result2["messages"][-1].content)
...Running calculator tool Turn 1: The result of 2 + 7 * 3 is 23. Turn 2: Your name is Alex.
In [ ]:
