如何用 Python 从零手写一个简单的 Agent
如何用 Python 从零手写一个简单的 Agent?——从概念认知到功能落地的完整实践指南
摘要/引言
开门见山:从 Siri、ChatGPT 到你手机上的闹钟,Agent 早已无处不在
你有没有想过:为什么你对着 Siri 说“明天下午3点提醒我带伞”,它不仅能听懂“明天下午3点”这个时间、“带伞”这个任务,还能自动在你的日历/提醒事项里创建条目?为什么 ChatGPT Plus 上的 Code Interpreter 不仅能解释代码,还能打开沙箱执行、绘制图表、甚至修复错误?为什么你手机上的智能闹钟能根据天气预报调整起床时间、播放音乐、还能汇报路况?
这些看似神奇的功能背后,都有一个共同的技术核心——智能体(Agent)。
很多人可能会觉得 Agent 是一个遥不可及的“黑科技”,需要深度学习、大模型、强化学习这些复杂的技术栈才能实现。但实际上,Agent 的本质只是一套遵循特定规则的决策与执行闭环系统——哪怕你只用 Python 的基础语法,也能写出一个功能完整、逻辑清晰的简单 Agent。
问题陈述:为什么我们要“从零手写”一个 Agent?
现在市面上有很多成熟的 Agent 框架,比如 LangChain、AutoGPT、CrewAI 等等。这些框架确实能让我们快速构建出功能强大的 Agent,但同时也带来了两个问题:
- “黑盒化”认知: 我们只会用框架的 API,却不知道框架背后的原理——比如 LLM 在 Agent 里到底扮演什么角色?Agent 的思考、行动、观察循环是怎么实现的?如果框架出了问题,我们根本不知道从哪里排查。
- “过度依赖”框架: 当我们的需求和框架的默认逻辑不一致时,我们往往会花大量时间去“适配框架”,而不是去“修改逻辑”——比如有些场景下我们不需要 LLM,只需要规则驱动;有些场景下我们不需要循环执行,只需要单次决策。
核心价值:从零手写简单 Agent,你能学到什么?
通过本文的学习,你将:
- 彻底理解 Agent 的本质与核心要素: 不再被“大模型驱动的 Agent”这个概念误导——知道 Agent 可以分为规则驱动、数据驱动、模型驱动、混合驱动等多种类型。
- 掌握 Agent 最经典的架构:ReAct 循环(Reasoning + Acting + Observing)——这是目前几乎所有成熟 Agent 框架的核心架构。
- 从零实现两个功能完整的 Agent:
- 规则驱动的“天气提醒小助手”: 不需要任何大模型,只用到 Python 的基础语法、requests 库和 datetime 库——适合新手入门。
- 大模型驱动的“迷你代码助手”: 用到 OpenAI 的 GPT-3.5/4o-mini API、Python 的 subprocess 库和正则表达式——能实现简单的代码解释、执行和修复功能。
- 了解 Agent 框架的核心设计思路: 为后续学习 LangChain、AutoGPT 等框架打下坚实的基础。
- 积累 Agent 开发的最佳实践: 比如如何设计清晰的工具接口?如何处理 Agent 的错误?如何限制 Agent 的权限?
文章概述:本文的主要内容结构
本文将按照以下结构展开:
- 概念认知篇: 先彻底搞懂什么是 Agent,Agent 的核心要素是什么,Agent 有哪些类型,经典的 ReAct 循环是什么。
- 规则驱动 Agent 实战篇: 从零实现一个规则驱动的“天气提醒小助手”——包括需求分析、环境安装、架构设计、接口设计、核心实现、测试优化。
- 大模型驱动 Agent 实战篇: 从零实现一个大模型驱动的“迷你代码助手”——包括需求分析、环境安装、架构升级、工具封装、核心实现、测试优化。
- 框架设计思路篇: 基于前两个实战项目,总结出一个通用的简单 Agent 框架的核心设计思路。
- 行业发展与未来趋势篇: 简单回顾 Agent 的发展历史,探讨 Agent 的未来发展方向。
- 本章小结与最佳实践篇: 总结本文的核心内容,分享 Agent 开发的最佳实践。
正文第一部分:概念认知篇——彻底搞懂 Agent 的本质
核心概念
什么是 Agent?
Agent 的概念最早来源于人工智能领域,但后来被广泛应用于软件工程、机器人学、经济学、社会学等多个领域。不同领域对 Agent 的定义略有不同,但核心思想是一致的:
Agent(智能体/代理)是一个能够感知环境(Perceive)、做出决策(Reason)、并采取行动(Act)以实现特定目标的实体(Entity)。
这个定义看起来有点抽象,我们可以用几个具体的例子来理解:
- 软件领域的 Agent: Siri、ChatGPT Plus、AutoGPT、你手机上的智能闹钟、浏览器的广告拦截插件——它们都是“软件实体”,能感知环境(比如用户的语音/文字输入、网页内容、当前时间/天气),做出决策(比如要不要创建提醒、要不要回答问题、要不要拦截广告),并采取行动(比如调用提醒事项 API、生成文字回复、调用拦截器代码)。
- 机器人领域的 Agent: 扫地机器人、工业机械臂、自动驾驶汽车——它们都是“物理实体”,能感知环境(比如用摄像头/激光雷达看路、用传感器检测障碍物/垃圾),做出决策(比如要不要转弯、要不要清理垃圾、要不要刹车),并采取行动(比如控制轮子/机械臂/刹车)。
- 经济学领域的 Agent: 股票市场的自动交易机器人——它是“经济实体”,能感知环境(比如股票价格、成交量、新闻),做出决策(比如要不要买入/卖出股票),并采取行动(比如调用券商的 API 进行交易)。
在本文中,我们主要关注软件领域的 Agent,特别是可以用 Python 从零实现的简单软件 Agent。
Agent 的核心要素有哪些?
从上面的定义可以看出,Agent 必须具备四个核心要素:
- 目标(Goal): Agent 存在的意义——它是为了完成什么任务而设计的?比如天气提醒小助手的目标是“在特定时间提醒用户带伞/穿衣”,迷你代码助手的目标是“帮助用户解释、执行、修复简单的 Python 代码”。
- 感知器(Perceiver/Sensor): Agent 用来获取环境信息的接口——比如天气提醒小助手的感知器是“当前时间查询接口”和“天气预报查询接口”,迷你代码助手的感知器是“用户的文字输入接口”和“代码执行结果的读取接口”。
- 决策器(Reasoner/Brain): Agent 用来处理感知到的信息、并生成下一步行动的核心模块——比如天气提醒小助手的决策器是“一套规则引擎”(比如“如果明天的天气预报有雨,且当前时间距离明天下午3点还有24小时以上,就不提醒;如果距离还有1小时,就提醒一次;如果距离还有10分钟,就再提醒一次”),迷你代码助手的决策器是“一套大模型 API 调用逻辑”(比如“先用 LLM 分析用户的输入,决定需要调用什么工具;然后生成工具的输入参数;最后根据工具的返回结果继续分析,直到完成目标”)。
- 执行器(Actuator/Actioner): Agent 用来执行决策器生成的行动的接口——比如天气提醒小助手的执行器是“系统弹窗接口”和“邮件/SMS 发送接口”(本文中简化为“打印到控制台”),迷你代码助手的执行器是“Python 代码执行沙箱接口”和“文字输出接口”。
除了这四个核心要素之外,Agent 通常还会有一个记忆体(Memory)——用来存储历史的感知信息、决策信息和行动信息,以便 Agent 能够“记住过去的事情”,做出更合理的决策。比如迷你代码助手的记忆体可以存储“用户之前的问题”、“之前调用过的工具”、“之前的执行结果”,以便 LLM 能够理解上下文。
问题背景:Agent 为什么突然火了?
其实 Agent 并不是一个新的概念——早在 1950 年代,图灵在他的经典论文《计算机器与智能》(Computing Machinery and Intelligence)中就提出了“图灵测试”的思想,而图灵测试中的“机器”本质上就是一个 Agent。在 1980 年代到 1990 年代,Agent 领域也出现了很多经典的理论和框架,比如BDI 模型(Belief-Desire-Intention)、Soar 架构、ACT-R 架构等等。
但为什么 Agent 会在 2022 年 ChatGPT 发布之后突然“火出圈”呢?核心原因有两个:
- 大模型(LLM)的出现解决了 Agent 的“决策瓶颈”: 之前的 Agent 主要是规则驱动或传统机器学习驱动的——规则驱动的 Agent 只能处理预先设定好的场景,灵活性很差;传统机器学习驱动的 Agent 需要大量的标注数据,训练成本很高,而且只能处理特定的任务。而大模型(比如 GPT-3.5/4o、Claude 3、Llama 3)具备强大的自然语言理解能力(NLU)、强大的自然语言生成能力(NLG)、强大的常识推理能力、强大的工具调用能力——这些能力正好解决了 Agent 的决策瓶颈,让 Agent 能够处理复杂的、开放的场景。
- 成熟的工具生态降低了 Agent 的“执行门槛”: 现在市面上有很多成熟的第三方 API(比如 OpenAI API、天气预报 API、地图 API、券商 API)和开源库(比如 requests、selenium、pandas、matplotlib)——这些工具为 Agent 提供了强大的执行能力,让 Agent 能够快速地完成各种任务。
问题描述:我们手写的“简单 Agent”需要满足什么条件?
为了让本文的内容适合新手入门,同时又能体现 Agent 的核心思想,我们手写的“简单 Agent”需要满足以下几个条件:
- 技术栈简单: 只用到 Python 的基础语法、少量的第三方库(比如 requests、datetime、openai)——不需要深度学习、强化学习这些复杂的技术栈。
- 功能完整: 具备 Agent 的四个核心要素(目标、感知器、决策器、执行器),最好还能有一个简单的记忆体。
- 逻辑清晰: 代码结构清晰,注释详细——让新手能够一眼看懂每个模块的作用。
- 可扩展: 代码模块化设计——方便后续添加新的功能、新的工具、新的决策逻辑。
边界与外延:我们手写的“简单 Agent”有什么局限性?
在开始实战之前,我们必须明确我们手写的“简单 Agent”的局限性——避免新手对 Agent 产生过高的期望:
- 规则驱动的 Agent 的局限性: 只能处理预先设定好的场景,灵活性很差——比如天气提醒小助手只能提醒“带伞”,如果用户想让它提醒“买牛奶”,就需要修改规则。
- 大模型驱动的 Agent 的局限性:
- 依赖大模型的能力: 大模型的能力越强,Agent 的能力就越强——如果用 GPT-3.5-turbo,Agent 的能力会比较有限;如果用 GPT-4o,Agent 的能力会强很多,但成本也会高很多。
- 容易产生幻觉(Hallucination): 大模型有时候会编造一些不存在的信息——比如迷你代码助手有时候会编造一些不存在的 Python 库或函数。
- 权限限制: 为了安全起见,我们手写的迷你代码助手只能在一个受限的沙箱里执行简单的 Python 代码——不能访问网络、不能读写本地文件(除了临时文件)。
- 没有长期记忆: 我们手写的 Agent 的记忆体只是一个简单的 Python 列表——只能存储当前会话的信息,会话结束后信息就会丢失。
- 没有强化学习: 我们手写的 Agent 不能从失败中学习——如果它犯了错误,下次还是会犯同样的错误。
不过,这些局限性并不影响我们理解 Agent 的核心思想——当我们掌握了这些核心思想之后,我们就可以在后续的学习中逐步解决这些局限性(比如用向量数据库实现长期记忆、用强化学习让 Agent 从失败中学习、用 LangChain 等成熟框架扩展功能)。
概念结构与核心要素组成
规则驱动 Agent 的概念结构
规则驱动的 Agent 是最简单的一种 Agent,它的决策器是一套预先设定好的规则(If-Then 规则)——当感知器获取到的环境信息满足某个条件时,决策器就会触发对应的行动。
规则驱动 Agent 的概念结构如下:
环境 → 感知器 → 规则引擎(决策器) → 执行器 → 环境
其中:
- 环境(Environment): 规则驱动 Agent 所在的外部世界——比如天气、当前时间、用户的输入。
- 感知器(Perceiver): 负责从环境中获取信息——比如调用天气预报 API 获取明天的天气、调用 datetime 库获取当前时间。
- 规则引擎(Rule Engine): 负责根据感知到的信息和预先设定好的规则生成下一步的行动——比如“如果明天有雨,且当前时间是明天下午2点50分,就执行‘打印带伞提醒’的行动”。
- 执行器(Actuator): 负责执行规则引擎生成的行动——比如打印到控制台、发送邮件、调用系统弹窗。
大模型驱动 Agent 的概念结构
大模型驱动的 Agent 是目前最流行的一种 Agent,它的决策器是一套大模型 API 调用逻辑——核心是经典的 ReAct 循环(Reasoning + Acting + Observing)。
大模型驱动 Agent 的概念结构如下:
环境 → 感知器 → 记忆体 → 大模型(决策器) → 执行器 → 环境
↑_________________________________________________________|
其中:
- 环境(Environment): 大模型驱动 Agent 所在的外部世界——比如用户的输入、代码执行的结果、网络请求的结果。
- 感知器(Perceiver): 负责从环境中获取信息——比如读取用户的文字输入、读取代码执行的输出结果。
- 记忆体(Memory): 负责存储历史的感知信息、决策信息(Reasoning)、行动信息(Acting)——比如“用户之前问了什么问题”、“LLM 之前是怎么思考的”、“之前调用了什么工具,返回了什么结果”。
- 大模型(LLM): 负责根据记忆体中的信息和当前的感知信息生成下一步的 Reasoning 和 Acting——比如“先分析用户的问题,然后决定需要调用‘代码执行’工具,接着生成执行的 Python 代码,最后等待工具返回结果”。
- 执行器(Actuator): 负责执行大模型生成的 Acting——比如调用“代码执行”工具、调用“文字输出”工具。
- ReAct 循环: 整个过程是一个循环——大模型生成 Reasoning 和 Acting → 执行器执行 Acting → 感知器观察 Acting 对环境的影响 → 将观察结果存入记忆体 → 大模型根据记忆体中的信息生成下一步的 Reasoning 和 Acting → 直到完成目标。
概念之间的关系:规则驱动 vs 大模型驱动
核心属性维度对比(Markdown 表格)
为了更直观地理解规则驱动 Agent 和大模型驱动 Agent 的区别,我们可以从以下几个核心属性维度进行对比:
| 核心属性维度 | 规则驱动 Agent | 大模型驱动 Agent |
|---|---|---|
| 决策方式 | 预先设定好的 If-Then 规则 | 大模型的自然语言推理(NLU + NLG + 常识推理 + 工具调用) |
| 灵活性 | 很低——只能处理预先设定好的场景,场景变化时需要修改规则 | 很高——能够处理复杂的、开放的场景,不需要预先设定规则 |
| 可控性 | 很高——每一步的行动都是预先设定好的,不会产生意外的结果 | 较低——大模型容易产生幻觉,可能会生成意外的行动,需要做好权限限制和错误处理 |
| 成本 | 很低——不需要调用大模型 API,只需要 Python 的基础语法和少量的第三方库 | 较高——需要调用大模型 API,成本取决于大模型的类型和调用次数 |
| 训练/配置成本 | 较高——需要人工编写大量的 If-Then 规则,场景越复杂,规则越多 | 较低——只需要编写简单的提示词(Prompt)和工具封装,不需要人工编写大量的规则 |
| 适合的场景 | 简单的、固定的、高频的场景——比如天气提醒、闹钟、广告拦截、自动回复消息 | 复杂的、开放的、低频的场景——比如代码解释、代码执行、代码修复、旅行规划、邮件撰写 |
| 是否需要记忆体 | 通常不需要——规则引擎只需要当前的感知信息就能做出决策 | 通常需要——大模型需要理解上下文才能做出合理的决策 |
| 是否需要强化学习 | 不需要——规则是固定的,不能从失败中学习 | 可选——可以通过强化学习让 Agent 从失败中学习,提高决策的准确性 |
概念联系的 ER 实体关系图(Mermaid 架构图)
虽然规则驱动 Agent 和大模型驱动 Agent 有很多区别,但它们也有很多共同的核心要素——我们可以用 ER 实体关系图来表示它们之间的联系:
ReAct 循环的交互关系图(Mermaid 流程图)
ReAct 循环是大模型驱动 Agent 的核心架构——我们可以用 Mermaid 流程图来更直观地理解它的交互关系:
数学模型:Agent 的通用数学模型
虽然我们手写的简单 Agent 不需要复杂的数学模型,但了解 Agent 的通用数学模型有助于我们更深入地理解 Agent 的本质。
Agent 的通用数学模型可以用以下公式表示:
1. 感知函数(Perception Function)
感知函数 PPP 负责将环境的当前状态 StS_tSt 映射为 Agent 的感知输入 OtO_tOt:
Ot=P(St)O_t = P(S_t)Ot=P(St)
其中:
- ttt 表示时间步(Time Step)。
- StS_tSt 表示环境在时间步 ttt 的当前状态——环境状态通常是部分可观测的(Partially Observable),也就是说 Agent 无法直接获取环境的全部状态,只能获取一部分状态。
- OtO_tOt 表示 Agent 在时间步 ttt 的感知输入——感知输入是环境状态的一个子集。
2. 决策函数(Reasoning Function)
决策函数 RRR 负责将 Agent 的历史感知输入 O1,O2,...,OtO_1, O_2, ..., O_tO1,O2,...,Ot、历史行动 A1,A2,...,At−1A_1, A_2, ..., A_{t-1}A1,A2,...,At−1、以及 Agent 的目标 GGG 映射为 Agent 的当前行动 AtA_tAt:
At=R(O1,O2,...,Ot;A1,A2,...,At−1;G)A_t = R(O_1, O_2, ..., O_t; A_1, A_2, ..., A_{t-1}; G)At=R(O1,O2,...,Ot;A1,A2,...,At−1;G)
其中:
- AtA_tAt 表示 Agent 在时间步 ttt 的当前行动——行动可以是“调用工具”、“输出答案”、“结束会话”等等。
- 历史感知输入 O1,O2,...,OtO_1, O_2, ..., O_tO1,O2,...,Ot 和历史行动 A1,A2,...,At−1A_1, A_2, ..., A_{t-1}A1,A2,...,At−1 通常存储在 Agent 的记忆体 MtM_tMt 中——记忆体 MtM_tMt 可以看作是历史信息的一个压缩表示:
Mt=M(Mt−1,Ot,At−1)M_t = M(M_{t-1}, O_t, A_{t-1})Mt=M(Mt−1,Ot,At−1)
其中 MMM 是记忆更新函数(Memory Update Function)。
因此,决策函数 RRR 也可以简化为:
At=R(Mt,G)A_t = R(M_t, G)At=R(Mt,G)
3. 执行函数(Execution Function)
执行函数 EEE 负责将 Agent 的当前行动 AtA_tAt 和环境的当前状态 StS_tSt 映射为环境的下一个状态 St+1S_{t+1}St+1:
St+1=E(At,St)S_{t+1} = E(A_t, S_t)St+1=E(At,St)
4. 奖励函数(Reward Function)
奖励函数 RewRewRew 负责将环境的当前状态 StS_tSt、Agent 的当前行动 AtA_tAt、以及环境的下一个状态 St+1S_{t+1}St+1 映射为一个标量奖励 RtR_tRt——奖励函数主要用于强化学习驱动的 Agent,用来评估 Agent 的行动是否有利于实现目标:
Rt=Rew(St,At,St+1)R_t = Rew(S_t, A_t, S_{t+1})Rt=Rew(St,At,St+1)
本章小结
在本文的第一部分(概念认知篇)中,我们彻底搞懂了 Agent 的本质与核心要素:
- 什么是 Agent: Agent 是一个能够感知环境、做出决策、并采取行动以实现特定目标的实体。
- Agent 的核心要素: 目标、感知器、决策器、执行器——通常还会有一个记忆体。
- Agent 的类型: 规则驱动、数据驱动、传统机器学习驱动、大模型驱动、混合驱动——本文主要关注规则驱动和大模型驱动。
- 经典的 ReAct 循环: Reasoning + Acting + Observing——这是目前几乎所有成熟 Agent 框架的核心架构。
- Agent 的通用数学模型: 感知函数、决策函数、执行函数、奖励函数——虽然我们手写的简单 Agent 不需要用到这些数学模型,但了解它们有助于我们更深入地理解 Agent 的本质。
在下一部分(规则驱动 Agent 实战篇)中,我们将从零实现一个规则驱动的“天气提醒小助手”——包括需求分析、环境安装、架构设计、接口设计、核心实现、测试优化。
(全文预计剩余 8000 字左右,将继续按照目录结构展开,下一部分为规则驱动 Agent 实战篇)
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)