AI 智能体(Agent)开发听起来像一个高级方向。实际上,用现成的 API 和框架,一个熟悉 Python 的开发者可以在一个下午写出第一个可运行的 Agent。

这篇文章不讲 Agent 的四层架构和概念模型。我直接从”我要写一个能调用工具完成任务的程序”出发,带你写出真正能跑起来的第一版 Agent。

确定你的第一个 Agent 要做什么

写代码之前先想清楚第一个实验的目标。不要一开始就想做一个”全能的个人助手”。

一个好的第一个 Agent 应该是这样的:

  • 任务单一:比如”查天气然后发邮件通知我”。
  • 参与的 API 不超过两个:一个 LLM API(比如 Claude API 或 OpenAI API),一个工具 API。
  • 可以失败:第一个版本不追求 100% 可靠。

我建议你用这个场景作为起步:让 Agent 能够根据用户的自然语言指令,决定是否调用一个外部工具(比如搜索或计算器),然后把结果整理成回答。

初始化项目

创建一个新的项目目录,装好你需要的依赖:

1
2
3
4
5
mkdir my-first-agent
cd my-first-agent
python -m venv venv
source venv/bin/activate # Windows 用 venv\Scripts\activate
pip install anthropic httpx

只需要两个包:anthropic 用来调用 Claude API,httpx 用来给 Agent 发 HTTP 请求访问外部工具。

如果你的 API 用的是 OpenAI、DeepSeek 或国产模型,对应的 SDK 也是类似的用法。

第一步:定义工具

Agent 的核心能力是”能调用工具”。先写一个简单的工具函数,让 Agent 可以用它。

这里用一个天气查询工具做示范。实际项目中你可能会换成搜索、数据库查询或文件操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import httpx

def get_weather(city: str) -> str:
"""查询指定城市的当前天气"""
try:
resp = httpx.get(
f"https://api.openweathermap.org/data/2.5/weather",
params={"q": city, "appid": "你的API_KEY", "units": "metric"}
)
data = resp.json()
temp = data["main"]["temp"]
desc = data["weather"][0]["description"]
return f"{city}当前天气:{desc},温度{temp}°C"
except Exception as e:
return f"查询失败:{str(e)}"

关键点不是这个函数本身,而是它有一个清晰的输入(城市名)和一个可预测的输出(带温度的天气描述)。Agent 框架需要这种结构才能正确调用工具。

第二步:把工具描述注册给 LLM

要让 LLM 知道什么时候该用这个工具,你需要把工具描述用 API 要求的格式传给模型。

以 Claude API 为例,工具注册格式是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import anthropic

client = anthropic.Anthropic(api_key="你的API_KEY")

tools = [
{
"name": "get_weather",
"description": "查询指定城市的当前天气",
"input_schema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,如北京、上海"
}
},
"required": ["city"]
}
}
]

这个描述告诉 LLM:有一个工具叫 get_weather,它需要一个 city 参数,作用是查天气。LLM 收到用户的”北京今天冷吗”之后,就会判断是否应该调用这个工具。

每条工具描述包含三个要素:

  1. name:函数名,必须和你的 Python 函数名一致。
  2. description:告诉 LLM 这个工具适合什么场景。写清楚,LLM 才会准确判断。
  3. input_schema:参数的 JSON Schema 描述。每个参数要有 type 和 description。

如果参数写得太模糊,比如把 city 写成 query,LLM 可能会传一个完整的句子而不是城市名进去。

第三步:实现 Agent 调用循环

最核心的部分来了。Agent 的工作方式是一个循环:收到用户消息 → LLM 决定回复或调工具 → 如果是调工具就执行工具并把结果送回 LLM → LLM 给出最终回答。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import json

def run_agent(user_input: str) -> str:
messages = [
{"role": "user", "content": user_input}
]

response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
system="你是一个有帮助的助手。如果需要查询天气才能回答用户的问题,请使用 get_weather 工具。",
messages=messages,
tools=tools
)

# 检查 LLM 是否想要调用工具
for block in response.content:
if block.type == "tool_use":
tool_name = block.name
tool_args = block.input

if tool_name == "get_weather":
result = get_weather(tool_args["city"])

messages.append({
"role": "assistant",
"content": response.content
})
messages.append({
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": block.id,
"content": result
}
]
})

# 把工具结果送回 LLM,让它生成最终回答
final = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
system="你是一个有帮助的助手。",
messages=messages
)
return final.content[0].text

# 如果没有工具调用,直接返回 LLM 的回复
return response.content[0].text

这个循环是 Agent 最基础的模式。你的第一个 Agent 做到这一步就足够了。

实际项目中,这个循环会更复杂:可能要连续调用多个工具,可能要处理工具出错的情况,可能要在工具结果中判断是否继续调用新工具。但第一步先把单工具循环跑通。

第四步:测试你的 Agent

写一个简单入口来测试:

1
2
3
4
5
6
7
if __name__ == "__main__":
while True:
user_input = input("你:")
if user_input.lower() in ["exit", "quit"]:
break
result = run_agent(user_input)
print(f"Agent:{result}")

测试几个不同的输入:

1
2
3
4
5
6
7
你:北京今天冷吗
Agent:我查一下北京的天气。
(调用 get_weather("北京"))
北京当前天气:多云,温度22°C,不算冷,适合出门。

你:你好
Agent:你好!有什么我可以帮你的?

第二个查询不需要调用工具,LLM 直接回答。这说明 LLM 正确判断了什么时候该用工具、什么时候不该用。

常见的失败模式

第一次跑通这个循环后,你大概率会遇到一些问题:

LLM 调用了不存在的工具。 检查 tools 列表里的 name 是否和 Python 函数名完全一致,input_schema 的参数名是否匹配。

工具参数格式不对。 比如 LLM 传了 city: "北京市" 但你的 API 只接受 "Beijing"。可以加参数预处理,或者在 description 里写清楚格式要求。

工具执行出错。 Agent 需要能处理工具返回的错误。如果 API 超时或返回 500,LLM 应该知道向用户说明而不是假装成功。可以在工具函数里返回错误描述而不是抛异常。

循环不终止。 LLM 反复调同一个工具。可以设置最大工具调用次数,比如最多 3 轮。

从这个起点怎么继续

第一个 Agent 跑通之后,你可以做两件事来扩展它。

加更多工具。 注册一个搜索工具、一个计算工具或一个文件读写工具。多个工具共存时,LLM 的选择质量取决于 description 写得清不清楚。

换多工具调用框架。 如果你发现自己写了大量的工具调度逻辑和对话管理代码,说明是时候考虑 LangChain 的 Tool 抽象或 Anthropic 的 Tool Use 高阶模式了。框架帮你处理多轮调用和状态管理,但你仍然需要理解上面这个基础循环才能用好它们。

关于框架选型,可以参考 LangChain 和 LangGraph 的 Agent 实现路径 了解框架层面的做法。

关键点总结

第一次做 Agent 开发不需要架构设计文档。你需要的是一个 LLM API key、一个简单的工具函数、一个工具注册描述、和一个循环把这三者串起来。

先让一个工具跑通。然后再考虑多工具、记忆、规划和持久化。Agent 开发入门最难的部分不是技术实现,而是把”Agent”从一个听起来很酷的概念拆解成一个可调试的循环逻辑。

如果你还想了解 Agent 开发中用到的 MCP 协议,可以看 MCP 协议介绍 了解工具层的标准化方案。