
在 2026 年再看 AI 应用开发Agent 已经不再是简历上的加分项而是很多业务项目的标配能力。本文不打算铺开讲大模型原理而是围绕“如何从零搭建一个真正能跑起来的自定义智能体”这条主线把 Agent 的运行逻辑、LLM 的核心作用、工具调用机制、RAG 知识库增强以及工程化落地的常见问题串起来讲。适合刚接触 Agent 的初学者也适合想系统梳理大模型开发体系的进阶读者。1. AI Agent 为什么会成为大模型应用的核心形态1.1 什么是 AI AgentAI Agent中文通常翻译为“智能体”可以简单理解为一个“会自己规划、自己做决定、自己动手干活”的 AI 程序。它不只是回答你的问题而是把大模型当作决策大脑通过调用外部工具去完成实际任务。举个例子你问普通聊天机器人“帮我看看杭州明天适合穿什么衣服”它可能只会给出泛泛的穿衣建议。但如果是一个 AI Agent它可以先调用天气查询工具获取城市天气再调用定位工具确认你的地理位置然后结合大模型的分析能力给出具体建议。整个过程不是一次问答而是多个步骤的循环。从专业角度来说AI Agent 是一个以 LLM 为核心控制器通过任务规划、记忆管理、工具调用等方式在复杂环境中自主完成目标的系统。它的核心组成部分包括感知、规划、行动、记忆这四个模块。1.2 AI Agent 与普通 Chatbot 的区别很多初学者会把 Agent 和聊天机器人混为一谈实际上两者有几个明显区别交互方式不同Chatbot 是“你问我答”Agent 是“你提出目标我拆解执行”。能力边界不同Chatbot 只能基于训练数据回答Agent 可以接入实时数据、业务系统、第三方 API。决策能力不同Chatbot 每次回答相对独立Agent 会进行多步推理过程中可能有观察、反思、调整。记忆能力不同Chatbot 通常只保存对话历史Agent 需要区分短期记忆和长期记忆并能从记忆库中检索历史经验。也就是说判断一个系统是不是 Agent关键是看它是否具备“感知环境 - 做出决策 - 执行动作 - 观察结果 - 再次决策”的闭环能力。1.3 Agent 的核心能力拆解我在学习 Agent 开发时习惯把它的能力拆成五块任务理解能力把用户模糊的诉求拆解成可执行的任务这是 Prompt 工程要解决的核心问题。规划能力制定执行步骤比如先查资料再写代码遇到问题能调整方案。工具调用能力通过函数调用或插件机制使用外部工具这是 Agent 真正能“干活”的关键。记忆能力会话内记住上下文跨会话保留用户偏好和历史结果。自我反思能力对执行结果进行评估发现失败后自动重试或更换方案。后面我们会围绕这些能力动手实现一个简化但完整的 Agent。2. LLM 在 Agent 体系中的核心地位2.1 LLM 的工作原理速览LLMLarge Language Model大语言模型本质上是基于海量文本训练出来的概率模型。它根据输入的 Token 序列逐步预测下一个最可能出现的 Token。这里需要特别强调一点LLM 不是数据库它不具备确定性查询能力它是在“生成”。举个例子你问“中国的首都是哪里”模型并不是从某个表格里查到了“北京”而是因为它在大规模语料中学到了“中国首都”和“北京”之间的关联概率。这意味着 LLM 的回答存在不确定性同一个问题在不同时间和参数设置下可能得到不同结果。在实际开发中这种概率生成特性会带来两个影响一是 Agent 的决策路径不固定需要设计好兜底逻辑二是关键业务场景需要引入确定性校验不能完全依赖模型输出格式。2.2 Agent 为什么离不开 LLMAgent 并不是新概念早在 20 世纪 80 年代人工智能领域就开始研究智能体但一直没能在工程领域大规模落地。直到大模型出现Agent 才有了一个真正强大的“大脑”。传统的规则型 Agent 需要开发者把每一种情况都写成 if-else 分支遇到稍微复杂的任务就难以维护。而基于 LLM 的 Agent 可以直接理解自然语言指令把“今天下午三点提醒我给客户回电话”这种没有固定格式的输入解析成结构化任务再触发定时器工具。可以说 LLM 给 Agent 带来的核心能力是常识理解、语义解析、任务分解和内容生成。这也是为什么现在提到 Agent 开发几乎默认就是大模型 Agent 开发。2.3 从 LLM 到 Agent缺少的环节是什么单独一个大模型 API 并不能称为 Agent两者之间还缺三个重要环节记忆缺失LLM 本身没有记忆需要开发者自己管理上下文。这也是很多 Agent 上下文窗口为什么会超限的原因。工具缺失LLM 只能输出文本不能直接查数据库、发请求、操作文件必须通过工具调用扩展能力边界。规划缺失LLM 默认是“一次生成”而 Agent 需要“多轮决策”这需要设计循环机制。所以从代码角度看LLM 只是 Agent 里的一个模型调用节点真正的工作量在于如何组织规划逻辑、如何设计工具协议、如何管理记忆状态。后面的实战部分我们会把这些点逐一落地。3. Agent 的运行逻辑规划、记忆与工具调用3.1 ReAct 模式Agent 的核心推理框架在 Agent 的众多实现模式中ReAct 是目前最常用也最容易上手的一种。ReAct 的全称是 Reasoning Acting也就是推理和行动交替进行。它的运行循环可以用这样一段伪代码表示用户输入目标。LLM 基于当前状态进行推理决定下一步行动。Agent 执行行动可能是调用某个工具。工具返回观察结果。LLM 根据观察结果继续推理。循环往复直到 LLM 认为任务完成输出最终答案。这种方式的优势在于每一步决策都有推理依据出现问题时可以通过观察结果调整方向而不是一条路走到黑。我们现在看到的大多数 Agent 框架底层都在使用类似 ReAct 的思路。3.2 Agent 的记忆体系记忆是 Agent 能否从“Demo”走向“可用”的关键。我们可以把 Agent 的记忆分成两层短期记忆指当前对话上下文通常缓存在内存中。主流实现方式是维护一个消息列表每次请求时把历史消息全部发给模型。长期记忆指跨会话存储的信息比如用户的偏好、历史任务结果。一般需要借助外部存储比如向量数据库。长期记忆的读取并不是全量读取而是采用“检索 注入”的方式。当用户提出新任务时Agent 先从长期记忆中检索相关片段再注入到提示词中供模型参考。这一步在很多系统里会和 RAG 技术结合使用。3.3 工具调用的两种实现方式工具调用是 Agent 区别于普通 Chatbot 的重要分水岭。目前主流的实现方式有两种第一种是模型原生支持函数调用也就是 Function Calling。开发者在请求中声明工具列表模型根据用户意图返回一个结构化的函数调用指令。这种方式解析稳定是当前最推荐的方式。第二种是让模型输出特定格式的文本指令然后由正则表达式或代码解析。这种方式兼容旧模型但稳定性较差新手容易踩坑。在后面的实战案例中我会以第一种方式为例演示如何让模型自主决定是否需要调用工具以及如何执行工具并把结果反馈给模型。4. 环境准备与项目结构4.1 运行环境说明在开始写代码之前先说明一下环境。本文示例选择 Python 作为开发语言因为当前大模型生态对 Python 支持最完善多数框架和示例代码都以 Python 为主。具体环境要求如下操作系统Windows 10/11、macOS、Linux 均可。Python 版本建议 3.10 或以上本文示例在 3.10 环境下测试通过。大模型 API需要准备一个兼容 OpenAI 接口的 API Key常见选择包括 OpenAI、DeepSeek、通义千问、Kimi 等。包管理工具pip。需要提醒的是不同厂商的模型在参数和接口细节上会有些许差异本文代码以兼容 OpenAI 接口的服务为准如果你用的是其他服务需要根据官方文档调整 base_url 和模型名称。4.2 安装依赖我们需要安装 openai 库它是调用大模型接口的基础依赖。在命令行执行pip install openai如果你的网络环境中安装速度较慢可以使用国内镜像源pip install openai -i https://pypi.tuna.tsinghua.edu.cn/simple安装完成之后可以用下面的代码验证环境是否正常import openai print(openai.__version__)只要能正常输出版本号说明环境已经准备就绪。如果后续接入向量数据库做 RAG我们还会安装额外的依赖库到时再单独说明。4.3 项目结构规划为了避免代码越写越乱我们先规划一个清晰的项目结构。这里采用一个小型但规范的目录布局agent_demo/ ├── tools.py # 工具定义 ├── agent.py # Agent 核心逻辑 ├── memory.py # 对话记忆管理 ├── config.py # 配置文件 ├── requirements.txt # 依赖清单 └── main.py # 入口文件这样的好处是工具层、调度层、入口层分离后续扩展新工具或更换模型时不需要改动整体框架。5. 从零搭建一个自定义智能体5.1 定义目标场景为了让教程更贴近实际业务我们设计一个非常典型的场景构建一个“个人信息助理智能体”。它需要具备以下能力查询指定城市的当前天气。执行简单的计算比如计算两个日期之间相隔多少天。当用户提出闲聊话题时能正常进行对话。通过这个场景我们可以在一个项目中同时覆盖对话、工具调用、多轮记忆三个核心功能而不会引入过多的业务复杂度。5.2 编写工具层工具层是 Agent 能力扩展的基础。在 tools.py 文件中我们定义两个工具函数。# 文件路径agent_demo/tools.py import datetime import json def get_weather(city: str) - str: 查询指定城市的天气。 这是一个模拟工具真实项目中可以替换为天气 API 调用。 # 这里用静态数据模拟天气返回结果 weather_data { 北京: 晴25 摄氏度微风, 上海: 多云28 摄氏度东南风 3 级, 杭州: 小雨22 摄氏度北风 2 级, } result weather_data.get(city, f暂未收录 {city} 的天气数据) return json.dumps({city: city, weather: result}, ensure_asciiFalse) def days_between(start_date: str, end_date: str) - str: 计算两个日期之间相差的天数。 日期格式为 YYYY-MM-DD。 date_format %Y-%m-%d start datetime.datetime.strptime(start_date, date_format) end datetime.datetime.strptime(end_date, date_format) days abs((end - start).days) return json.dumps({days_between: days})这里做两点说明。第一天气查询是模拟数据实际开发时应替换成真实的气象 API 或内部服务。第二工具函数的返回值统一使用 JSON 字符串这样格式清晰也方便模型理解工具执行结果。接下来定义工具注册表把工具的名称、函数、参数说明集中管理起来# 文件路径agent_demo/tools.py追加内容 class ToolRegistry: def __init__(self): self.tools {} def register(self, name, func, description, parameters): self.tools[name] { name: name, func: func, description: description, parameters: parameters, } def call_tool(self, name: str, arguments: dict): tool self.tools.get(name) if not tool: raise ValueError(f工具 {name} 不存在) return tool[func](**arguments) def to_openai_tools_format(self): 将工具转换为 OpenAI Function Calling 需要的格式。 tools [] for name, tool in self.tools.items(): tools.append({ type: function, function: { name: name, description: tool[description], parameters: tool[parameters], }, }) return tools # 全局工具注册中心 tool_registry ToolRegistry() tool_registry.register( nameget_weather, funcget_weather, description查询一个城市的当前天气情况, parameters{ type: object, properties: { city: {type: string, description: 城市名称比如北京、上海} }, required: [city], }, ) tool_registry.register( namedays_between, funcdays_between, description计算两个日期之间相差的天数, parameters{ type: object, properties: { start_date: {type: string, description: 开始日期格式 YYYY-MM-DD}, end_date: {type: string, description: 结束日期格式 YYYY-MM-DD}, }, required: [start_date, end_date], }, )5.3 编写 Agent 核心调度逻辑Agent 的核心逻辑在 agent.py 中实现。它的工作流程是拼接系统提示词和对话历史。调用大模型接口并传入工具列表。判断模型的返回结果是否包含工具调用请求。如果包含执行对应工具并把工具结果作为新的消息传给模型。循环调用直到模型输出最终答案。# 文件路径agent_demo/agent.py import json from openai import OpenAI from tools import tool_registry SYSTEM_PROMPT 你是一个智能的个人助理你通过与用户对话来帮助用户解决问题。 你可以使用以下工具 1. get_weather查询天气 2. days_between计算日期相差天数 当用户的问题需要工具时请调用工具获取真实数据不要凭空编造。 当不需要调用工具时可以直接回复用户。 在获得工具返回结果之后请根据结果组织你的回答。 class Agent: def __init__(self, api_key: str, base_url: str, model: str): self.client OpenAI(api_keyapi_key, base_urlbase_url) self.model model self.messages [ {role: system, content: SYSTEM_PROMPT} ] def run(self, user_input: str, max_steps: int 5): 运行 Agent 主循环。 max_steps 用于限制工具调用轮数防止死循环。 self.messages.append({role: user, content: user_input}) for step in range(max_steps): response self.client.chat.completions.create( modelself.model, messagesself.messages, toolstool_registry.to_openai_tools_format(), tool_choiceauto, ) message response.choices[0].message # 如果模型没有要求调用工具说明可以输出最终答案 if not message.tool_calls: final_answer message.content self.messages.append({role: assistant, content: final_answer}) return final_answer # 将带工具调用的消息追加到历史 self.messages.append(message) # 依次执行工具 for tool_call in message.tool_calls: tool_name tool_call.function.name tool_args json.loads(tool_call.function.arguments) print(f[执行工具] {tool_name}参数{tool_args}) result tool_registry.call_tool(tool_name, tool_args) self.messages.append({ role: tool, tool_call_id: tool_call.id, content: result, }) # 达到最大步数仍未结束返回提示信息 return 处理超时请缩小问题范围后重试。这段代码里有几个重要细节值得展开说明。第一max_steps是防止死循环的关键设计。如果 Agent 多次调用工具后仍然无法得出最终答案程序会强制退出避免消耗过多 Token。生产环境中这个值可以根据任务复杂程度调整但一般不建议设置得过大。第二工具执行结果通过tool角色的消息返回给模型。这个角色是 OpenAI Function Calling 协议要求的标准字段目的是让模型知道工具调用后的真实结果。第三tool_choiceauto表示由模型自主决定是否调用工具。如果你希望模型必须调用某个工具可以显式指定工具名称。5.4 编写入口文件和配置文件为了方便管理 API 配置我们单独写一个 config.py。# 文件路径agent_demo/config.py import os API_KEY os.getenv(LLM_API_KEY, 你的 API Key) BASE_URL os.getenv(LLM_BASE_URL, https://api.openai.com/v1) MODEL os.getenv(LLM_MODEL, gpt-4o-mini)需要注意的是这里读取环境变量的方式方便在部署时动态配置。如果你使用的是兼容 OpenAI 接口的国内模型服务只需要修改 BASE_URL 和 MODEL 两个变量即可。接下来是 main.py用于命令行交互测试。# 文件路径agent_demo/main.py from agent import Agent from config import API_KEY, BASE_URL, MODEL def main(): agent Agent(api_keyAPI_KEY, base_urlBASE_URL, modelMODEL) print(个人助理已启动输入 exit 退出。) while True: user_input input(你) if user_input.lower() in [exit, quit]: print(再见) break answer agent.run(user_input) print(f助手{answer}) print() if __name__ __main__: main()5.5 运行与验证在项目目录下执行python main.py程序启动后可以尝试以下测试用例你北京今天天气怎么样正常情况下Agent 会判断出“查询天气”需要调用工具于是先输出一行[执行工具] get_weather日志再给出最终回答助手北京今天晴25 摄氏度微风。再测试一个日期计算你帮我算一下从 2026-01-01 到 2026-03-15 有多少天这个案例会触发days_between工具如果结果正确说明 Agent 的工具调用链路已经跑通。为了验证记忆能力还可以连续提问你我叫小明。 助手你好小明很高兴认识你 你我叫什么名字如果 Agent 能说出“小明”说明对话历史在消息列表中被成功维护。5.6 结果与预期效果到此为止一个最小的自定义 Agent 已经能够完成天气查询、日期计算、多轮对话三个功能。你可以在 tools.py 中继续注册新的工具比如查询今日汇率调用搜索 API 获取最新资讯查询企业内部的订单信息每增加一个工具只需要写一个普通函数并注册到 ToolRegistry 中核心调度逻辑无需改动。这就是工具注册表设计带来的好处。6. 高频报错与排查思路在 Agent 开发过程中遇到报错是常态。这里整理几个我在学习和实践中遇到过的高频问题供大家参考。6.1 常见问题汇总表问题现象常见原因解决思路模型报错tool_calls参数不支持模型不支持 Function Calling更换支持工具调用的模型或使用提示词解析方案工具调用后模型仍给不出结果工具返回内容格式不清晰统一使用 JSON 字符串返回内容要简洁对话轮次多了之后报上下文超限消息列表过长对历史消息做截断或摘要压缩LLM 请求超时网络波动或模型响应时间过长设置合理超时时间并增加重试机制Agent 死循环一直调用同一个工具缺少终止条件增加最大迭代轮次或增加结果校验逻辑返回结果被截断模型输出 Token 上限不够调整max_tokens参数6.2 工具调用失败的排查路径如果你发现模型调用了工具但 Agent 最终没有得到正确结果可以按下面的顺序排查确认工具函数本身能正常运行。单独写一个测试脚本调用该函数排除代码 bug。确认工具返回的 JSON 能被json.loads正确解析。确认tool_call_id与tool角色的消息一一对应。检查模型返回的arguments中字段名是否与函数参数保持一致。6.3 上下文超限的应对策略上下文超限可以说是 Agent 开发中最高频的问题之一。短对话场景下问题不明显一旦进入多轮工具调用消息列表会快速增长。一个实用的处理策略是只保留最近的 N 轮对话更早的内容用摘要代替。工具返回内容如果过长先做截断只保留关键字段。使用量化或检索的方式从历史消息中提取与当前任务相关的部分。具体实现时可以在 Agent 的run方法中增加一个trim_history方法对消息列表进行裁剪。7. Agent 开发的最佳实践与工程建议7.1 提示词设计给 Agent 明确的边界系统提示词决定了 Agent 的行为边界。一个合格的系统提示词至少包含以下内容角色定位你是谁服务于什么场景。能力边界你能做什么不能做什么。工具使用规则什么情况必须调用工具什么情况可以直接回答。输出规范回答要简明还是详细是否要求结构化输出。尤其要注意的是明确告诉 Agent“不要编造工具结果”。在实际项目中我发现如果不加这句限定模型在工具调用失败后经常会“脑补”一个结果这对业务系统来说是非常危险的。7.2 工具命名与参数设计规范工具是 Agent 与外部世界交互的桥梁规范命名能显著提升模型识别准确率。工具名称使用小写字母加下划线例如get_weather、query_order_status。参数名要自解释避免使用 a、b、c 这类无意义简写。参数数量控制在 5 个以内过多参数会让模型出现错误填充。所有参数都提供 description模型会参考描述来理解参数含义。7.3 安全与权限控制Agent 拥有工具调用能力后安全边界问题变得特别重要。在接生产环境之前至少要做好以下几件事所有工具调用必须做权限校验不能因为模型说出某个指令就直接执行危险操作。涉及数据库操作、文件删除、资金变动等敏感动作必须加人工确认环节。对工具调用参数做白名单校验比如查询订单时必须校验订单号格式。在测试环境中做完整的异常注入测试确认 Agent 在异常输入下不会执行非预期操作。这些原则听起来简单但在实际项目中是最容易被忽视的环节还是希望大家重视起来。7.4 日志与可观测性Agent 链路比传统接口复杂很多一个完整请求可能涉及多次模型调用、多次工具调用。没有日志排错会非常痛苦。建议在关键节点打印日志用户输入模型最终决策工具调用名称与参数工具返回结果最终回答如果条件允许可以把这些日志存储到独立的日志系统并给每次请求生成一个request_id方便全链路追踪。7.5 从 Demo 到生产还需要考虑什么本文的示例是一个迷你 Agent距离生产环境还有一段距离。如果要在业务中落地还需要考虑异步任务处理长耗时任务建议使用消息队列而不是同步等待。模型路由简单任务用小模型复杂任务用大模型降低成本。缓存策略相同问题在缓存有效期内直接复用结果。评估体系建立 Agent 的自动评测集每次提示词或工具调整后要回归测试。其中评估体系是目前企业落地 Agent 时最缺少的一环。如果没有可量化的评测集很难判断一个改动到底是变好了还是变差了。8. 用 RAG 给 Agent 注入私有知识8.1 为什么 Agent 需要 RAG大模型的训练数据存在截止时间而且不包含企业私有知识。比如你公司的内部规章制度、产品操作手册模型是完全不知道的。RAGRetrieval-Augmented Generation检索增强生成就是为了解决这个问题先从知识库中检索出相关内容再把检索结果注入提示词让模型基于这些材料回答。在 Agent 体系中RAG 通常是作为一个检索工具存在的。Agent 收到用户问题后判断是否涉及私有知识如果是就调用“知识库检索”工具获取相关内容再结合上下文生成答案。8.2 一个最小可用的 RAG 链路一个完整的 RAG 链路包括四个环节文档加载读取本地文本、PDF、Markdown 等格式的文档。文本切分把长文档切分成固定长度的段落并保留一定重叠。向量化调用 Embedding 模型把文本转换为向量。相似度检索把用户问题向量化在向量数据库中查找最相似的文本片段。向量数据库方面常用的选择有 Chroma、Milvus、Weaviate、FAISS 等。以 FAISS 为例安装命令如下pip install faiss-cpu sentence-transformers一个最小示例代码如下from sentence_transformers import SentenceTransformer import faiss import numpy as np # 加载 embedding 模型 model SentenceTransformer(BAAI/bge-small-zh-v1.5) # 示例知识文本 docs [ 公司年假政策入职满一年可享受5天年假。, 公司加班申请流程需提前一天在OA系统提交申请。, 公司产品支持导出PDF和CSV格式报表。, ] # 生成向量 doc_vectors model.encode(docs) # 构建索引 dimension doc_vectors.shape[1] index faiss.IndexFlatIP(dimension) index.add(np.array(doc_vectors).astype(float32)) # 查询 question 我怎么申请加班 question_vector model.encode([question]) # 检索最相似的1条 distances, indices index.search(np.array(question_vector).astype(float32), 1) print(最相关内容, docs[indices[0][0]])8.3 RAG 与 Agent 的结合方式在实际的 Agent 项目中你可以把“知识库检索”封装成一个工具注册到 ToolRegistry 中。这样 Agent 就能在需要时调用检索工具从而把模型本身的通用知识与企业的私有知识结合起来。这里需要提醒的是RAG 的效果很大程度上取决于文档切片质量和检索召回率。切分过大检索结果不够精准切分过小可能丢失上下文信息。建议先对不同文档类型做切分实验再结合评测指标调整。9. 给想要深入 Agent 开发的你如果你看完本文想继续深入我建议不要急着学习各种复杂框架而是先把这个最小 Agent 反复跑熟理解它的运行循环。在此基础上再去看 LangChain、Dify、Coze 等框架或平台你会发现它们本质上都是对这个循环做了工程化封装。下一阶段可以重点关注三个方向多工具协同设计复杂任务让 Agent 自选工具并串联执行。多智能体协作把一个大型任务拆分给多个专注的 Agent让它们互相配合。评估与调优搭建一套评测集持续优化提示词、工具描述和模型选择。这中间最大的乐趣在于你可以不断观察模型在工具调用过程中的“思考过程”然后通过调整提示词和工具设计让整个系统变得更加可靠。动手把今天的示例代码跑起来你会对 Agent 的运行逻辑有更实在的理解。