Hello, everyone! Welcome to Yuan Ge’s “Five Steps of AI Agents”.
In the previous two articles, we unified the “worldview” of the [Thoughts] section and created a small Agent using the Vercel AI SDK in the [Practical Application] section.
If you’ve been following along, I believe you’re no longer satisfied with that little “toy” that can only check the weather. Today, we will step it up and discuss some professional-grade tools—OpenAI and Anthropic’s Agent SDKs—and see how they evolve from “toys” to real “productivity” tools on the actual “battlefield”.
1. From “Guerrilla” to “Regular Army”: OpenAI Assistants API
If the Vercel AI SDK we used in the last article was like a “guerrilla”—flexible and lightweight, striking and retreating (stateless)—then OpenAI’s Assistants API is like a “regular army”—heavily equipped and organized.
The biggest difference lies in “state management“.
Do you remember how we manually called `streamText` twice in the last article to make the Agent remember the query results? In real complex business scenarios, a task may involve dozens or hundreds of dialogues and tool calls. If we continue using this “manual mode”, the code will be nearly impossible to maintain.
OpenAI’s Assistant helps you solve this problem. You only need to:
-
Create an Assistant: You can think of it as an “AI employee”. Set its identity (`instructions`), skills (`tools`), and knowledge base (`files`). This creation is a one-time setup.
-
Create a Thread: When a user starts a conversation with your Agent, you create a “conversation thread” (Thread) for them. This is like assigning a “task order” to this AI employee.
-
Send Message and Run: You place the user’s message (Message) into this thread and then initiate a run (Run).
Next, something magical happens: all subsequent dialogues, tool calls, and state management are automatically handled by OpenAI in the cloud!
Code Practice: Building a “Memory-Enabled” Agent with Assistants API
The concepts are explained, but not showing code would be a disservice. Below, Yuan Ge will provide a more complete Python example to show you how the “regular army” operates. We will also use the “check weather” scenario to directly compare with the previous Vercel AI SDK example.
# aio_assistant_example.py
import openai
import time
import json
# 0. Set your API Key
# It is strongly recommended to use environment variables instead of hardcoding
# client = openai.OpenAI(api_key="sk-...")
client = openai.OpenAI()
# 1. Define our local tool function
def search_weather(location: str):
"""Query weather information based on city name (simulated)."""
print(f"Calling local tool search_weather, querying city: {location}")
if "北京" in location:
return json.dumps({"temperature": "-2°C", "condition": "Sunny"})
elif "上海" in location:
return json.dumps({"temperature": "8°C", "condition": "Light Rain"})
else:
return json.dumps({"temperature": "Unknown", "condition": "Unknown"})
# Tool name -> function mapping
available_tools = {
"search_weather": search_weather,
}
# 2. Create an Assistant (AI employee)
# Only need to create once, can be reused later
print("Creating Assistant...")
assistant = client.beta.assistants.create(
name="Weather Query Assistant",
instructions="You are a weather query assistant. Use the tools in your toolbox to answer weather questions based on user inquiries.",
model="gpt-4-turbo-preview",
tools=[{
"type": "function",
"function": {
"name": "search_weather",
"description": "Get weather information for a city based on its name.",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name, e.g., Beijing"},
},
"required": ["location"],
},
}
}])
print(f"Assistant created successfully, ID: {assistant.id}")
# 3. Create a Thread (task order) for the user
print("Creating Thread...")
thread = client.beta.threads.create()
print(f"Thread created successfully, ID: {thread.id}")
# 4. Add the user's initial message to the Thread
user_message = "Hello, I want to know what the weather is like in Beijing today?"
print(f"User message: {user_message}")
client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content=user_message,
)
# 5. Create and run Run (let the AI employee start working)
print("Creating and running Run...")
run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant.id,
)
print(f"Run created successfully, ID: {run.id}")
# 6. Key: Loop to check the status of Run
while run.status in ["queued", "in_progress"]:
time.sleep(1) # Wait 1 second
run = client.beta.threads.runs.retrieve(thread_id=thread.id, run_id=run.id)
print(f"Run status: {run.status}")
if run.status == "requires_action":
print("Run requires tool calls...")
tool_outputs = []
for tool_call in run.required_action.submit_tool_outputs.tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
# Find the corresponding function from the available tools list and execute it
function_to_call = available_tools[function_name]
output = function_to_call(**function_args)
tool_outputs.append({
"tool_call_id": tool_call.id,
"output": output,
})
print(f"Tool {function_name} returned result: {output}")
# Submit the results of the tool calls
print("Submitting tool results...")
run = client.beta.threads.runs.submit_tool_outputs(
thread_id=thread.id,
run_id=run.id,
tool_outputs=tool_outputs,
)
# 7. Check if Run is ultimately successful
if run.status == "completed":
print("Run completed.")
messages = client.beta.threads.messages.list(thread_id=thread.id)
# Iterate through messages and print the final AI response
for message in messages.data:
if message.role == "assistant":
print(f"AI Assistant response: {message.content[0].text.value}")
break # Usually, the latest message is what we want
else:
print(f"Final status of Run: {run.status}")
Yuan Ge’s Interpretation:
As you can see, this code is longer than the previous Vercel AI SDK example, but the logical structure is very clear. This is the discipline of the “regular army”.
1. Thorough State Separation: We only need to create `Assistant` and `Thread`, and all dialogue history and intermediate states are maintained by OpenAI in the cloud. Your code no longer needs to pass data back and forth; you only need a `thread.id` to trace all context, which is crucial for developing long processes and multi-turn dialogue Agents.
2. “requires_action” is the Core Hub: The most critical part of the entire code is that `while` loop. We continuously “poll” the status of Run, and when the status changes to `requires_action`, it means the AI has “thought it through” and decided to use a tool, informing you which tool to call (`function_name`) and what parameters are needed (`function_args`).
3. Sovereignty is Mine: The AI only “suggests” using tools, but the actual execution power of the tools remains in your code. We call the local `search_weather` function, obtain the result, and then “feed” the result back to the AI through `submit_tool_outputs`.
4. Autonomous Follow-Up Thinking: After the AI receives the results returned by the tool, it will continue its thinking. It may decide that this result is sufficient to answer the user, thus changing the status of `Run` to `completed`; or it may feel that another tool needs to be called, in which case the status of `Run` will change back to `requires_action`. The entire process is driven autonomously by the AI.
In this way, the Agent we build can utilize the AI’s “brain” for thinking and planning while safely and controllably executing various local tools, and it also possesses long-term “memory” capabilities. This is what a “productivity” level Agent should look like.
2. Real Combat! The Real Battlefield of Agents
With both theory and tools in place, where can these “production-level” Agents actually be used? Drawing from my own experience, let me share a few practical scenarios.
1. Intelligent Operations (AIOps) — My 24/7 Cloud Engineer
As an experienced operations engineer, being woken up by alarm calls in the middle of the night is a common occurrence. Now, I can create an “operations Agent”.
Skills (Tools): Access to monitoring system APIs (check logs, view server load), cloud service provider APIs (restart servers, adjust configurations), alarm notification APIs (send SMS, make calls).
Workflow:
-
Agent continuously monitors through tools and discovers “User login service CPU 100%”.
-
Planning: ① Check logs for any abnormal errors; ② Check associated databases and caches for slow queries; ③ Assess the severity of the issue.
-
Action: Discover that an abnormal request caused a deadlock. The Agent calls the cloud service API to precisely restart the problematic service instance and uses the alarm API to send me a text message while I’m asleep: “Login service instance A-52 has been automatically restarted due to a deadlock, and the business has recovered. Please pay attention during the day.”
Value: Isn’t this much stronger than just a “screaming” alarm system? It turns “alarms” into “actions” and “firefighting” into “self-healing”.
2. Enterprise Knowledge Base — That “All-Knowing” Old Employee
Every company has a pile of “ancestral” knowledge that only old employees know. When new employees come in, they ask questions here and there, which is very inefficient.
Skills (Tools): Access to the company’s Confluence, GitLab, Jira, and shared documents.
Workflow: A new employee asks: “Where is the review report for the online incident of Module A in our project?”
-
Planning: ① “Module A”, “online incident”, “review report” are keywords; ② Search Confluence and shared documents.
-
Action: The Agent finds the relevant report in Confluence and sends the link and summary to the new employee, even attaching the Jira ID of the person responsible at that time.
Value: It transforms unstructured knowledge into callable “memory”, greatly reducing the onboarding cost for new employees and internal communication costs.
3. IoT Hub — My Hardware “Manager”
The hardware field, which I love the most, has even more imaginative space!
Background: I have a room full of smart home devices using ESP32 and Raspberry Pi, each with its own API.
Agent: I no longer need to write control logic for each device; instead, I create a “Home Manager Agent”.
Workflow: I tell the Agent: “I’m leaving, activate security mode.”
-
Planning: ① “Security mode” means turning off lights, closing windows, and turning on cameras; ② Need to call the lighting control API, window control API, and camera API.
-
Action: The Agent sequentially calls the APIs of each device to complete all operations and replies to me: “Home security mode has been activated.”
Value: The Agent becomes the “unified language” and “intelligent brain” of physical world devices, making complex hardware interactions as simple as talking to a person.
3. Yuan Ge’s Summary and Preview
By today, we have mastered all the knowledge needed to build a powerful “solo combat” Agent, from the lightweight Vercel AI SDK to the “regular army” OpenAI Assistants API. We can now enable Agents to work in the real world.
But a question arises: the tools we write are all in the same project as the Agent’s code. What if I want to call a tool written by someone else, deployed on a remote server? This is like our Agent only speaks “Chinese”, while the remote tool may only understand “English”; they need a “translator” and a “standard way to make calls”.
In the next article, [Protocol Section], we will delve into an important standard—MCP (Model Context Protocol)—and see how it establishes a “common language” for communication between Agents and the external world, allowing our Agents to easily call tools from around the world.
Stay tuned!