AI Agent
1. What You'll Learn
| No. | Content |
|---|---|
| ❶ | The Difference Between an Agent and a Regular Chatbot |
| ❷ | ReAct Mode (Reasoning + Action) |
| ❸ | Function Calling |
| ❹ | Agent Planning and Memory |
| ❺ | Implementing a Simple Agent in Python |
2. The Story
Bob wanted the AI to help him "check Apple's latest stock price and analyze whether it's worth investing in." A standard ChatGPT would only respond, "I can't connect to the internet. As of the cutoff date for my training data..."—the information is outdated and completely useless.
Alice built an AI agent using the Agent framework. When asked the same question, the agent decides for itself:
- Open the Search Tool → Find that AAPL’s current stock price is $195.27, with a P/E ratio of 31.2
- Open the Calculation Tool → Calculate the expected annualized return to be approximately 6.8%
- Based on the above results → Generate investment recommendations
Bob exclaimed, "Isn't this just the AI thinking and working on its own?"
The key difference: A chatbot only "talks," while an agent "acts."
3. What Is an AI Agent?
(1) Definition of an Agent
AI Agent = LLM + Tools + Memory + Planning
| Component | Function | Analogy |
|---|---|---|
| LLM (Large Language Model) | Understanding, Reasoning, Decision-Making | Brain |
| Tools | Perform actions (search, calculate, execute code, etc.) | Both hands |
| Memory | Saves conversation history and long-term knowledge | Notebook |
| Planning | Break down tasks and outline steps | Schedule |
A typical chatbot relies solely on an LLM, much like an advisor who “can only talk but can’t take action.” An agent, however, equipped with tools, memory, and planning capabilities, is like an assistant who can independently search the web for information, perform calculations, and write reports.
(2) Chatbot vs Agent vs Workflow
| Dimension | Chatbot | Agent | Workflow |
|---|---|---|---|
| Decision-Making Method | No decision; answer directly | LLM decides the next step on its own | Predefined human-defined process |
| Tool Usage | None | Dynamic Selection and Invocation | Fixed Node Invocation |
| Flexibility | Low | High | Medium |
| Controllability | High | Medium | High |
| Typical Scenarios | Q&A, Casual Chat | Research, Analysis, Independent Exploration | Workflows, Approval Processes |
4. ReAct Model—Reasoning + Action
(1) The Core Concept of ReAct
ReAct (Reasoning + Acting) is the most classic decision-making model for agents:
- Observation: Receive user input or results returned by the tool
- Thought: The LLM analyzes the current situation and decides on the next step
- Action: Call a tool to perform an operation
- Repeat this process until you arrive at the final answer.
(2) Explanation of Each Step in ReAct
| Step | Description | Example |
|---|---|---|
| Observation | Receive Input/Tool Results | "User asks: What is Apple's latest stock price?" |
| Thought | LLM reasoning: What should I do now? | "I need to use a search tool to look up stock prices" |
| Action | Execute Tool Call | search_stock("AAPL") |
| Observation | Tool Results | "AAPL = $195.27" |
| Thought | Continue reasoning | "Now that we have the stock price, we can calculate the P/E ratio" |
| Action | Call the next tool | calculate_pe(195.27, 6.26) |
| ... | Repeat until a final answer is reached | ... |
| Final Answer | Output final response | "AAPL is currently at $195.27, with a P/E ratio of 31.2..." |
(3) ReAct Flowchart
graph TB
A[User Input] --> B[Observation]
B --> C[Thought]
C --> D{Need Action?}
D -- Yes --> E[Action / Tool Call]
E --> F[Tool Result]
F --> B
D -- No --> G[Final Answer]
G --> H[User]
5. Function Calling
(1) What Is Function Calling?
Function Calling is a capability offered by models such as OpenAI: you tell the model "what tools are available," and when responding, the model can choose to call a specific tool rather than providing a text-based answer directly.
Key Difference: The model does not execute the code directly; instead, it outputs a structured tool invocation request (function name + arguments), which your code is responsible for executing.
(2) Comparison of Tool Types
| Tool Type | Purpose | Typical API | Example |
|---|---|---|---|
| Search | Get Real-Time Information | SerpAPI / Tavily | get_stock_price("AAPL") |
| Calculator | Math Operations | Python eval / Wolfram | calculate("31.2 / 6.26") |
| Code Execution | Run Program | Python REPL / Docker | run_code("print(2**10)") |
| API Call | Integration with External Services | HTTP / SDK | send_email(to, subject) |
▶ Example: Defining a utility function (Difficulty: ⭐)
import json
def get_weather(city: str) -> str:
"""Get current weather for a city."""
weather_data = {
"Beijing": '{"temp": 22, "condition": "Sunny"}',
"Tokyo": '{"temp": 18, "condition": "Cloudy"}',
"New York": '{"temp": 15, "condition": "Rainy"}',
}
return weather_data.get(city, '{"temp": null, "condition": "Unknown"}')
tool_definition = {
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a given city",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name, e.g. Beijing, Tokyo"
}
},
"required": ["city"]
}
}
}
print(get_weather("Beijing"))
{"temp": 22, "condition": "Sunny"}
▶ Example: Calling an OpenAI Function (Difficulty: ⭐⭐)
from openai import OpenAI
client = OpenAI()
tools = [tool_definition]
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "What is the weather in Beijing?"}
],
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
if message.tool_calls:
tool_call = message.tool_calls[0]
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
print(f"Model wants to call: {func_name}")
print(f"Arguments: {func_args}")
result = get_weather(**func_args)
print(f"Tool result: {result}")
Model wants to call: get_weather
Arguments: {'city': 'Beijing'}
Tool result: {"temp": 22, "condition": "Sunny"}
6. Agent Planning and Memory
(1) Planning
Complex tasks must be completed step by step. An agent’s planning capabilities are reflected in:
- Task Breakdown: Break down "Analyze whether it is worth investing in" into "Check the stock price → Calculate the P/E ratio → Compare with the industry average → Provide a recommendation"
- Sequencing Steps: Determine what to do first and what to do next
- Dynamic Adjustment: If a search tool fails, try a different tool or strategy
(2) Memory
| Type | Description | Implementation |
|---|---|---|
| Short-term memory | Current conversation context | Conversation history list |
| Long-Term Memory | Cross-Session Knowledge | Vector Databases / File Storage |
| Working Memory | Intermediate Results of the Current Task | Scratchpad / Variables |
Short-term memory is simply the conversation history—passing all previous messages along with each LLM call. Long-term memory requires an additional storage mechanism.
7. Implementing a Simple Agent in Python
▶ Example: Agent Loop (Implemented with a while loop) (Difficulty: ⭐⭐)
import json
from openai import OpenAI
client = OpenAI()
def get_weather(city: str) -> str:
"""Get current weather for a city."""
data = {
"Beijing": '{"temp": 22, "condition": "Sunny"}',
"Tokyo": '{"temp": 18, "condition": "Cloudy"}',
}
return data.get(city, '{"temp": null, "condition": "Unknown"}')
available_tools = {
"get_weather": get_weather,
}
tool_schemas = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a given city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"}
},
"required": ["city"]
}
}
}]
def run_agent(user_query: str, max_steps: int = 5) -> str:
messages = [{"role": "user", "content": user_query}]
for step in range(max_steps):
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
tools=tool_schemas,
tool_choice="auto"
)
msg = response.choices[0].message
messages.append(msg)
if not msg.tool_calls:
return msg.content
for tool_call in msg.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
print(f"[Step {step+1}] Calling {func_name}({func_args})")
result = available_tools[func_name](**func_args)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result
})
return "Agent reached max steps without final answer."
answer = run_agent("What is the weather in Beijing and Tokyo?")
print(answer)
[Step 1] Calling get_weather({'city': 'Beijing'})
[Step 2] Calling get_weather({'city': 'Tokyo'})
The weather in Beijing is 22°C and Sunny, while Tokyo is 18°C and Cloudy.
▶ Example: Multi-Tool Agent (Search + Calculator) (Difficulty: ⭐⭐⭐)
import json
from openai import OpenAI
client = OpenAI()
def search_web(query: str) -> str:
"""Simulate web search."""
mock_results = {
"Tesla 2024 revenue": "Tesla 2024 total revenue: $97.69 billion",
"Tesla 2023 revenue": "Tesla 2023 total revenue: $96.77 billion",
"AAPL stock price": "AAPL current price: $195.27, PE ratio: 31.2",
}
for key, val in mock_results.items():
if key.lower() in query.lower():
return val
return "No results found for: " + query
def calculate(expression: str) -> str:
"""Evaluate a math expression safely."""
allowed = set("0123456789+-*/.() ")
if all(c in allowed for c in expression):
try:
result = eval(expression)
return str(result)
except Exception as e:
return f"Calculation error: {e}"
return "Invalid expression"
available_tools = {
"search_web": search_web,
"calculate": calculate,
}
tool_schemas = [
{
"type": "function",
"function": {
"name": "search_web",
"description": "Search the web for information",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"}
},
"required": ["query"]
}
}
},
{
"type": "function",
"function": {
"name": "calculate",
"description": "Evaluate a mathematical expression",
"parameters": {
"type": "object",
"properties": {
"expression": {"type": "string", "description": "Math expression to evaluate"}
},
"required": ["expression"]
}
}
}
]
def run_multi_tool_agent(user_query: str, max_steps: int = 10) -> str:
messages = [{"role": "user", "content": user_query}]
for step in range(max_steps):
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
tools=tool_schemas,
tool_choice="auto"
)
msg = response.choices[0].message
messages.append(msg)
if not msg.tool_calls:
return msg.content
for tool_call in msg.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
print(f"[Step {step+1}] {func_name}({func_args})")
result = available_tools[func_name](**func_args)
print(f" -> {result}")
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result
})
return "Agent reached max steps."
answer = run_multi_tool_agent("What was Tesla's 2024 revenue and how much did it grow YoY?")
print(f"\nFinal Answer:\n{answer}")
[Step 1] search_web({'query': 'Tesla 2024 revenue'})
-> Tesla 2024 total revenue: $97.69 billion
[Step 2] search_web({'query': 'Tesla 2023 revenue'})
-> Tesla 2023 total revenue: $96.77 billion
[Step 3] calculate({'expression': '(97.69 - 96.77) / 96.77 * 100'})
-> 0.9508080206700424
Final Answer:
Tesla's 2024 revenue was $97.69 billion, compared to $96.77 billion in 2023.
This represents a year-over-year growth of approximately 0.95%.
▶ Example: Agent with Memory (Difficulty: ⭐⭐⭐)
import json
from openai import OpenAI
client = OpenAI()
class MemoryAgent:
def __init__(self, system_prompt: str = "You are a helpful assistant."):
self.system_prompt = system_prompt
self.short_term_memory: list = []
self.long_term_memory: list = []
def add_to_long_term(self, fact: str):
self.long_term_memory.append(fact)
print(f"[Memory Saved] {fact}")
def get_context(self) -> list:
context = [{"role": "system", "content": self.system_prompt}]
if self.long_term_memory:
mem_str = "\n".join(f"- {m}" for m in self.long_term_memory)
context.append({
"role": "system",
"content": f"Long-term memory:\n{mem_str}"
})
context.extend(self.short_term_memory)
return context
def chat(self, user_input: str) -> str:
self.short_term_memory.append({"role": "user", "content": user_input})
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=self.get_context()
)
reply = response.choices[0].message.content
self.short_term_memory.append({"role": "assistant", "content": reply})
return reply
def remember(self, fact: str):
self.add_to_long_term(fact)
agent = MemoryAgent(system_prompt="You are a research assistant.")
r1 = agent.chat("My name is Bob and I work at Apple Inc.")
print(f"Agent: {r1}")
agent.remember("User name: Bob, works at Apple Inc.")
r2 = agent.chat("What is my name and where do I work?")
print(f"Agent: {r2}")
Agent: Nice to meet you, Bob! How can I help you today?
[Memory Saved] User name: Bob, works at Apple Inc.
Agent: Your name is Bob, and you work at Apple Inc.
8. Agent Frameworks
(1) Comparison of Agent Frameworks
| Framework | Features | Suitable Scenarios | Language |
|---|---|---|---|
| LangChain / LangGraph | Rich ecosystem, large community, flexible but complex | General-purpose agent development | Python / JS |
| OpenAI Assistants API | Officially hosted, easy to use, black box | Rapid prototyping, OpenAI ecosystem | REST / Python |
| AutoGen (Microsoft) | Multi-agent collaboration, conversational | Multi-agent discussion and collaboration | Python |
| CrewAI | Role-playing, Team Collaboration | Simulating Team Workflows | Python |
(2) How to Choose
- Introductory Exercise: Write your own code using a
whileloop (following the method from this lesson) to understand the underlying principles. - Rapid Prototyping: OpenAI Assistants API—done in just a few lines of code
- Production Project: LangGraph, offers good controllability
- Multi-Agent: AutoGen or CrewAI
9. Comprehensive Example: Research Assistant Agent
▶ Example: Building a "Research Assistant Agent" (Difficulty: ⭐⭐⭐)
import json
from openai import OpenAI
client = OpenAI()
# --- Tool Definitions ---
def search_web(query: str) -> str:
"""Simulate web search for real-time information."""
mock_db = {
"Tesla 2024 revenue": "Tesla 2024 total revenue: $97.69 billion, net income: $7.09 billion",
"Tesla 2023 revenue": "Tesla 2023 total revenue: $96.77 billion, net income: $14.99 billion",
"Tesla stock price": "TSLA current price: $352.00, market cap: $1.13 trillion",
}
for key, val in mock_db.items():
if key.lower() in query.lower():
return val
return f"No specific results for: {query}"
def calculate(expression: str) -> str:
"""Evaluate a mathematical expression."""
allowed = set("0123456789+-*/.() ")
if all(c in allowed for c in expression):
try:
return str(eval(expression))
except Exception as e:
return f"Error: {e}"
return "Invalid expression"
def run_code(code: str) -> str:
"""Execute Python code and return output."""
import io
import contextlib
output = io.StringIO()
try:
with contextlib.redirect_stdout(output):
exec(code, {"__builtins__": {}})
return output.getvalue() or "Code executed with no output."
except Exception as e:
return f"Execution error: {e}"
# --- Agent Setup ---
available_tools = {
"search_web": search_web,
"calculate": calculate,
"run_code": run_code,
}
tool_schemas = [
{
"type": "function",
"function": {
"name": "search_web",
"description": "Search the web for real-time information like stock prices, revenue, news",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"}
},
"required": ["query"]
}
}
},
{
"type": "function",
"function": {
"name": "calculate",
"description": "Evaluate a mathematical expression, e.g. (100-90)/90*100",
"parameters": {
"type": "object",
"properties": {
"expression": {"type": "string", "description": "Math expression"}
},
"required": ["expression"]
}
}
},
{
"type": "function",
"function": {
"name": "run_code",
"description": "Execute Python code for complex analysis, charting, or data processing",
"parameters": {
"type": "object",
"properties": {
"code": {"type": "string", "description": "Python code to execute"}
},
"required": ["code"]
}
}
}
]
SYSTEM_PROMPT = """You are a research assistant agent. When answering questions:
1. Use search_web to find real-time data
2. Use calculate for math operations
3. Use run_code for complex analysis
Always show your reasoning step by step."""
def research_agent(user_query: str, max_steps: int = 10) -> str:
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_query}
]
for step in range(max_steps):
print(f"\n--- Step {step + 1} ---")
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
tools=tool_schemas,
tool_choice="auto"
)
msg = response.choices[0].message
messages.append(msg)
if msg.content:
print(f"Thought: {msg.content[:200]}")
if not msg.tool_calls:
return msg.content
for tool_call in msg.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
print(f"Action: {func_name}({json.dumps(func_args)})")
result = available_tools[func_name](**func_args)
print(f"Observation: {result[:200]}")
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result
})
return "Agent reached maximum steps."
# --- Run the Agent ---
answer = research_agent(
"What was Tesla's 2024 revenue? How much did it grow year-over-year? "
"Calculate the growth rate as a percentage."
)
print(f"\n{'='*50}\nFinal Answer:\n{answer}")
--- Step 1 ---
Thought: I need to find Tesla's 2024 and 2023 revenue first.
Action: search_web({"query": "Tesla 2024 revenue"})
Observation: Tesla 2024 total revenue: $97.69 billion, net income: $7.09 billion
--- Step 2 ---
Action: search_web({"query": "Tesla 2023 revenue"})
Observation: Tesla 2023 total revenue: $96.77 billion, net income: $14.99 billion
--- Step 3 ---
Action: calculate({"expression": "(97.69 - 96.77) / 96.77 * 100"})
Observation: 0.9508080206700424
==================================================
Final Answer:
Tesla's 2024 total revenue was $97.69 billion, compared to $96.77 billion in 2023.
The year-over-year growth rate is approximately 0.95%.
❓ FAQ
📖 Summary
- AI Agent: LLM + Tools + Memory + Planning = An AI Capable of Autonomous Action
- ReAct: The Observe→Think→Act Cycle: The Core Decision-Making Model of an Agent
- Function Calling: The model generates a request to call a tool, and the code is responsible for executing it
- Planning: The agent breaks down complex tasks into actionable steps
- Memory: Short-term (conversation history) + Long-term (vector database) = Agent's knowledge base
- Agent Frameworks: LangChain, OpenAI Assistants, AutoGen, and others, which simplify agent development
📝 Exercises
-
Basics (⭐): Define two custom tools (such as
get_populationandget_gdp), write the tool definitions in the JSON Schema format for Function Calling, and register them in theavailable_toolsdictionary. -
Advanced (⭐⭐): Implement a single-tool agent loop: Define a tool named
get_exchange_rate. When the user enters "How much CNY is 100 USD worth?", the agent automatically calls the tool and returns the result. -
Challenge (⭐⭐⭐): Have the Agent answer a question that requires both searching and calculation: for example, "What is the population of Tokyo? If each person needs 2 kg of water per day, how many metric tons of water does Tokyo need each day?" The Agent must decide on its own to first search for population data and then use a calculation tool to arrive at the answer.



