「Hello Agents 第07章」为什么要造轮子?200行Python手写Agent框架
当你用LangGraph写了第三个Agent之后,你会开始思考:这些框架到底帮我做了什么?自己造一个轮子,是搞懂框架本质最快的方式——没有之一。
为什么在LangGraph已存在的情况下,还要自己写框架?
这个问题我问过很多人,得到最多的回答是:”不需要,直接用现成的就好。”
但我的经历恰好相反。
当我第一次用LangGraph跑通一个ReAct Agent之后,我对它的工作原理几乎一无所知。StateGraph是什么?ToolNode内部发生了什么?add_conditional_edges的路由逻辑是怎么写进去的?这些黑盒让我在遇到Bug时完全不知道从哪里下手。
直到我花了一个周末,从零实现了一个200行的最小化Agent框架,才真正搞清楚这些概念。
自建框架的三个真实价值:
- 理解本质:你会明白框架在帮你做什么,遇到问题有地方下手
- 可控性:在现有框架不满足需求时,你有能力裁剪和扩展
- 面试必杀技:能说清楚”我造过轮子,知道轮子里有什么”的候选人,价值翻倍
一、一个Agent框架的核心组件是什么?
剥开LangGraph、AutoGen的外壳,一个Agent框架的核心只有四个组件:
graph TB
subgraph "Agent框架核心"
A["🎯 Router<br/>路由决策器<br/>决定下一步做什么"]
B["🔧 Tool Registry<br/>工具注册表<br/>管理所有可用工具"]
C["🧠 Memory<br/>记忆管理<br/>维护对话上下文"]
D["🔄 Message Loop<br/>消息循环<br/>驱动整体运行"]
end
INPUT["📥 用户输入"] --> D
D --> C
C --> A
A -->|"调用工具"| B
A -->|"生成回答"| OUTPUT["📤 最终输出"]
B -->|"工具结果"| D
style A fill:#FFB3C6,stroke:#F48FB1,color:#333
style B fill:#FFDAB9,stroke:#FFAB76,color:#333
style C fill:#E8D5F5,stroke:#CE93D8,color:#333
style D fill:#C7CEEA,stroke:#9FA8DA,color:#333
style INPUT fill:#B5EAD7,stroke:#80CBC4,color:#333
style OUTPUT fill:#B5EAD7,stroke:#80CBC4,color:#333| 组件 | 类比 | 核心问题 |
|---|---|---|
| Router(路由决策器) | 项目经理 | 下一步该做什么? |
| Tool Registry(工具注册表) | 工具箱 | 有哪些工具可以用? |
| Memory(记忆管理) | 会议纪要 | 到目前为止发生了什么? |
| Message Loop(消息循环) | 工作流水线 | 如何把上面三个串起来? |
理解了这四个组件,你就理解了所有Agent框架的骨架。
二、架构设计:最小化Agent框架
我们要构建的框架叫 MiniAgent,设计原则:
- 最小依赖:只依赖
openai这一个外部库 - 可扩展:工具通过装饰器注册,随时添加
- 完整可用:ReAct(推理+行动)循环,支持多轮对话
graph LR
subgraph "MiniAgent 架构"
direction TB
REG["🔧 ToolRegistry<br/>@tool装饰器注册<br/>tool_map字典存储"]
MEM["🧠 Memory<br/>messages列表<br/>滑动窗口截断"]
LOOP["🔄 AgentLoop<br/>ReAct循环驱动"]
ROUTER["🎯 Router<br/>LLM function_call<br/>决定行动"]
end
USER["👤 用户"] -->|"query"| LOOP
LOOP --> MEM
MEM -->|"历史消息"| ROUTER
ROUTER -->|"tool_call"| REG
REG -->|"结果"| LOOP
LOOP -->|"最终答案"| USER
style REG fill:#FFDAB9,stroke:#FFAB76,color:#333
style MEM fill:#E8D5F5,stroke:#CE93D8,color:#333
style LOOP fill:#C7CEEA,stroke:#9FA8DA,color:#333
style ROUTER fill:#FFB3C6,stroke:#F48FB1,color:#333
style USER fill:#B5EAD7,stroke:#80CBC4,color:#333三、手把手实现:200行Python写一个能用的Agent框架
下面的代码可以直接运行(需要 pip install openai):
1 | """ |
四、常见误区
❌ 误区1:框架越多功能越好
初学者常常堆砌功能:加个向量数据库、加个Web搜索、加个代码执行……
真相:功能越多,调试越难。一个你完全理解的简单框架,比一个你不明白的复杂框架可靠100倍。从最小可用版本开始,按需扩展。
❌ 误区2:直接把用户输入传给eval
上面的calculate工具里,我做了一个简单的字符白名单过滤。在生产环境中,直接eval用户输入是严重的安全漏洞。
应该使用 ast.literal_eval 或专门的数学解析库如 simpleeval。
❌ 误区3:记忆不做截断
很多人把所有对话历史都塞进消息列表,结果在第几十轮对话后触发context limit错误。
正确做法:
- 短期:滑动窗口(如上面Memory实现的
max_messages) - 长期:把重要信息存到外部数据库(第八章的RAG)
❌ 误区4:没有迭代次数限制
如果LLM进入了”工具A → 工具B → 工具A → 工具B”的死循环,没有max_iterations的Agent会一直运行,直到你的API账单爆炸。
五、何时自建 vs 使用现有框架
| 场景 | 建议 | 理由 |
|---|---|---|
| 学习理解Agent原理 | ✅ 自建 | 没有比造轮子更好的方式 |
| 快速验证业务可行性 | ✅ 现有框架 | LangGraph/AutoGen省掉大量脚手架 |
| 需要深度定制工具调用逻辑 | ✅ 自建或魔改 | 框架的封装可能是障碍 |
| 生产环境高并发 | ✅ 现有框架 | 他们处理过的边界情况比你想象的多 |
| 框架不支持你的模型API | ✅ 自建 | 适配一个奇怪的模型格式,自建更直接 |
| 团队中有人不熟悉框架 | ⚠️ 权衡 | 学习成本 vs 自建成本,看团队情况 |
graph TD
Q1{"目的是什么?"}
Q1 -->|"学习/理解"| SELF["✅ 自建<br/>最好的老师"]
Q1 -->|"快速上线"| Q2{"需要深度定制?"}
Q2 -->|"否"| EXISTING["✅ 现有框架<br/>省时省力"]
Q2 -->|"是"| Q3{"框架能魔改吗?"}
Q3 -->|"能"| FORK["⚠️ Fork框架<br/>在基础上改"]
Q3 -->|"不能"| SELF2["✅ 自建<br/>从头控制"]
style Q1 fill:#FFF9C4,stroke:#F9A825,color:#333
style Q2 fill:#FFF9C4,stroke:#F9A825,color:#333
style Q3 fill:#FFF9C4,stroke:#F9A825,color:#333
style SELF fill:#B5EAD7,stroke:#80CBC4,color:#333
style EXISTING fill:#B5EAD7,stroke:#80CBC4,color:#333
style FORK fill:#FFDAB9,stroke:#FFAB76,color:#333
style SELF2 fill:#FFB3C6,stroke:#F48FB1,color:#333六、下一步怎么学?
你现在手里有一个200行的Agent框架了。接下来的扩展方向:
- 加入RAG(第八章):让Agent能检索文档知识库,而不只依赖LLM内置知识
- 加入多Agent:实现多个MiniAgent互相通信,复现AutoGen的协作模式
- 加入持久化记忆:把Memory的messages列表存到SQLite或Redis,支持跨会话记忆
graph LR
MINI["🚀 MiniAgent<br/>(本章)"] --> RAG["📚 + RAG记忆<br/>(第8章)"]
RAG --> MULTI["🤝 + 多Agent<br/>(自行扩展)"]
MULTI --> PROD["🏭 生产级框架<br/>(你自己的版本)"]
style MINI fill:#C7CEEA,stroke:#9FA8DA,color:#333
style RAG fill:#B5EAD7,stroke:#80CBC4,color:#333
style MULTI fill:#FFDAB9,stroke:#FFAB76,color:#333
style PROD fill:#FFB3C6,stroke:#F48FB1,color:#333当你能从零写出一个Agent框架,再去看LangGraph的源码,会发现它和你写的东西本质上一模一样——只不过它处理了更多边界情况,有更好的可观测性。这才是真正的”知其所以然”。
📚 Hello Agents 系列导航
本文是《Hello Agents》开源系列第 7/16 章,适合 AI Agent 开发入门到进阶学习。
| 方向 | 章节 |
|---|---|
| ◀ 上一章 | 第06章:当一个Agent不够用时:三大框架多智能体实战 |
| 下一章 ▶ | 第08章:Agent为何失忆?RAG与记忆系统深度解析 |
📖 全部 16 章目录(点击展开)
- 初识智能体:LLM会聊天,Agent能办事
- 智能体60年:从会下棋到能打工
- LLM原理:它不理解语言,却比你更会用语言
- Agent思考三剑客:ReAct、Plan-and-Solve与Reflection
- 不会写代码也能搭AI Agent?低代码平台实战指南
- 当一个Agent不够用时:三大框架多智能体实战
- 为什么要造轮子?200行Python手写Agent框架 ← 当前
- Agent为何失忆?RAG与记忆系统深度解析
- Context Engineering:让Agent真正聪明的隐秘武器
- AI Agent如何与世界对话:MCP、A2A、ANP协议全解析
- 用强化学习驯服AI Agent:GRPO与Agentic RL全解析
- 你的Agent真的好用吗?智能体评估体系完全指南
- 用Agent规划日本5日游,2分钟搞定2小时的活
- 自动写研究报告的Agent:比ChatGPT深,但有盲点
- 赛博小镇:25个AI角色自主生活,涌现了什么?
- 学完16章,现在从0构建你自己的Agent
本章用 200 行 Python 手写一个 Agent 框架,对比维度:自研 vs 相邻章节的工业框架 vs 其他轻量开源实现。
对比分析
一、本章概念 vs 相邻章节
| 维度 | ch07 自研框架 | ch06 三大框架 | ch08 记忆检索 | ch09 Context Engineering |
|---|---|---|---|---|
| 抽象层级 | Runtime + Tool 接口 | 上层 API | 记忆子系统 | Prompt 与上下文子系统 |
| 学习收益 | 理解 Agent 本质 | 学会用轮子 | 学会扩展能力 | 学会用好轮子 |
| 与本章互补 | —— | 提供参考实现 | 提供能力外挂 | 提供调优手段 |
二、对比生产中类似轻量框架
| 项目 | 行数级别 | 设计哲学 | 与本章对照 |
|---|---|---|---|
| smolagents | ~1k 行 | code Agent、极简 | 同样强调”短小” |
| LangChain v0 | ~1k 行(早期) | 链式组合 | 同样强调可组合 |
| LlamaIndex agent | 中等 | 数据 / RAG 优先 | 在 ch08 上更强 |
| eliza(ai16z) | 中等 | 角色 + 消息总线 | 多 Agent 通信视角不同 |
三、本章观点的优缺点
优点:
- 去掉所有”魔法”,看清 ReAct 循环的真实结构
- 用 200 行说明”框架并不神秘”
缺点:
- 没有错误恢复 / 工具超时等生产级细节
- 没有可观测性(logging、trace)
四、何时选
- 想造自己的框架 / 公司内 SDK:按本章结构起步
- 想用现成:直接 ch06 选框架
- 想做企业级:在本章基础上加记忆(ch08)、协议(ch10)