ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AI Agent开发实战:从核心架构到最小代码实现

AI Agent开发实战:从核心架构到最小代码实现 每年都有人说“AI Agent 是下一个风口”但真正的问题从来不是“它火不火”而是作为开发者你能不能把 Agent 从概念变成能跑通、能上线、能产生实际价值的程序如果你最近在看 Agent 开发相关的内容大概率会刷到一大堆术语Function Calling、ReAct、记忆机制、多智能体协作、MCP……一个个单独查好像都能看懂组合在一起就不知道从哪里入手。尤其是网上的视频和文章常常分成两个极端要么只讲概念看完还是不会写代码要么直接丢给你一个大项目跑完也不明白每一层是干什么的。这篇教程的目标很直接带你把 AI Agent 的核心架构拆开然后用最小可运行的代码亲手搓一个能调用工具的 Agent。我会把“Agent 到底是什么”“为什么它和普通 API 调用有本质区别”“框架选型怎么选”“实际开发中有哪些坑”一次讲清楚。文章不要求你有很深的机器学习背景只要你写过 Python、理解 HTTP 请求和 JSON 基本结构就能沿着这条路径走下去。读完以后你会具备一套完整的 Agent 开发认知框架可以直接拿去做知识库问答、自动化办公、日志分析、客服机器人等真实场景。1. Agent 到底是什么先解决认知问题1.1 为什么“会调大模型”不等于“会做 Agent”很多人第一次接触 Agent会以为它就是一个“更聪明的聊天机器人”。这个理解不算全错但会严重限制你的开发思路。普通的大模型调用是单轮或连续多轮对话模型只负责“生成文本”它没有能力去读取数据库、调用外部 API、执行计算或写入文件。换句话说模型只是大脑不是身体。而 Agent 的核心特征是三点有目标用户可以给它一个任务比如“分析今天的日志文件并生成报告”。能使用工具它会调用搜索、数据库查询、SQL 执行、第三方 API 等能力。能自主决策模型会根据中间结果决定下一步做什么而不是每一步都由用户手动触发。如果还用“大脑和身体”的比喻Agent 就是给大脑接上了手和脚同时又给了它一张任务清单。它先制定计划然后一步步执行遇到缺失信息会自己决定去查什么工具最终交付一个完整结果。1.2 Agent 与传统代码、工作流引擎的区别为了更清楚我把常见的技术方案放在一起对比方案类型决策能力执行方式典型场景普通程序/API 调用完全由开发者写死顺序执行有明确分支订单系统、登录模块工作流引擎通过规则和状态机控制节点流转条件判断审批流、数据处理管道聊天机器人只生成回复对话式返回文本客服问答Agent由模型驱动动态规划自主调用工具、多步推理复杂任务编排、自动化分析这里的重点在于传统工作流是“流程固定数据变化”Agent 是“目标固定流程由模型动态生成”。这也是 Agent 最大的价值同时也是最大的难点——你无法提前枚举所有执行路径所以必须靠模型能力 完善的工具封装 足够的兜底机制来保障正确性。2. Agent 的核心架构四层必不可少如果你去网上搜“Agent 完整架构”会看到各种复杂的分层图。剥掉术语外壳绝大多数 Agent 系统都由下面四层组成模型层Model Layer负责推理、规划、生成。你可以用 OpenAI、Claude、国产大模型也可以本地部署。工具层Tools Layer把外部能力封装成模型可调用的接口比如天气查询、数据库查询、文件读写。记忆层Memory Layer保存短期上下文和长期知识解决“模型记不住”的问题。编排层Orchestration Layer决定模型什么时候调用工具、调用哪个工具、如何拼接结果、何时终止。这四个层次不是物理隔离的而是在代码里互相配合。你可以用 LangChain 这类框架直接组合也可以自己从零实现。2.1 记忆层短期记忆与长期知识很多 Agent 教程会回避记忆的细节但这恰恰是工程化时最容易出问题的地方。短期记忆就是当前对话的 messages 列表。模型只能记住你提供给它的上下文所以携带多少内容直接决定成本和效果。长期记忆通常用向量数据库存储例如 Chroma、Milvus、Elasticsearch。当用户提问时先从向量库检索相关片段再拼进提示词。这就是 RAG检索增强生成的基本思路。会话级记忆指某个用户多次任务之间的状态保存常用 Redis 或数据库实现。如果你打算做“AI Agent 通过 ES Rest API 智能分析日志”这类场景长期记忆层就是你的核心。因为一次对话里的历史日志不可能全部塞进模型上下文必须通过检索把最相关的部分取出来。2.2 工具层Agent 的“手和脚”工具层的核心设计原则是让模型知道你有哪些工具以及每个工具是做什么的。大模型本身不会主动调用任何东西它只会输出一段结构化指令你写的代码再去执行这个指令这个机制在 API 层面叫 Function Calling。工具层要解决的三个问题工具对外如何描述——需要给每个工具写名字、描述、参数结构。模型如何选择工具——靠描述文本和参数 schema 的语义匹配。工具结果如何返回给模型——执行完要把结果拼成 message 回到模型。这里需要提一下 MCPModel Context Protocol。它是一种标准化的工具接入协议本质是让工具提供商按照统一格式暴露能力避免每个 Agent 框架都重复造轮子。如果你只做一个私有项目不一定要上 MCP但如果你的 Agent 要接多种外部系统MCP 会显著降低接入成本。3. 环境准备与基础配置写 Agent 之前先把环境搭好。以 Python 为例这是 Agent 开发最主流的语言生态最完整。3.1 运行环境推荐Python 3.10 或 3.11建议用虚拟环境不要直接装在全局环境。操作系统不限Windows、macOS、Linux 都可以只是有些依赖在 Windows 上可能要多配几步。编辑器推荐 VS Code配好 Python 插件即可。3.2 安装依赖这里以 OpenAI SDK 为例做演示思路同样适用于 DeepSeek、Qwen 等兼容 OpenAI 接口的模型服务。建议先创建一个干净的虚拟环境python -m venv agent-demo source agent-demo/bin/activate # Windows 下是 agent-demo\Scripts\activate pip install openai python-dotenv然后准备一个.env文件保存 API Key避免把密钥写死在代码里# .env OPENAI_API_KEYsk-xxxxxxxxxxxxxxxx OPENAI_BASE_URLhttps://api.openai.com/v1 MODEL_NAMEgpt-4o-mini如果你使用的是国内兼容 OpenAI 协议的服务把OPENAI_BASE_URL换成对应地址即可。模型名称的实际取值以你调用的服务为准本文示例用MODEL_NAME统一引用方便替换。4. 第一个 Agent从一次普通的模型调用开始4.1 基础调用模型只会“说”不会“做”先写一个最小代码确认环境和模型能跑通。# 文件路径demo_01_basic.py import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client OpenAI( api_keyos.getenv(OPENAI_API_KEY), base_urlos.getenv(OPENAI_BASE_URL), ) def chat(prompt: str): resp client.chat.completions.create( modelos.getenv(MODEL_NAME), messages[ {role: system, content: 你是一个有帮助的助手。}, {role: user, content: prompt}, ], ) return resp.choices[0].message.content if __name__ __main__: print(chat(北京今天的天气适合出门吗))这个示例的问题很明显模型并不知道北京今天的天气。它只能基于训练数据生成一个“听起来合理但不一定真实”的回答。真正可靠的 Agent必须先拿到真实数据再回答用户问题。要做到这一点我们需要引入工具。4.2 定义工具让模型知道天气查询能力OpenAI SDK 支持tools参数我们按 JSON Schema 给模型描述一个“查询天气”的函数# 文件路径demo_02_tool_definition.py import json import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client OpenAI( api_keyos.getenv(OPENAI_API_KEY), base_urlos.getenv(OPENAI_BASE_URL), ) tools [ { type: function, function: { name: get_weather, description: 查询指定城市的实时天气适合回答任何与天气相关的问题。, parameters: { type: object, properties: { city: { type: string, description: 城市中文名例如北京、上海 } }, required: [city] } } } ] resp client.chat.completions.create( modelos.getenv(MODEL_NAME), messages[ {role: user, content: 北京今天天气怎么样} ], toolstools, tool_choiceauto, ) message resp.choices[0].message print(message)运行这段代码模型通常不会直接返回“北京今天晴天”而是返回一个tool_calls结构里面包含函数名get_weather和参数{city: 北京}。这一步是关键模型不是执行者它是调度者它告诉你“现在应该去调用哪个工具”。你需要在你的业务代码中自己实现get_weather然后把真实结果返回给模型。4.3 完整循环让模型看见工具执行结果接下来我们实现一个最小 Agent 循环模型生成工具调用指令 → 我们执行工具 → 把结果作为 tool message 返回 → 模型基于真实结果生成最终回答。# 文件路径demo_03_agent_loop.py import json import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client OpenAI( api_keyos.getenv(OPENAI_API_KEY), base_urlos.getenv(OPENAI_BASE_URL), ) # 1. 定义一个最简单的“伪天气接口”演示工具执行 def get_weather(city: str) - dict: # 真实项目中这里应该去调用天气服务 API fake_db { 北京: {temperature: 18, condition: 晴, wind: 2级}, 上海: {temperature: 22, condition: 多云, wind: 3级}, } return fake_db.get(city, {temperature: 未知, condition: 未知, wind: 未知}) # 2. 工具注册表把函数名映射到真实函数 TOOL_REGISTRY { get_weather: lambda args: get_weather(args[city]), } # 3. 工具描述给模型看 TOOL_DESCRIPTIONS [ { type: function, function: { name: get_weather, description: 查询指定城市的实时天气适合回答任何与天气相关的问题。, parameters: { type: object, properties: { city: { type: string, description: 城市中文名例如北京、上海 } }, required: [city] } } } ] def run_agent(user_input: str): messages [ {role: system, content: 你是可靠的小助手需要使用工具获取真实信息后再回答。}, {role: user, content: user_input}, ] # 设置最大循环次数避免死循环 for _ in range(5): resp client.chat.completions.create( modelos.getenv(MODEL_NAME), messagesmessages, toolsTOOL_DESCRIPTIONS, tool_choiceauto, ) message resp.choices[0].message # 如果模型没有要求调用工具说明已经得到最终答案 if not message.tool_calls: return message.content # 把模型的工具调用指令加入对话 messages.append(message) # 逐个执行工具调用并把结果返回给模型 for tool_call in message.tool_calls: func_name tool_call.function.name func_args json.loads(tool_call.function.arguments) print(f [tool] 调用 {func_name}({func_args})) result TOOL_REGISTRY[func_name](func_args) messages.append({ role: tool, tool_call_id: tool_call.id, content: json.dumps(result, ensure_asciiFalse), }) return 达到最大循环次数任务终止。 if __name__ __main__: answer run_agent(北京今天天气怎么样适合出门吗) print(answer)这段代码就是一个个最小可用 Agent 的完整骨架。核心逻辑只有四步将用户问题发送给模型。模型返回“完整回答”或“工具调用指令”。如果是工具调用执行工具把结果追加到消息列表。把新的消息再发给模型直到模型给出最终回答。不管你后续使用 LangChain、自定义框架还是更复杂的多智能体系统本质都是这个循环的扩展。先把这个循环吃透胜过背一百个工具框架的 API。5. 从最小示例走向生产级架构上面 20 多行代码只是玩具实际项目里你会遇到几个绕不开的问题上下文爆炸、工具返回格式不稳定、Agent 无限循环、成本失控。5.1 上下文管理如何让 Agent 记住该记的在最小循环里每轮工具结果都会追加进 messages。如果工具一次返回 10 万行日志你很快会超出模型上下文窗口并且费用暴涨。生产环境的常见做法结果截断只保留工具返回的前 N 个字符或前 N 条记录。摘要压缩用模型把长文本压缩成摘要再放回上下文。向量检索把日志或文档向量化先检索再拼接。滑动窗口只保留最近几轮消息更早的转成摘要信息。5.2 工具返回格式永远不要相信模型会完美解析 JSON模型可能不按你定义的参数结构输出甚至可能传错参数类型。工程上的约束手段是工具代码里必须做参数校验和默认值兜底。解析 JSON 时使用try/except失败时让 Agent 修正参数。给每个工具定义清晰的错误返回格式比如{error: city not found}让模型知道下一步该怎么办。错误处理的原则是工具永远不要抛异常中断整个 Agent而是把错误信息返回给模型让模型决定如何修复。5.3 循环控制给 Agent 系上安全绳模型在复杂任务中完全可能反复调用同一个工具或者陷入无意义的死循环。生产环境至少要加三把锁最大迭代次数限制。单次任务超时时间。连续相同工具调用的次数限制。6. Agent 与 Skill 的区别别再搞混了在 Agent 社区尤其是 Hugging Face 相关的讨论里经常出现Agent和Skill两个词。不少人把二者混为一谈但它们的层级完全不同。Skill 是可复用的单一能力单元。它封装了一个明确的技能比如“发送邮件”“解析 PDF”“查询天气”。Skill 通常不包含复杂的决策链路更像是一个经过标准化封装的函数。你写一个 get_weather 并配上清晰的描述和参数 Schema就可以称为一个 Skill。Agent 是围绕目标组织多种 Skill 的决策执行体。它负责理解任务、拆解步骤、按需调用 Skill、观察结果、判断是否完成任务。一句话总结Agent 是导演Skill 是演员Agent 负责调度Skill 负责执行。一个有经验的 Agent 开发者一定会花大量时间打磨 Skill 的边界、描述和异常处理因为模型能不能正确选到工具很大程度上取决于工具描述写得好不好。7. 框架与平台选型不做选择就会踩坑现在 Agent 开发框架非常多新同学最容易陷入“教程用哪个我就用哪个”的盲从。我的建议是先了解主流方案再根据自己的场景决策。框架/平台定位适合场景学习成本说明LangChain开发框架组合模型、工具、记忆的复杂应用中等生态最大抽象多适合理解 Agent 全流程LlamaIndex数据/RAG 框架知识库问答、文档检索中低对检索增强场景支持更好AutoGen多智能体框架多角色协作、任务分解较高适合研究多 Agent 协作CrewAI多智能体框架角色化团队协作中等更贴近“团队分工”模型Dify / 扣子低代码平台快速搭建业务 Agent低适合非深度定制场景和快速验证选型建议如果你目标是理解原理建议先用本文的方式自己从零实现一遍循环再接触框架。如果你目标是快速交付一个内部工具用 Dify 或扣子这类平台效率最高。如果你目标是深度定制、与现有 Java/Go 核心系统集成则要认真评估 LangChain 的抽象是否符合你的架构有时自己维护一套轻量 Agent 循环反而更可控。值得留意的趋势是2026 年模型具备原生流程编排能力的说法越来越多但对于开发者核心技能仍然集中在工具封装、数据接入、评测和运维监控上。框架可以换这套工程能力不会过时。8. Agent 开发常见问题与排查思路新手写 Agent 时遇到的问题高度集中大多数不是模型不行而是工程处理不到位。下面列一份高频排查表。问题现象可能原因排查方式解决方案模型不调用工具工具描述不清晰或模型不支持 Function Calling查看 API 返回 message 里是否有 tool_calls重写描述明确“什么时候用”换支持工具调用的模型工具执行后模型还重复调用上下文中缺少工具结果或结果格式不对打印 messages 查看 role 和 tool_call_id确认 tool message 的 role 为 tool且 tool_call_id 与请求一致JSON 解析报错模型返回了多余文字或格式错误打印原始 tool_call.function.arguments用正则提取 JSON 片段增加 try/except回答内容与现实不符模型没拿到真实数据或工具结果未被利用检查最终一轮 messages 是否包含 tool 结果限制模型在无工具结果时必须继续调用/明确说不知道上下文太长费用暴涨把大文本直接拼入 messages检查 messages 长度和 token 用量加截断、摘要、向量检索Agent 死循环缺少最大迭代限制查看日志中工具调用次数加次数限制与超时控制工具内部异常导致回答中断工具抛出了未捕获异常查看异常堆栈改为返回 error 形式的结构化结果排错时最核心的意识是不要黑盒猜测把每一轮 messages 完整打印出来Agent 的行为逻辑一目了然。9. 5天学习路线从零到能接需求下面是针对“零基础到能开发 Agent 项目”的 5 天实践路线配合本文前面的内容可以快速跑通。第 1 天跑通最小闭环。目标是理解模型调用、工具定义和 Agent 循环。完成本文第 4 节的代码并尝试把get_weather替换成一个自己的工具比如查询本机文件列表。第 2 天掌握记忆与 RAG。学会用向量数据库存文档实现一个“基于公司知识库回答问题”的 Agent。重点理解检索召回和上下文拼接。第 3 天封装真实业务工具。选择一个你工作里高频的操作比如查询订单状态、读取日志、调用内部接口把它封装成 Agent 工具。这一步要重点关注鉴权、超时和错误返回。第 4 天做一个完整项目。推荐从“日志智能诊断”或“客服问答机器人”入手。明确用户的输入输出格式、工具边界、失败兜底形成一个小型可交付 demo。第 5 天评估与优化。建立测试集逐条跑 Agent记录成功率和失败原因再迭代工具描述、提示词和错误处理逻辑。这里有一个经常出现的误区学 Agent 不是背 API而是练“把任务拆成工具 决策”的思维方式。每天必须动手写代码只看视频和文章不会有明显进步。10. 工程化最佳实践与安全边界最后这部分是你在教程和 Demo 里不太容易看到、但在生产环境非常关键的内容。10.1 日志与可观测性Agent 是动态决策系统你不可能靠“猜”排查线上问题。至少要做到记录每一轮用户输入、模型输出、工具调用、工具结果。为每次任务分配 Trace ID串联整个执行链路。记录 token 消耗和耗时方便做成本分析。10.2 安全边界与最小权限Agent 能调用工具就意味着它能执行操作。生产环境必须遵守最小权限原则给 Agent 的 API Key 只能访问它必需的资源不要直接使用管理员凭证。高风险操作加人工确认涉及删除、修改、支付、对外发送消息等操作建议先让 Agent 生成操作方案由人工确认后再执行。数据脱敏日志分析和知识库问答中避免把敏感字段直接塞进模型上下文。输入校验用户的输入可能诱导 Agent 执行非预期工具调用。必要时加一层输入防火墙限制工具可接收的参数范围。10.3 测试与回归Agent 的输出有随机性因此测试不能只靠“看一次结果”。建议建立小型评估集例如 20 个典型问题每次修改提示词或工具后全部重跑一遍统计回答正确率、工具调用正确率。这个流程虽然朴素却是防止 Agent 效果“越改越差”的有效手段。10.4 保持“人在环路”即使模型能力再强也不要让 Agent 在无人监督的情况下完成全自动的破坏性操作。比较稳妥的做法是Agent 负责信息收集和方案拟定关键决策由人来做。稳妥的业务设计比追求炫技更重要。11. 总结这篇文章从“Agent 到底是什么”讲到了最小代码实现、生产级架构、框架选型和工程化安全边界。最重要的收获不是某一段代码而是那个完整的认知链路模型是大脑工具是手脚记忆是笔记本编排是工作流而安全与可观测性是生产环境的地基。第一次写 Agent不必急着上复杂框架。建议你把本文第 4 节的代码改成自己的场景哪怕只是一个“查询天气”的小工具跑通之后再逐步加入记忆、检索和多工具协作。等你亲手经历过“模型调用工具 → 工具返回 → 模型给出答案”的过程再看任何 Agent 框架的文档都会轻松很多。下一步可以重点研究 RAG、MCP 工具接入规范和 Multi-Agent 协作模式这三个方向是 Agent 走向真实业务的核心路径。如果在实践过程中遇到问题欢迎在评论区把你的错误日志贴出来一起讨论。建议收藏这篇文章动手写第一行代码时随时回来对照。
返回列表