AI Agent 搭建必备:模型、工具、记忆与编排的5个开源装备
不瞒各位我最近在技术社区潜水的时候发现问得最频繁的话题已经从“哪个模型最强”悄悄变成了“AI agent 到底怎么搭”。和标题相关的那几个热搜词里“agent 和 LLM 和 AI 模型有什么区别”“deepseek 属于哪个”“ai agent skill memory mcp”这几条几乎每天都有人翻来覆去地问。这些问题的背后其实是同一个核心困惑大家手里已经有了不错的模型也知道 agent 是趋势但一动手就发现——光有模型根本跑不出一个像样的 agent中间缺了一大把“装备”。这篇内容就是来补这个缺口的。我会以 GitHub 上的热门开源项目为主线按一个 agent 真正需要的几个子系统来拆模型接入与执行环境、工具调用协议、记忆层、工作流编排以及底层的状态控制。一共挑 5 个项目每个我都会说明它解决的是哪一块问题应该怎么上手以及在实际使用中容易踩哪些坑。适合刚入门的开发者也适合已经跑了几个 Demo、想往生产级方向推进的人参考。1. 先搞懂 AI agent 到底由哪些零件组成很多人把 agent 想成一个“更聪明的 AI”这个理解其实跑偏了。模型只是给 agent 提供推理能力的一张“显卡驱动”而 agent 本身是一个系统——它需要感知、决策、调用工具、记住上下文还要能对外部反馈做出反应。这也是为什么热搜词里会出现“ai agent 组成结构”“ai agent harness 自动化运维”这类问题大家已经在追问内部构造了。1.1 用一个老朋友来锚定概念DeepSeek 属于哪一层热搜词里有一条问得很典型“deepseek 是属于 agent 还是模型”答案是DeepSeek 属于模型层也就是 LLM。它解决的问题是“文字接龙”——你给它一段输入它预测下一段最合理的输出。它甚至可以做工具调用的规划但前提是外部的框架把工具列表、规则和状态喂给它。agent 则是在模型之上加了一圈“驾驶舱”。驾驶舱里至少包含几个部分模型内核负责推理和生成比如 DeepSeek、GPT、Claude、Qwen都属于这一层。工具访问层它决定了 agent 能不能读文件、查数据库、调 API、操作网页。MCP 就是这一层的协议标准。记忆层让 agent 在多个会话之间记住偏好和事实而不是每次对话都“失忆”。编排层/状态机控制 agent 先做什么、后做什么、什么条件下重试、什么条件下把控制权交还给人。LangGraph 就是干这个的。执行环境agent 如果真的要操作电脑、写代码、跑脚本就需要一个可控的沙箱环境。OpenHands 这块做得很完整。1.2 一个典型 agent 的推理循环把上面的零件串起来看一个标准的 agent 工作循环长这样用户输入目标比如“帮我把这个仓库的 README 翻译成中文并提交一个 PR”。模型思考决定是否需要调用工具输出一个结构化的工具调用请求。工具访问层把请求转发给对应工具拿到结果后回填给模型。模型根据工具结果更新计划继续下一步或者向用户请求澄清。循环直到任务完成。这个过程中任何一个零件缺失都会让体验大打折扣。比如没有 MCP 这一层工具调用就得为每家 API 单独写胶水代码没有记忆层每次会话都要重新告诉 agent 你的偏好没有状态机循环一旦分叉就容易陷入死循环。1.3 下文 5 个项目的对应关系我挑选项目时不是按“谁 Star 多”来排的而是按“能不能把上面某个零件补齐”来排的OpenHands完整的 agent 执行环境相当于一台带驾驶舱的整机。MCP 全家桶modelcontextprotocol 官方仓库工具访问层的标准插座。mem0记忆层的独立组件。Dify可视化编排层适合快速搭业务。LangGraph底层状态编排框架适合自研复杂 agent。下面一个个讲。2. 第一件装具OpenHands能真跑的 agent 主机OpenHands 由 All-Hands-AI 团队维护原项目名叫 OpenDevin后来改了名。它的定位很清晰一个开源的 AI 软件工程师代理。和那种只能聊天的机器人不同OpenHands 真的能在沙箱里操作文件、执行命令、安装依赖、编辑代码然后一步步把任务做完。2.1 这个项目解决什么问题我自己跑过不少 agent 框架最常见的问题就是“规划一套套落不了地”。模型很会输出步骤但真正执行时要么没有环境权限要么中间状态丢失。OpenHands 把这些问题打包处理掉了。它的核心设计有几点很值得关注Docker 沙箱执行所有命令、代码都跑在隔离容器里不影响宿主机也不怕 agent 把系统搞乱。多 Agent 架构任务规划、代码生成、测试执行由不同 agent 角色协作完成而不是一个模型硬扛。事件流机制Event Stream每一步操作都会被记录成事件方便调试、回溯也方便你观察模型到底做了什么、为什么卡住。模型无关OpenAI、Anthropic、DeepSeek、Ollama 本地模型都能接。2.2 安装与首次运行的实测建议仓库地址是All-Hands-AI/OpenHands。安装方式有两种我建议优先选 Docker。用 Docker 运行 :docker pull docker.all-hands.dev/all-hands/openhands:latest mkdir -p ~/.openhands docker run -it --rm \ -e OPENAI_API_KEY你的 API Key \ -v ~/.openhands:/.openhands \ -v /var/run/docker.sock:/var/run/docker.sock \ -p 3000:3000 \ docker.all-hands.dev/all-hands/openhands:latest开启 Web UI 后在浏览器打开http://localhost:3000填入模型供应商信息和 API Key 就能开始用了。如果你只是想快速试试 CLI也可以用 pip 安装不过依赖隔离确实麻烦强烈建议用pipx而不是直接 pippipx install openhands-ai openhands实测下来Docker 方式最大的好处是环境干净。因为 agent 要执行任意命令如果直接跑在宿主机上万一它rm -rf一个错误目录那就有意思了。沙箱至少给你留了后悔药。2.3 使用中容易被忽略的三个细节第一别把它当纯聊天框。OpenHands 是干活的你要给它具体任务比如“看看这个项目为什么编译失败并修复”。任务描述越具体完成度越高。你要是问“你觉得这个项目怎么样”它也会答但那完全浪费了这个工具的能力。第二Token 消耗比纯对话高很多。原因是 agent 会反复观察命令输出、读取文件、修改代码每一步都要把上下文发给模型。我跑一个中型 bug 修复任务通常要烧掉几十万 token。建议在开放任务之前先给一个预算上限或者用单价更低的模型做执行用强模型做规划。第三注意.openhands目录里会保存大量历史记录。如果你的磁盘空间紧张记得定期清理因为事件流日志增长得很快。3. 第二件装具MCP 全家桶agent 的工具插座MCP 是 Model Context Protocol 的缩写最早由 Anthropic 发起并开源现在已经是 agent 工具连接的事实标准。热搜词里那条“ai agent skill memory mcp”其实就精准地指出了 agent 时代的三个关键词——技能、记忆、协议。其中 MCP 解决的是“agent 怎么用上外部工具”的问题。3.1 MCP 到底解决了什么在没有 MCP 以前每个 agent 想接入一个新工具都要为它单独写一套调用逻辑GitHub 一个接口封装、数据库一个接口封装、浏览器一个接口封装。工具少还好工具一多维护成本直接爆炸。MCP 把问题标准化了。它的结构和你家里配电箱差不多Hostagent 本体比如 OpenHands、Claude Desktop、Dify 里的 agent。Server每个工具就是一个 MCP Server暴露出一组“可被调用的工具”。Protocol统一的 JSON-RPC 传输协议Host 和 Server 按同一套规范通信。这样带来的好处是工具方只需要实现一次 MCP Server任何支持 MCP 的 agent 都能用agent 方也只需要支持 MCP 协议就能接入生态里所有现成的工具。你可以把 MCP 理解成 agent 的 USB-C 接口。过去你给电脑接打印机要装驱动、接显示器要装驱动现在只要设备支持 USB-C 标准插上就能用。MCP 就是这个标准。3.2 官方仓库里有什么GitHub 上的组织账号是modelcontextprotocol下面有几个最重要的仓库仓库作用servers官方维护的参考 Server 集合包含 GitHub、Filesystem、PostgreSQL、Fetch、Brave Search 等常用工具python-sdk用 Python 快速开发和接入 MCP Server 的 SDKtypescript-sdkTypeScript 版本的 SDKspecificationMCP 协议规范的官方文档上手路径我建议这样先看servers仓库里的 filesystem 和 fetch 两个例子明白一个工具服务器大概长什么样再用官方 SDK 写一个自己的 Server。3.3 一个最简 MCP Server 示例下面是一个用 Python SDK 写的极简时间查询工具跑通它你就能理解整个模型。from mcp.server.fastmcp import FastMCP mcp FastMCP(demo-server) mcp.tool() def get_current_date() - str: 返回今天的日期格式为 YYYY-MM-DD。 from datetime import date return str(date.today()) mcp.tool() def add_numbers(a: float, b: float) - float: 计算两个数字的和。 return a b if __name__ __main__: mcp.run()安装依赖并运行pip install mcp[fastmcp] python demo_server.py启动后这个 Server 就通过标准输入输出和 Host 通信了。你的 agent 每需要一次“获取当前日期”就会调用这个工具然后把返回结果交给模型继续推理。整个过程对模型是透明的模型只负责“要不要调用、怎么调”具体执行是全靠工具。我个人的建议是如果你是做 agent 开发的一定要培养“工具优先”的思维。遇到一个外部系统先想“能不能包成一个 MCP Server”而不是“能不能让模型直接生成调这个系统的代码”。前者稳定、可复用后者容易在参数格式上翻车。4. 第三件装具mem0记忆这一层不能省很多 agent 项目 Demo 跑得很顺一上真实业务就露馅原因往往不在模型而在“没有记忆”。你上午告诉它“用户偏好简洁回复”下午它又变成话痨它上次查完资料后留下的结论这次对话根本找不到。这就是记忆层缺失的表现。4.1 没有记忆的 agent 有多难受记忆分几种你得先分清楚短期记忆当前对话窗口里的上下文由模型的 context window 管理。长期记忆跨会话持久化的事实和偏好需要外部存储。情景记忆某次任务的过程记录可以用来复盘和优化。语义记忆对领域知识的结构化理解。大多数框架只做了前两种。长期记忆这块常见方案是直接把历史记录全文塞给模型但这样又贵又容易被无关信息干扰。更好用的方式是提取“有效的记忆条目”——比如“用户喜欢 Python 而不是 Java”“这个项目的构建命令是 make build”——然后存进向量库或图数据库需要时再检索出来。4.2 mem0 是什么以及怎么接入mem0GitHub 地址mem0ai/mem0就是一个专门给 AI agent 设计的长期记忆层。它会从你和模型的交互中自动抽取记忆按用户或会话分别存储并在后续对话中把相关记忆自动注入上下文。安装pip install mem0ai基本使用方式from mem0 import Memory memory Memory() # 每次和 agent 交互后把对话内容喂给记忆层 memory.add(用户说所有生成的代码必须带类型注解, user_idalice) # 下次 agent 思考前先检索相关记忆 relevant_memory memory.search(代码风格偏好, user_idalice) print(relevant_memory)这里有个关键设计你在内存里存的不是“全文”而是“结构化后的记忆片段”。检索时也是按相关性召回而不是把所有历史记录都塞进上下文。这样做既能省 token又能提升准确率。mem0 底层支持多种向量数据库和存储后端你可以在初始化时指定用 Qdrant、Chroma 还是 PGVector。生产环境我推荐单独部署一个向量库本地测试用默认配置就行。4.3 记忆颗粒度与隐私注意事项用记忆层会遇到一个绕不开的问题哪些信息该记住哪些不该记我测试下来有两条经验别主动存隐私信息。在真实业务里记忆系统可能会记住手机号、身份证号这类敏感数据一旦数据库泄露就是大事故。要给“遗忘”留出口。mem0 支持按用户删除记忆你应该在设计产品时给用户一个“清除我的记忆”入口这不只是合规需要也是基本的信任问题。另外记忆是有时效性的。用户偏好会变项目上下文也会变。如果只往库里写、从不更新三个月后 agent 用老记忆回答新问题效果反而比没记忆更糟。建议定期清理或手动调整记忆条目。5. 第四件装具Dify可视化编排上手最快我见过不少团队技术栈还没定就急着让 AI 干活结果花了三周写胶水代码最后发现已有现成的开源平台能干同样的事。Dify 就是这类平台里最有名的一个。5.1 Dify 在 agent 生态里的位置DifyGitHub 地址langgenius/dify是一个开源的 LLM 应用开发平台。你可以用它搭 RAG 问答机器人、可视化工作流、智能体应用甚至带定时任务和插件系统。如果你不想深究底层状态机直接用 Dify 拖拖拽拽就能出一个业务可用的 agent。它和 LangGraph 这种框架的区别在于Dify 提供的是完整产品自带前端界面、用户管理、日志、标注LangGraph 是让你自己拼装的零件。对大多数业务场景先用 Dify 跑通比从零自己搭一套要理性得多。5.2 从零建一个带工具调用的 AgentDify 支持docker compose一键部署部署完进入工作台创建“Agent 应用”然后按下面几步操作配置模型供应商。在“设置-模型供应商”里填 API Key支持 OpenAI、Anthropic、DeepSeek、Ollama 等几乎市面上主流的模型都接好了。在 Agent 应用的编排页面选择“Agent 模式”启用“工具调用”。在工具列表里添加内置工具或自定义 OpenAPI 工具。比如加一个“天气查询”APIagent 在回答天气问题时就会自动调用。设置系统提示词约束 agent 的回复风格和权限边界。我自己测试过的一个典型 Dify agent 长这样用户提问“帮我看看这个 CSV 文件里哪个月销售额最高”agent 先调用代码解释工具读取文件再调用数据分析工具跑统计最后用自然语言把结论讲出来。整个过程在 Dify 的日志里都能看到每个节点的输入输出排错非常方便。5.3 什么时候该换掉 DifyDify 很方便但它不是万能的。遇到下面几种情况你就该考虑迁移到 LangGraph 或自己写框架了你的 agent 逻辑需要复杂的条件判断、循环、多轮人机协作Dify 的可视化节点会变得非常臃肿。你需要在 agent 运行过程中用代码动态调整工具集和数据源Dify 的可视化配置会限制你的发挥。你有很高的自定义部署要求比如需要在每个请求里注入特定的鉴权逻辑Dify 的封装反而成了障碍。用一句话总结Dify 适合“把它当产品用”LangGraph 适合“把它当积木用”。先明确你的定位再选工具。6. 第五件装具LangGraph把 agent 变成可控程序如果前面的项目你都试过了并且开始不满足于“能用”想追求“稳定可控”那你迟早会接触到 LangGraph。它的目标是把 agent 的这种自由发挥约束进一个可控的状态机里。6.1 为什么需要状态机一个 agent 的核心循环其实是“反复思考-行动-观察”。用普通代码写这个循环你会陷入一堆 if-else 和 while 的泥潭。而状态机提供了一种更清晰的范式定义若干个状态节点定义状态之间的转移条件边agent 每次运行就是从起始节点出发按条件走出一条路径。LangGraph 最典型的场景是“人机回退”human-in-the-loop。比如 agent 在执行某个高风险操作前可以先停留在“等待审批”状态等审批结果出来再决定继续还是终止。用 LangGraph 原生的中断和恢复机制处理比你自己维护一个外部队列要省心太多。6.2 核心 API 与一个最小示例LangGraph 由 LangChain 团队维护GitHub 地址langchain-ai/langgraph。它的核心概念只有几个StateGraph、节点、边、状态对象。下面是一个简单的“研究助手”状态机示例agent 先做搜索再生成最终答案。from typing import TypedDict, Literal from langgraph.graph import StateGraph, END class AgentState(TypedDict): query: str search_results: list final_answer: str def search_node(state: AgentState) - dict: # 这里替换成真实的搜索工具 state[search_results] [f关于 {state[query]} 的搜索结果1] return {search_results: state[search_results]} def answer_node(state: AgentState) - dict: # 这里替换成真实的模型调用 state[final_answer] f根据搜索结果回答如下{state[search_results][0]} return {final_answer: state[final_answer]} def should_continue(state: AgentState) - Literal[answer, search]: # 不满足条件就继续搜索否则生成答案 if len(state[search_results]) 3: return answer return search graph StateGraph(AgentState) graph.add_node(search, search_node) graph.add_node(answer, answer_node) graph.set_entry_point(search) graph.add_conditional_edges(search, should_continue, {answer: answer, search: search}) graph.add_edge(answer, END) app graph.compile() result app.invoke({query: 2025年 agent 最佳实践, search_results: [], final_answer: }) print(result[final_answer])这个例子看起来简单但它把 agent 的“循环-条件-终止”都变成了显式结构。你可以在任何一个节点插入日志、检查点、人工确认动作这是普通提示词工程做不到的。6.3 和 LangChain 的区别很多人会把 LangGraph 和 LangChain 混淆。LangChain 是工具链提供各种接口抽象LangGraph 是运行时负责控制 agent 的执行流程。实际项目中两者常一起用LangChain 提供工具、模型封装LangGraph 编排流程。不过我要提醒一句LangGraph 的学习曲线明显比 Dify 陡。如果你不需要对人机协作和复杂状态做精细控制直接用 Dify 更划算。技术选型不是为了炫技是为了解决问题。7. 按场景打包这套装备怎么组合不踩坑单个项目讲完了最后说说组合策略。很多读者拿到一篇文章就开始“全家桶安装”结果每个组件都装了、每个都没跑通最后得出结论“ai agent 搭建太难”。其实是因为缺少规划。装备不是越多越好而是越对越好。7.1 三条推荐组合路径针对不同目标我给出三条实测过比较顺的路径目标建议组合理由快速验证一个 agent 业务Dify 官方 MCP Servers30 分钟出原型工具链成熟不用写基础设施代码开发一个能写代码的技术助手OpenHands MCP 工具 mem0执行环境隔离工具调用标准化记忆持久化自研一个生产级复杂 agentLangGraph 自建 MCP Server mem0 向量库状态可控、可插拔、可观测适合长期演进注意第一条路径我不建议再加 LangGraph。Dify 本身有状态控制能力再加一套状态机会造成管理复杂度翻倍。先跑通业务再看有没有必要换底座。7.2 选型心法先跑通再重构这是我自己踩了很多坑之后总结的一句话。不少开发者包括我早期也是这样一上来就想搭建最完美的架构模型要最强、框架要最新、存储要分布式。结果架构还没搭完需求已经变了。正确的姿势是用一个最小组合把业务跑通哪怕是 Dify 里拖出来的流程图。记录痛点。是工具调用不稳定是记忆丢失还是并发不够针对痛点引入新装备。比如发现工具调用太乱就引入 MCP 统一管理发现每次对话都要重新解释业务背景就引入 mem0。这套思路下来你既不会浪费时间搭一堆用不上的模块也不会在出现问题时无从下手。7.3 最后一个小提醒我遇到过一个很常见的坑在同一个项目里同时接入了 Dify、LangChain、LangGraph还有好几个 MCP Server但谁都没对谁做版本兼容测试最后整个环境一团乱麻。开源的乐趣是自由组合但自由的前提是能复现。每个组件都记录好版本和配置最好用容器化方案统一管理出现问题才有退路。另外开源项目更新速度极快MCP 和 agent 相关项目更是如此一两个月不看文档API 都可能变。写代码的时候别对着过时的教程抄以 GitHub 仓库里的 README 和 examples 目录为准。这也是为什么我一直强调看项目推荐是用来“开眼界、指方向”的真正落地永远以官方文档为准。