最近一两年,AI Agent 可以说是 AI 应用开发里热度最高的方向之一。不少同学在 B 站收藏了很多 Agent 教程,但真到自己动手做时,还是会卡在环境搭建、工具调用、记忆管理、Function Calling 这些细节上。本文把一套能落地的 AI Agent 学习路径整理成文字版,从核心概念讲起,再到一个完整的实战项目:让 Agent 通过 Elasticsearch REST API 自动分析日志、统计错误、定位异常服务。
这篇文章适合下面几类读者:
- 刚开始接触 AI Agent,想搞清楚它和普通聊天机器人有什么区别的同学;
- 已经会调用大模型 API,但不知道怎么让模型使用工具、执行任务的开发者;
- 后端工程师或运维同学,想给日常日志分析、故障排查加一个“智能助手”;
- 正在做 AI Agent 框架选型,想知道 LangChain、LangGraph、手写调用之间怎么取舍的人。
学完本文之后,你会掌握 Agent 的核心原理,读懂 ReAct 和 Function Calling,并且能直接跑起来一个“日志分析 Agent”项目。文章中的代码不依赖复杂的平台,只要你有可用的 OpenAI 兼容接口(很多国产大模型也提供同样的兼容接口),再配一个本地或测试环境的 Elasticsearch,就能复现。
1. AI Agent 是什么,为什么值得系统学
1.1 从“聊天机器人”到“智能体”
先来看一个最简单的问题:传统聊天机器人和 AI Agent 有什么区别?
传统聊天机器人做的事情是“你说一句,我回一句”。模型只负责把输入文本转换成输出文本,它不能主动去查数据库、不能调用外部系统、不能感知外部环境的变化。你的问题一旦需要“实时数据”,它就只能靠训练时的知识来猜,或者告诉你“我无法获取最新信息”。
AI Agent 则往前迈了一大步。你可以把它理解成一个带“手脚”的大模型:
- 大模型是大脑,负责理解任务、拆解步骤、决定下一步做什么;
- 工具是手脚,包括调用 REST API、查询数据库、执行代码、操作浏览器等;
- 记忆是工作区,让 Agent 能记住上下文、历史结果和用户偏好;
- 执行循环是运转机制,Agent 通过“思考-调用-观察结果-再思考”不断逼近最终答案。
换句话说,Agent 的价值不在于“能聊天”,而在于“能完成任务”。同样是“帮我看看今天订单服务的错误日志”,聊天机器人只能给你一段通用建议;Agent 可以去查 Elasticsearch,返回真实的错误数量、错误分布、受影响的服务,然后再给你分析结论。
1.2 AI Agent 的核心组成
从工程实现角度看,一个完整的 AI Agent 通常由五部分组成:
| 组成 | 作用 | 常见实现 |
|---|---|---|
| LLM 大脑 | 理解任务、规划步骤、生成文本 | GPT 系列、DeepSeek、Qwen 等 |
| 工具集 Tools | 让 Agent 能与外部系统交互 | REST API、Python 函数、数据库查询 |
| 执行循环 Loop | 决定何时调用工具、何时给出最终答案 | ReAct、Function Calling、Agent 框架 |
| 记忆 Memory | 保存短期上下文和长期知识 | 消息列表、向量数据库、Redis、KV 存储 |
| 反馈与评估 | 判断结果是否正确、是否需要重试 | 人工反馈、规则校验、评测集 |
初学者最容易忽略的是“工具集”和“执行循环”。很多人以为把大模型 API 接上就是 Agent,其实那只是一个聊天机器人。真正的 Agent 难点在于:
- 如何让模型正确选择工具;
- 如何把工具返回的复杂结果重新组织成用户能理解的答案;
- 如何在多步调用中保持上下文不混乱;
- 如何防止模型在一个错误结果上反复循环。
这些正是本文后面要逐步解决的核心问题。
1.3 典型应用场景
AI Agent 不是只能做 Demo,它在很多真实业务场景中已经落地:
- 智能客服:Agent 自动查订单、查物流、处理售后,而不是只回复“请您稍等”;
- 日志与运维分析:Agent 根据自然语言自动查询监控系统、ES 日志、告警平台,辅助定位故障;
- 数据分析:Agent 连接数据仓库,把“本月各渠道销售额是多少”变成 SQL 并执行,然后返回图表和结论;
- 办公自动化:Agent 自动整理邮件、生成周报、填写表单;
- 代码助手:Agent 读取仓库代码、搜索 API 文档、执行测试命令,辅助开发者完成编码任务。
在这些场景中,Agent 的共同特征都是:把“大模型的推理能力”和“系统的操作能力”连接在一起。这也是我们接下来要重点练习的能力。
2. 环境准备与框架选型
2.1 本地环境要求
在开始写代码之前,先准备一套可复现的开发环境。
本文示例基于 Python,版本建议使用 3.10 或更高版本。原因有两个:
- 新版 OpenAI SDK 和一些 Agent 框架对 Python 3.9 以下版本的支持越来越弱;
- 项目里用到类型标注和 f-string 等语法,在 3.10 以上体验更稳定。
如果你不确定本机 Python 版本,可以先执行命令检查:
python --version操作系统方面,Windows、macOS、Linux 都可以跑通。命令行的差异主要在环境变量设置上,Windows 下可以用set,macOS/Linux 下可以用export,后面文章会分别说明。
另外,如果你想跑通本文的完整案例,需要准备:
- 一个 OpenAI 兼容的模型接口,包括
base_url、api_key、model三个信息; - 一个可访问的 Elasticsearch 实例,端口默认是
9200; - 如果没有 Elasticsearch,也没关系,代码里内置了 Mock 模式,可以直接用模拟日志演示 Agent 的运行流程。
这里的重点是思路,而不是具体平台。你可以使用任何提供 OpenAI 兼容接口的模型服务,只需要修改环境变量即可。
2.2 安装依赖
新建一个项目目录,并创建虚拟环境:
mkdir agent-demo cd agent-demo python -m venv venvmacOS / Linux 激活虚拟环境:
source venv/bin/activateWindows PowerShell 激活虚拟环境:
venv\Scripts\Activate.ps1然后在项目根目录创建requirements.txt:
openai>=1.0.0 requests>=2.31.0安装依赖:
pip install -r requirements.txt这里没有锁定具体版本号,因为 OpenAI SDK 迭代比较快。需要说明的是,不同 SDK 版本在调用参数上可能有细微差异,本文代码以 OpenAI SDK 1.x 的通用写法为准。如果你安装到了更新的版本,遇到参数报错时,优先查看官方文档中的迁移说明。
2.3 主流框架怎么选
很多同学一开始会在框架选型上纠结很久。这里先做一个横向对比。
| 方案 | 特点 | 适合场景 |
|---|---|---|
| 手写 OpenAI SDK + Function Calling | 代码直观,原理清晰,无框架依赖 | 学习原理、轻量 Agent、定制化强 |
| LangChain | 生态丰富,组件多,文档全 | 快速做原型、需要大量现成组件 |
| LangGraph | 图结构编排 Agent 流程,支持状态管理 | 生产级复杂流程、多人协作开发 |
| AutoGen | 多智能体对话模式 | 研究实验、多角色模拟 |
| Dify | 低代码/可视化平台 | 非技术人员搭建 AI 应用 |
我的建议是:第一遍学习不要选太重的框架,直接手写一遍 OpenAI 兼容接口的 Function Calling。原因很简单:
- 手写能让你理解 Agent 的底层循环,而不是被框架的抽象封装住;
- 很多框架出问题时,最终还是得回到“消息格式对不对”“工具返回结构对不对”这些底层问题;
- 手写的代码量其实不多,核心循环大概几十行就能跑通。
等你理解了原理,再去用 LangGraph 这类框架做流程编排,会事半功倍。本文的实战部分就采用“手写 OpenAI 兼容接口 + Function Calling”的方式。
2.4 项目目录规划
为了让代码结构清晰,我们先规划好项目目录。本文最终的项目结构如下:
agent-demo/ ├── venv/ # 虚拟环境 ├── requirements.txt # 依赖 ├── init_es_data.py # 初始化 ES 测试数据 ├── tools.py # 工具层,封装 ES REST API ├── agent.py # Agent 核心循环 └── main.py # 命令行入口各文件职责:
tools.py负责所有外部操作,相当于 Agent 的“手脚”;agent.py负责大模型调用、工具选择、结果回传,相当于 Agent 的“大脑”;main.py负责接收用户输入,启动 Agent。
这种拆分的好处是:以后你想给 Agent 加新能力,只需要在tools.py里新增一个函数,然后在agent.py的工具描述里注册即可,不需要改动主流程。
3. 核心原理:ReAct 与 Function Calling
3.1 ReAct:思考-行动-观察循环
ReAct 是 Agent 最核心的推理范式之一,全称是 Reasoning and Acting,意思是“推理与行动交替进行”。
它的执行过程可以拆成下面几步:
- 用户提出任务;
- 模型思考当前任务需要哪些信息,并决定调用哪个工具;
- 程序执行模型指定的工具,返回结果;
- 模型观察工具结果,判断任务是否完成;
- 如果没完成,继续重复第 2 步到第 4 步;
- 如果完成了,模型生成最终答案返回给用户。
用一个用户的真实问题来举例:
用户提问:最近1小时有多少ERROR日志?主要来自哪些服务?模型可能的推理过程如下:
第1步: 思考:我需要先查询ES,统计最近1小时的ERROR日志数量。 行动:调用 count_error_logs(time_range="1h") 观察:返回 45 第2步: 思考:数量已经拿到,现在需要知道主要来自哪些服务。 行动:调用 get_error_top_services(time_range="1h") 观察:返回 [order-service:20, pay-service:15, gateway:10] 第3步: 思考:数据已经足够,可以生成最终结论。 回答:最近1小时共有45条ERROR日志,主要集中在order-service和pay-service……这个“思考-行动-观察”的循环,就是 ReAct 的核心。它让模型不再是一次性输出答案,而是像一个真正的工作人员那样,一步步收集信息、做出判断。
在实际代码中,你不需要真的让模型输出“思考”和“观察”这些文本。OpenAI 兼容接口的tool_calls机制已经帮我们完成了大部分工作:模型直接返回“我要调用哪个工具、参数是什么”,程序执行后再把结果作为tool消息送回模型。
3.2 Function Calling:模型怎么“使用”工具
Function Calling 是当前实现 AI Agent 最主流的技术方案。它的思路并不是让模型真的去执行代码,而是让模型“声明”它想调用哪个函数,以及函数的参数是什么。
举个例子。假设我们定义了一个函数get_weather(city),那么在调用模型时,需要把这个函数的描述以 JSON Schema 的形式传给模型:
{ "type": "function", "function": { "name": "get_weather", "description": "查询指定城市的天气", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称,例如北京" } }, "required": ["city"] } } }当用户问“北京今天下雨吗”时,模型可能会返回一个特殊的tool_calls结果:
{ "name": "get_weather", "arguments": "{\"city\": \"北京\"}" }注意,模型并没有真正查询天气。它只是说:“我建议调用get_weather函数,参数是北京。”真正执行函数的是我们自己的代码:
result = get_weather("北京")然后把执行结果作为tool消息再次发给模型,模型看到结果后,才能组织最终回答。
这就是 Function Calling 的核心思想:模型负责“决策”,代码负责“执行”。这样做有几个好处:
- 模型不需要真的写可执行代码,降低了安全风险;
- 工具的执行结果可控,我们可以增加权限校验、日志记录、超时重试;
- 模型可以把复杂的工具参数结构化输出,避免自由文本解析的误差。
3.3 记忆与上下文管理
Agent 的记忆可以分为短期记忆和长期记忆。
短期记忆就是指当前会话的消息列表。在 Function Calling 场景中,消息列表不仅包含用户和模型的对话,还包含工具调用的过程记录。一个典型的消息序列如下:
system: 你是日志分析助手 user: 最近1小时有多少ERROR日志? assistant: 我想需要调用统计工具 [...tool_calls...] tool: 工具执行结果,返回 45 assistant: 最近1小时共有45条ERROR日志。短期记忆是 Agent 实现多轮任务的基础。如果每次请求都重新拼一个空消息列表,模型就无法感知“刚才已经查过日志数量”这个事实。
长期记忆则用于跨会话保存信息,比如用户的偏好、历史故障记录、企业知识库等。实现方案很多:
- 向量数据库(如 Milvus、Qdrant、pgvector)存语义向量,适合做知识库检索;
- Redis 或 MySQL 存结构化信息,适合保存用户状态和任务记录;
- 文件系统存日志和中间结果,适合离线分析和审计。
在今天的日志分析 Agent 中,我们用消息列表实现短期记忆就足够。但如果将来要让 Agent 记住“哪台服务器经常出问题”,就需要引入长期记忆模块。
3.4 多智能体与工作流编排
当任务变得复杂时,单个 Agent 可能难以胜任。比如一个完整的故障排查流程包括:收集日志、分析异常、查询变更记录、通知负责人。如果全让一个 Agent 做,工具列表会非常长,上下文也容易混乱。
这时可以把任务拆成多个专用 Agent:
- 日志分析 Agent:负责查询