AI Agent智能体开发实战:从核心原理到可运行代码
发布时间:2026/9/29 14:58:50来源:尧图网络
最近两年AI Agent 智能体开发成了大模型应用落地最热的方向。很多人在 B 站、知识星球、GitHub 上收藏了各种教程但真正动手时往往发现概念翻来覆去就那几个代码却对不上自己本地环境或者跑通了 demo 却不知道下一步该学什么。这篇文章不再重复“AI 改变世界”这类套话而是把 AI Agent 智能体开发这条路径完整拆开从核心概念到环境准备再带着你从零写一个可运行的 Agent 项目最后补充工程落地和常见坑点。零基础但有 Python 基础或者做过 Web 后端开发的读者按文中的步骤走完基本能独立搭建一个带工具调用能力的 Agent 应用。1. 背景与核心概念1.1 什么是 AI Agent 智能体先给一个直白解释AI Agent 是一个能独立思考、拆解任务、调用工具并且通过多轮推理来达成目标的程序实体。它和普通聊天机器人最大的区别在于传统 Chatbot 是“你问一句它答一句”而 Agent 是自己判断下一步该做什么。比如你告诉它“帮我查一下最近一周的订单数据然后写一份分析报告并发邮件给团队”Agent 会自己决定先查数据库或 API 获取订单数据对数据做筛选、统计、生成分析结论调用报告生成模板调用邮件服务完成发送。这个过程中每一步都由大模型作为“大脑”来决策而具体的数据获取、文件读写、网络请求则由外部工具完成。术语上这种模式常被称为 ReActReasoning Acting也就是推理和行动交替进行。从专业定义来看AI Agent 通常由四个核心模块组成大语言模型LLM负责理解指令、生成推理过程、决定调用哪个工具记忆Memory分为短期记忆和长期记忆用于保存当前会话上下文和历史经验规划Planning把复杂任务拆分成多个子步骤并安排执行顺序工具调用Tool Use通过调用既定函数、API、数据库或外部系统来获取信息、执行动作。这四个模块在后面实战部分会一一体现。理解 Agent 的关键不是背概念而是明确它和普通函数调用的区别普通程序是人为写死逻辑Agent 是由大模型动态生成逻辑路径再交给执行器去跑。1.2 Agent 解决什么问题传统软件开发最典型的痛点是把复杂业务拆成大量条件判断。比如一个客服工单系统可能要写“如果用户说卡顿就判断网络问题如果用户说登录不了就判断账号问题”这种规则越写越多维护成本越来越高而且无法覆盖长尾场景。Agent 的思路是不预先枚举所有分支而是让模型根据当前输入自行推理。所以 Agent 的常见应用场景有自动运维接收告警信息自动查询日志、对比指标、执行脚本数据分析助手用自然语言提问Agent 自动生成 SQL、执行查询、总结结果个人知识库问答检索文档片段再结合模型生成答案自动化工作流邮件整理、周报汇总、会议纪要分发。对于开发者来说掌握 Agent 开发意味着多了一种构建应用的方式不再只是写死接口逻辑而是要设计“工具集 提示词 大模型调度”的结构。1.3 学习 AI Agent 需要哪些前置基础这是很多初学者容易焦虑的地方。坦率地说AI Agent 开发不需要你懂深度学习的数学原理也不需要从零训练模型。它更像一个工程集成问题。建议掌握的基础如下Python 基础能写函数、类会处理 JSON 和 requests 调用至少调用过一次大模型 API了解 System Prompt、User Prompt、Completion 的基本概念了解 HTTP API 的基本格式因为在开发过程中会频繁调试工具调用接口如果能写简单的 SQL 查询或者会读基础日志后续做真实场景项目会更顺手。如果你只有前端经验没有 Python 基础建议先用一周时间补齐 Python 基础语法。Agent 框架大量基于 Python 生态硬换语言会绕很多弯路。2. 环境准备与工具链2.1 开发环境版本说明版本需要根据你的项目实际情况调整本文示例以常见环境为例重点演示配置思路。基础环境建议如下组件建议配置说明操作系统Windows 10/11、macOS、Linux 均可代码以跨平台为主Windows 注意路径分隔符Python3.10 或更高版本推荐 3.10更好地支持类型注解和异步IDEVS Code 或 PyCharm不强求顺手即可大模型 APIOpenAI 兼容接口、阿里云百炼、DeepSeek 等示例代码使用 OpenAI 兼容格式可按实际平台替换依赖管理pip requirements.txt简单直接适合教程演示需要注意一点示例代码中会使用openai库、langchain库的可选功能。这两个库版本更新很快接口变化频繁。本文代码按常见稳定写法展示假如你本地跑不通优先检查库版本再对照官方文档调整参数格式。2.2 大模型服务选择国内开发者可以直接使用 OpenAI 兼容格式的各种平台服务也可以是模型厂商提供的 SDK。整体调用方式都差不多只是base_url、api_key和模型名称不同。这里给一个通用选择建议如果只是学习可以用价格较低的模型例如 DeepSeek、通义千问等如果做中文场景优先选中文理解能力好的模型如果需要调用工具Tool Call务必确认所选模型具备 Function Calling 能力企业项目还要看是否有私有化部署要求如果数据不能出内网需要使用开源模型 本地推理框架如 vLLM、Ollama。在实战代码中我们会写一个统一的提示词、工具定义和 API 调用逻辑尽量做到“换模型只改配置”。2.3 安装 Python 依赖先创建一个虚拟目录避免依赖冲突mkdir ai-agent-tutorial cd ai-agent-tutorial python -m venv venv激活虚拟环境# Windows venv\Scripts\activate # macOS / Linux source venv/bin/activate然后安装核心依赖pip install openai pip install python-dotenv pip install requests如果平时习惯使用 LangChain也可以自行安装langchain和langchain-openai。不过本文的完整项目案例会尽量少依赖框架用原生 Python 实现一遍 Agent 的核心循环。这样更能帮助你理解底层原理而不是被框架封装掩盖掉关键逻辑。3. Agent 的核心组成模块拆解3.1 LLMAgent 的“大脑”在 Agent 里LLM 承担两个职责根据用户指令和已有上下文推理出下一步行动如果需要调用工具生成结构化的调用参数。以 OpenAI 兼容接口为例最核心的是chat.completions.create。标准写法如下from openai import OpenAI client OpenAI( api_key你的KEY, base_url你的接口地址 ) response client.chat.completions.create( modelgpt-4o-mini, messages[ {role: system, content: 你是智能助手可以调用外部工具来回答用户问题。}, {role: user, content: 北京今天天气怎么样} ] ) print(response.choices[0].message.content)关键参数说明model用的具体模型名称需要根据服务商调整messages对话消息列表包含 system、user、assistant 三种角色temperature控制随机性Agent 应用建议设 0.2 左右避免过度发挥tools如果要让模型调用工具需要传入工具定义列表后面实战会展开。新手常见的误区是只发一次请求拿结果而 Agent 需要“多轮循环”也就是模型可能会连续请求调用多个工具每轮都要把工具结果回传直到模型认为任务完成。3.2 Memory短期记忆与长期记忆记忆是 Agent 和普通 API 调用拉开差距的一个重要模块。短期记忆指的是当前对话窗口内的消息列表。比如用户先问“我上个月的项目叫什么”再问“它什么时候截止”模型需要靠前面的对话来理解“它”指代什么。所以 Agent 的每条请求通常会把历史消息全部带上。长期记忆则常通过向量数据库实现。系统将用户的提问转换成向量从知识库中召回相关片段再塞进系统提示词里让模型基于这些内容回答。常用方案有Chroma适合本地小规模原型Milvus适合生产级向量存储云厂商的向量检索服务。实战中最简单的方式是用文本拼接召回结果def build_context(retrieved_docs): context \n.join([doc[content] for doc in retrieved_docs]) return f参考资料\n{context}\n这样模型在生成回答时能拿到知识库中的权威信息而不是纯粹依赖训练数据准确率和可控性都会显著提升。3.3 Planning任务拆解与执行顺序复杂任务需要拆解。比如“帮我统计本季度各渠道的用户增长并生成图表”这个任务至少可以拆成三步查询数据、分析数据、绘图。Agent 有两种拆解方式单轮规划模型在第一次回答时列出任务清单然后逐个执行动态规划每一步都根据当前状态重新决定下一步更符合真实场景。动态规划的核心是 Agent 循环Agent Loop。伪代码如下messages [{role: system, content: system_prompt}] while True: response call_llm(messages) if response.tool_calls: messages.append(response.message) for tool_call in response.tool_calls: result execute_tool(tool_call) messages.append(tool_result_message(tool_call, result)) else: final_answer response.message.content break这个循环的意义在于模型提出调用工具的请求后程序并不直接返回给用户而是把工具执行结果再次丢给模型让模型决定下一步。只有当模型不再要求调用工具时才把最终结果展示给用户。这里推荐把规划拆成小块去调试。如果你的 Agent 经常做无用步骤优先检查系统提示词里有没有明确“尽可能减少工具调用次数”的约束。3.4 Tool Use工具定义与参数解析Tool Call 是 Agent 区别于普通聊天最重要的能力。在 OpenAI 兼容接口中一个工具定义包含type、function、name、description、parameters。以天气查询工具为例{ type: function, function: { name: get_weather, description: 根据城市名查询实时天气, parameters: { type: object, properties: { city: { type: string, description: 城市名例如北京、上海 } }, required: [city] } } }模型收到这个工具定义后如果认为需要查询天气会在返回内容中给出如下结构{ tool_calls: [ { id: call_xxx, type: function, function: { name: get_weather, arguments: {\city\: \北京\} } } ] }程序要做的是根据function.name找到对应的 Python 函数再把arguments解析为 JSON 字典作为参数传入。这个“工具注册与分发”机制是 Agent 框架里最核心的部分后面实战会给出完整封装。4. 完整实战从零搭建一个 AI Agent 项目这一节带着你搭建一个可运行的 Agent 项目功能包括工具调用、上下文记忆和任务循环。项目结构如下ai-agent-tutorial/ ├── agent.py # Agent 核心类 ├── tools.py # 工具注册与实现 ├── config.py # 配置管理 ├── main.py # 入口示例 └── .env # 存放 API 密钥不要提交到 git4.1 创建项目结构和配置文件先在项目根目录创建.env文件MODEL_NAME你的模型名 API_BASE你的接口地址 API_KEY你的密钥然后新建config.pyimport os from dotenv import load_dotenv load_dotenv() MODEL_NAME os.getenv(MODEL_NAME) API_BASE os.getenv(API_BASE) API_KEY os.getenv(API_KEY)这里用python-dotenv自动读取环境变量好处是不会把密钥硬编码在代码里。如果是在企业内网部署也建议通过环境变量或配置中心下发这些敏感信息不要写死在源码仓库中。4.2 编写工具模块 tools.py接下来编写工具注册与分发逻辑。先定义工具字典再写具体函数。import datetime import json import random def get_current_time() - str: 返回当前时间供模型判断时间相关信息 return datetime.datetime.now().strftime(%Y-%m-%d %H:%M:%S) def get_today_plan() - str: 返回今日任务计划模拟从日历中读取数据 return 上午 10:00 项目评审下午 16:00 客户会议晚上 20:00 写技术报告。 def get_order_statistics() - str: 模拟从数据库查询订单统计数据 return json.dumps( { total_orders: 128, total_amount: 56900.0, daily_count: random.randint(1, 50) }, ensure_asciiFalse ) TOOLS_INFO [ { type: function, function: { name: get_current_time, description: 获取当前时间当用户询问时间时调用, parameters: { type: object, properties: {} } } }, { type: function, function: { name: get_today_plan, description: 获取今日日程安排当用户询问今天要做什么时调用, parameters: { type: object, properties: {} } } }, { type: function, function: { name: get_order_statistics, description: 获取近期订单统计数据当用户询问订单或销售情况时调用, parameters: { type: object, properties: {} } } } ] TOOL_MAP { get_current_time: get_current_time, get_today_plan: get_today_plan, get_order_statistics: get_order_statistics, } def dispatch_tool(name: str, arguments: str) - str: 根据模型返回的工具名称和参数执行对应函数 if name not in TOOL_MAP: return f错误未找到工具{name} try: args json.loads(arguments) if arguments else {} except json.JSONDecodeError: args {} func TOOL_MAP[name] return func(**args)核心思路是TOOLS_INFO是提交给模型的工具描述列表TOOL_MAP是工具名到 Python 函数的映射dispatch_tool统一负责解析参数和调用函数。这种写法比在每个 if 分支里写逻辑更清晰。以后增加新工具只需要在TOOLS_INFO加描述在TOOL_MAP加映射在模块顶部写函数实现即可。4.3 编写 Agent 核心循环 agent.py这一节是全文的重点。Agent 核心循环需要完成以下动作接收用户输入把系统提示词和历史消息组装好发给大模型如果模型返回tool_calls逐个执行工具并把结果回传给模型如果模型返回普通文本说明任务完成跳出循环。实现代码如下from openai import OpenAI from config import MODEL_NAME, API_BASE, API_KEY from tools import TOOLS_INFO, dispatch_tool DEFAULT_SYSTEM_PROMPT ( 你是一个智能助手用户会向你提出各种问题。 如果需要获取实时信息或执行操作你可以调用我提供的工具。 你每一步只能调用一个工具调用工具后请根据工具返回结果继续推理。 当不需要调用工具时直接给出最终回答。 ) class Agent: def __init__(self, model: str MODEL_NAME): self.client OpenAI(api_keyAPI_KEY, base_urlAPI_BASE) self.model model def chat(self, user_input: str, max_iterations: int 5) - str: messages [ {role: system, content: DEFAULT_SYSTEM_PROMPT}, {role: user, content: user_input}, ] for _ in range(max_iterations): response self.client.chat.completions.create( modelself.model, messagesmessages, toolsTOOLS_INFO, temperature0.2, ) assistant_message response.choices[0].message if assistant_message.tool_calls: # 先把模型回复追加到消息列表 messages.append(assistant_message) # 逐个处理工具调用 for tool_call in assistant_message.tool_calls: tool_name tool_call.function.name tool_args tool_call.function.arguments print(f[工具调用] {tool_name}({tool_args})) result dispatch_tool(tool_name, tool_args) messages.append({ role: tool, tool_call_id: tool_call.id, content: result, }) else: return assistant_message.content or return 达到最大迭代次数任务未完成请调整提示词或工具配置。 if __name__ __main__: agent Agent() while True: user_input input(你) if user_input.lower() in (exit, quit): break print(Agent, agent.chat(user_input))代码说明max_iterations是安全阀防止模型进入无限循环messages.append(assistant_message)要把assistant_message原样加进对话历史模型才能知道它自己刚刚调用了什么工具每次工具结果都要使用role: tool追加并带上tool_call_id否则大模型接口会报错打印[工具调用]日志方便本地调试时观察到模型当前的行为。这里有个容易踩坑的点不同模型服务商对tool消息格式要求可能略有差异。比如部分平台要求content必须是字符串不能是 JSON 对象部分平台要求消息顺序必须符合“工具调用之后必须紧跟工具消息”。如果请求时报 invalid messages优先对照官方接口文档检查这块结构。4.4 编写入口 main.py新建main.pyfrom agent import Agent agent Agent() if __name__ __main__: question 现在是几点我今天有什么安排顺便看看最近的订单数据。 answer agent.chat(question) print(Agent 最终回答) print(answer)这个示例故意让用户同时提三个问题目的是观察 Agent 是否能连续多次调用不同工具。从 OpenAI 兼容接口的机制来看模型一般会在一次回复中带出多个tool_calls程序会循环执行全部工具再把结果统一回传。4.5 运行与验证在命令行执行python main.py预期输出类似[工具调用] get_current_time({: }) [工具调用] get_today_plan({}) [工具调用] get_order_statistics({}) Agent 最终回答 当前时间是 2026-06-21 14:30:00。你今天有两个重要安排上午 10:00 项目评审下午 16:00 客户会议。另外最近订单统计显示总订单量 128 单总金额 56900.0 元。由于get_order_statistics里的daily_count使用了随机数每次执行结果会略有不同这是预期行为。运行完这个 demo你就已经掌握 Agent 最核心的循环机制。之后无论使用 LangChain 还是其他框架底层逻辑都是这个思路的封装。4.6 实战结果分析这个实战案例虽然简单但已经覆盖了 Agent 的核心链路大模型接收复杂指令模型自主决定调用哪个工具程序执行工具并把结果回传模型根据结果组织最终回答。你可以在此基础上做以下扩展增加数据库查询工具把假数据改成真实 SQL 查询增加网页搜索工具让 Agent 能获取实时新闻增加文件读写工具让 Agent 能生成报告并保存到本地增加消息推送工具让 Agent 执行完整业务动作。5. 从入门到精通的进阶方向5.1 从单工具到多工具协作真实项目很少只有三个工具。工具多了以后模型容易选错工具或生成非法参数。这时可以采取以下工程手段给每个工具写清晰、无歧义的描述描述里要包含触发场景示例参数尽量压缩数量能用一层结构就不要用嵌套结构对高成本动作增加二次确认机制比如删除文件和发送消息前先向用户确认定期统计工具调用失败率发现高频失败工具后优化定义或调整提示词。多工具协作还需要注意工具命名前缀一致例如db_、http_、file_出问题时按前缀快速定位。5.2 引入记忆机制构建对话闭环目前的 Agent 每次对话都是独立的用户说“上一轮的结论呢”模型无法回答。要解决这个问题需要把每次对话保存在本地文件或数据库中在下一次请求时附加到messages中。一条简单实现如下def load_history(user_id: str): # 从 sqlite 或文件读取该用户的最近对话 pass def save_history(user_id: str, messages: list): # 持久化保存 pass生产级应用一般会配置 Redis 管理短期会话缓存用 MySQL 或 MongoDB 保存长期用户数据再配合向量库维护知识库索引。5.3 多 Agent 协作与角色分工当业务复杂到单个 Agent 难以胜任时可以考虑多 Agent 协作。比如把系统拆成“数据分析 Agent”“报告撰写 Agent”“发送邮件 Agent”每个 Agent 负责一个专门角色通过消息队列或共享状态协作。多 Agent 设计的核心是明确“谁负责决策、谁负责执行、冲突怎么解决”。初学者不建议一上来就搭复杂多角色系统先让单 Agent 稳定跑通再逐步拆分角色边界这样排查问题会容易得多。5.4 Agent 可观测性与安全性Agent 进入生产环境后只关注最终结果是不够的。因为 Agent 是动态决策的一旦结果出错很难直接定位是哪一轮推理出了问题。这时必须做全链路日志记录记录每一轮的 messages 完整内容记录工具调用名称、参数、耗时、返回状态记录最终回答的生成时间、token 消耗对异常工具调用做告警。安全性上建议遵循最小权限原则。Agent 能调用的工具权限应该尽量收敛不要直接把数据库管理账号、文件删除接口、转账接口直接暴露给模型。模型是概率系统不是可靠程序必须把高风险操作拦在人工确认层。6. 常见问题与排查思路6.1 常见问题速查表问题现象常见原因解决思路接口返回 401 错误API Key 错误或没有读取到环境变量检查.env文件路径和变量名确认load_dotenv()调用位置接口返回模型不存在错误模型名称与平台不匹配登录对应平台控制台确认模型名称注意区分版本后缀返回结果不调用工具模型不支持 Function Calling 或提示词没有说明检查工具定义格式在系统提示词里明确“需要时可调用工具获取最新信息”调用工具时报参数错误模型生成的 JSON 参数与工具定义不一致在工具函数里增加 try-except把参数错误转成可读消息回传模型让模型重新生成消息历史报错 invalid messagestool_call_id 缺失或 role 顺序错误严格按照接口文档追加 tool 消息确保工具的回复紧随对应 tool_call 之后Agent 死循环工具结果没有正确回传或提示词没有终止条件设置最大迭代次数工具函数应返回明确的结构化结果6.2 详细排查清单如果你刚写完一个 Agent 项目但跑不通按下面顺序检查确认你的模型接口是 OpenAI 兼容格式可以在调试工具里直接发送单次工具调用请求测试确认tools列表是 JSON 可序列化的不要包含 Python 对象确认工具返回的结果一定是字符串部分接口不接受 dict 类型确认每次请求的messages顺序正确user → assistant → tool → user/assistant检查代码里是否真的执行了dispatch_tool而不是只打印了参数检查温度参数温度过高模型容易“发散”生成意外的工具参数。7. 最佳实践与工程建议7.1 用两层封装隔离框架升级Agent 框架更新迭代非常快。建议在项目里加一层自己的封装接口所有业务代码只依赖这个接口不直接依赖第三方框架。这样即使底层框架大升级业务代码也不需要重写。一个比较稳妥的封装思路是class AgentService: def __init__(self, agent_core): self.agent_core agent_core def execute(self, query: str) - str: # 在这里统一处理日志、鉴权、限流、降级 pass7.2 提示词即配置不进代码Agent 的系统提示词应该放到配置文件或配置中心不要直接硬编码在代码里。因为同一个 Agent 上线后大概率要频繁调整提示词来优化表现。提示词中央化之后可以做到不改代码、不重新发布只改配置就完成线上调优。7.3 控制成本并设计超时机制大模型 Agent 的成本来自 token 消耗和工具调用次数。上线前建议设置单次对话的 token 上限、调用次数上限、单次工具超时时间。这些都是线上故障防护能避免一次异常对话拖垮整个预算。7.4 安全边界放在工具层不要在模型返回的可信度上赌安全。哪怕模型信誓旦旦说“已删除”也要看代码里删除操作是否真的经过了审批流。工具层要做权限控制和操作确认模型层只负责生成意图不负责业务合规。8. 总结与下一步学习路线写到这里你已经完整走通了一个 AI Agent 智能体开发的最小闭环理解 Agent 组成、配置环境、编写工具、搭建循环、排查常见问题。下一步建议按这个顺序继续深入动手扩展三个真实工具把模拟数据换成真实接口研究 LangChain 或 LiteLLM 的源码看看官方封装和本文手写实现的差异学习向量数据库完成一个知识库问答 Agent把 Agent 封装成 FastAPI 服务接入前端或飞书、钉钉机器人研究多 Agent 协作框架并在小场景里做对比实验。AI Agent 开发真正难的地方不是写循环而是定义边界哪些事交给模型决策哪些事必须由程序控制。能把这条边界想清楚你的 Agent 项目才能真正跑到生产环境里扛住真实流量。建议把本文的完整代码在本地跑通再逐步做扩展遇到问题优先看日志日志里每一轮工具调用都是定位问题的关键线索。如果这篇文章对你有帮助可以先把核心代码存到自己的项目里后边用到时直接照着改。
网站建设高端定制企业官网