AI Agent核心原理与Python实战:从聊天到自动执行工具 📅 发布时间:2026/8/29 2:45:15 👁 浏览次数: 最近技术圈有两件事放在一起看很有意思Manus 重新回到大众视野林俊旸也再次出现在公开讨论中。前者是 2025 年初刷屏的通用 AI Agent 产品后者被普遍视为国内大模型研究的代表性人物。两件事几乎同时发生背后的信号其实是同一个AI 行业的关注点正在从“训练一个更强的模型”转向“把模型变成真正能干活的产品”而 AI Agent 就是这个转向的核心载体。本文不打算追热点而是把这两个信号当成切入点把 AI Agent 的原理、关键技术模块、最小可运行实现和工程落地要点完整拆解一遍。读完你会理解 Manus 这类产品的基本工作方式也能自己用 Python 写一个能调用工具、能计算、能查时间的 Agent 雏形。文章包含完整可复制代码适合想入门智能体开发的同学也适合后端工程师把 Agent 能力接入现有系统。1. 背景Manus 和林俊旸的“回归”意味着什么1.1 Manus 是什么Manus 是一个通用型 AI Agent 产品名字取自拉丁语“手”寓意是“把想法变成能动手执行的任务”。它和普通聊天机器人的最大区别在于你给它一个目标它可以自己拆解步骤、调用工具、浏览网页、写代码、生成文件最后交付一份可用的结果。2025 年初它的一段演示视频在全球范围内传播很多人第一次直观感受到“AI 不只会聊还会干活”。需要说明的是科技产品迭代速度非常快本文讨论的是它背后的通用技术模式而不是某个固定版本的功能清单。你在不同时间打开这类产品界面和能力可能已经不同但底层逻辑是一致的大模型负责思考工具负责执行循环负责修正。1.2 林俊旸的“回归”为什么被关注公开信息显示林俊旸是 DeepSeek 系列大模型的核心研究者之一也是 AI 圈公认的技术型人物。这样一位模型侧的研究者重新出现在大众视野和 Manus 的回归几乎同时发生让不少从业者认为模型能力已经积累到一个临界点接下来比拼的不再只是参数规模和评测分数而是谁能把模型能力封装成稳定、可信、可交付的 Agent 产品。对于普通开发者这个趋势意味着一个新的技术窗口Agent 开发并不是大厂专属个人开发者只要有模型 API、会写 Python就能构建自己的自动化助手。这也是本文选择“手写一个最小 Agent”作为核心实战的原因。2. AI Agent 是什么从“会聊天”到“会干活”2.1 大模型与智能体的边界我们先给一个通俗定义AI Agent 大模型 规划 工具调用 记忆 执行反馈闭环单独的大模型LLM本质上是一个文本生成器。你输入一段文字它预测下一段最合理的文字。它能写诗、能总结、能写代码片段但它不能替你打开网页、不能查询实时股价、不能操作数据库因为它的知识截止于训练数据且没有对外部系统执行动作的能力。Agent 则在模型外面包了一层“执行逻辑”模型负责理解目标、拆解任务、决定下一步调用什么工具。工具负责真正接触外部世界比如查时间、算数学、调接口、读写文件。循环负责把工具结果回传给模型让模型决定下一步做什么直到任务完成。传统聊天机器人与 Agent 的核心差异可以看下面这张表。对比维度传统 ChatbotAI Agent交互方式一问一答目标驱动多步执行外部能力不支持或单点集成可动态调用多种工具任务复杂度简单问答、信息查询复杂任务拆解与自动执行失败处理答错就结束可重试、可修正、可上报典型产品客服机器人Manus、AutoGPT 类产品2.2 典型应用场景Agent 适合解决“多步骤、需要外部信息、需要操作环境”的任务常见场景包括信息收集与整理自动搜索资料、去重、生成结构化报告。数据分析读取 CSV、清洗数据、生成图表和结论。代码开发按需求生成项目结构、编写代码、执行测试。自动化运维根据日志定位问题、执行排查命令。个人助理管理日程、查询天气、订票等工具集成。掌握了 Agent 的基本原理这些场景本质上是同一个模式给模型一个目标提供足够的工具让循环跑起来。3. AI Agent 的核心技术模块拆解3.1 规划Planning规划是 Agent 的“大脑”。一个复杂目标通常不能一步完成模型需要把它拆成若干子任务并确定执行顺序。最常见的两种实现方式固定流程编排开发者预先定义好步骤比如“先抓数据再清洗再出报告”每一步调用固定的工具。这种方式可控性强适合业务稳定、变化少的场景。模型自主规划把目标交给模型让模型自己决定下一步。配合 ReActReason Act模式模型会一边分析现状一边决定行动观察结果后再继续。这种方式的灵活度高但结果不确定性也更大。在实际产品中往往两者结合主流程用编排保证稳定性分支细节交给模型自主决策。3.2 工具调用Function Calling / Tool Use工具调用是 Agent 区别于普通聊天的关键能力。大模型本身不执行代码但它可以输出一个结构化的 JSON描述“我想调用某个函数、传入这些参数”。这个机制通常被称为 Function Calling 或 Tool Use。一次完整调用包含四个部分工具描述告诉模型存在哪些工具每个工具的用途、参数是什么。模型决策模型根据当前对话输出工具名和参数 JSON。程序执行代码在本地真正调用对应函数。结果回传把函数返回值作为一条消息追加到对话中。工具描述写得越清晰模型的选择就越准确。尤其是 description 字段它直接影响模型对工具用途的理解这也是很多 Agent 效果差的原因之一。3.3 记忆Memory记忆让 Agent 在多次交互中保持上下文。短期记忆即对话窗口内的消息列表模型通过它知道“之前说了什么、刚才工具返回了什么”。长期记忆跨会话的用户偏好、历史任务结果通常存储在向量数据库或普通数据库中需要时检索后注入提示词。对于简单 Agent短期记忆已经够用。生产级 Agent 必须考虑长期记忆否则每次对话都从零开始体验会非常割裂。3.4 执行与反馈闭环Agent 的运行是一个循环用户目标 ↓ 模型思考决定调用工具 or 直接回答 ↓ 需要工具──否──→ 输出最终答案 ↓ 执行工具 ↓ 把结果回传给模型 ↓ 重复直到达到停止条件停止条件通常是三个模型给出了最终答案、达到最大循环步数、用户主动中断。没有停止条件的 Agent 可能陷入死循环因此在代码实现中必须设置 max_steps 这类上限。4. 手写一个最小可用 AgentPython 实战4.1 环境准备本文示例使用 OpenAI 兼容接口来完成模型调用核心依赖是 openai SDK。Python 版本建议 3.9 及以上示例在 3.10/3.11 环境同样适用。依赖安装pip install openai1.0.0如果你使用 OpenAI 官方接口base_url 填官方地址如果使用国内兼容 OpenAI 协议的模型服务按服务商文档填写 base_url 和模型名。API Key 建议放在环境变量里不要硬编码到代码中。4.2 项目结构agent_demo/ ├── agent.py # Agent 主循环 ├── tools.py # 工具定义与实现 ├── requirements.txt # 依赖清单 └── README.md # 说明文档本文会给出 tools.py 和 agent.py 的完整代码。4.3 编写工具层 tools.py工具层要解决两件事定义工具描述信息给模型看实现工具函数给程序执行。先看代码。# 文件路径agent_demo/tools.py import ast import operator import datetime def get_current_time() - str: 获取当前日期和时间返回字符串 return datetime.datetime.now().strftime(%Y-%m-%d %H:%M:%S) def safe_calculator(expression: str) - str: 安全计算数学表达式仅支持数字、括号、 - * / % ** allowed_ops { ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul, ast.Div: operator.truediv, ast.Mod: operator.mod, ast.Pow: operator.pow, ast.USub: operator.neg, ast.UAdd: operator.pos, } def eval_node(node): if isinstance(node, ast.Expression): return eval_node(node.body) if isinstance(node, ast.BinOp) and type(node.op) in allowed_ops: left eval_node(node.left) right eval_node(node.right) return allowed_ops[type(node.op)](left, right) if isinstance(node, ast.UnaryOp) and type(node.op) in allowed_ops: return allowed_ops[type(node.op)](eval_node(node.operand)) if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)): return node.value raise ValueError(不支持的表达式) try: tree ast.parse(expression, modeeval) return str(eval_node(tree)) except Exception as exc: return f计算失败{exc} TOOLS [ { type: function, function: { name: get_current_time, description: 获取当前日期和时间返回字符串例如 2025-01-01 10:00:00, parameters: { type: object, properties: {}, required: [] } } }, { type: function, function: { name: safe_calculator, description: 执行数学表达式计算支持加()、减(-)、乘(*)、除(/)、取模(%)、乘方(**)、括号例如 ((12 34) * 56) / 7, parameters: { type: object, properties: { expression: { type: string, description: 要计算的数学表达式 } }, required: [expression] } } } ] TOOL_MAP { get_current_time: get_current_time, safe_calculator: safe_calculator, }这里有几个设计点值得注意。第一计算器没有使用内置的 eval 函数而是用 ast 模块解析表达式并只允许白名单内的运算符。在生产环境任何执行外部输入代码的行为都必须隔离在沙箱中这是一个安全底线。第二工具描述对模型至关重要。safe_calculator 的 description 里明确写了支持的运算符和示例表达式模型看到后更容易生成正确的参数。第三TOOL_MAP 是一个名字到函数的映射表主循环拿到模型返回的工具名后通过它找到真实函数。4.4 编写 Agent 主循环 agent.py主循环负责管理对话消息、调用模型、执行工具、回传结果。# 文件路径agent_demo/agent.py import json from openai import OpenAI from tools import TOOLS, TOOL_MAP client OpenAI( api_keyyour-api-key, # 建议从环境变量读取 base_urlhttps://api.example.com/v1 # 按服务商文档填写 ) def agent_loop(user_input: str, max_steps: int 5) - str: messages [ { role: system, content: ( 你是一个实用型 AI Agent。你可以调用工具来获取实时信息或完成计算。 每次工具调用后请根据工具结果继续分析直到给出最终答案。 ) }, {role: user, content: user_input} ] for step in range(1, max_steps 1): print(f\n Step {step} ) response client.chat.completions.create( modelgpt-4o-mini, # 按服务商可用模型调整 messagesmessages, toolsTOOLS, tool_choiceauto, ) message response.choices[0].message messages.append(message) # 模型没有请求调用工具说明已给出最终答案 if not message.tool_calls: print(最终答案, message.content) return message.content or # 处理模型请求的每一个工具调用 for tool_call in message.tool_calls: fn_name tool_call.function.name fn_args json.loads(tool_call.function.arguments or {}) print(f调用工具{fn_name}参数{fn_args}) if fn_name not in TOOL_MAP: result f错误未注册的工具 {fn_name} else: try: result TOOL_MAP[fn_name](**fn_args) except Exception as exc: result f工具执行异常{exc} messages.append({ role: tool, tool_call_id: tool_call.id, content: str(result), }) print(达到最大步数任务结束。) return if __name__ __main__: print(AI Agent Demo 已启动输入 exit 退出) while True: question input(\n你) if question.strip().lower() in (exit, quit): break agent_loop(question)主循环的逻辑并不复杂但它是所有 Agent 产品的骨架。第一步把系统提示词和用户问题放进 messages。系统提示词在这里承担“规则设置”的作用告诉模型它是 Agent并且可以使用工具。第二步调用模型接口传入 tools。模型会返回两种结果之一要么直接给出文本答案要么生成 tool_calls 列表。第三步如果模型要求调用工具程序逐条执行并把结果以 roletool 的消息追加进对话。注意 tool_call_id 必须和模型的调用 ID 对应否则接口会报错。第四步带着包含工具结果的新消息再次请求模型。模型看到工具结果后要么继续调用新工具要么汇总出最终答案。整个循环中最容易被忽略的是 messages.append(message)。把模型这次返回的消息原样追加到历史里是保持多轮工具调用上下文正确的关键。4.5 运行验证安装依赖后在项目目录执行cd agent_demo python agent.py依次输入两个问题观察输出。第一个问题你现在几点钟了请调用工具查询预期过程 Step 1 调用工具get_current_time参数{} Step 2 最终答案当前时间是 2025-07-01 14:23:45。第二个问题你帮我算一下 ((12 34) * 56) / 7 的结果预期过程 Step 1 调用工具safe_calculator参数{expression: ((12 34) * 56) / 7} Step 2 最终答案计算结果为 368.0。4.6 结果说明从运行日志可以看出模型在第一步并没有直接回答而是先“决定”调用工具。这个决定来自工具描述和用户问题的匹配用户要查时间模型在 TOOLS 里找到了 get_current_time于是生成对应的 JSON 调用。工具执行完成后结果被回传模型在第二步基于真实数据组织语言输出。这就是“模型思考 工具执行 结果反馈”的闭环。任何复杂 Agent无论界面多华丽核心都是这个循环的放大和工程化。如果你发现模型始终不调用工具优先检查两个地方一是模型是否支持 function calling二是工具描述是否足够清晰。模型没有“常识”去猜测工具的用途描述越精确命中率越高。5. 从 Demo 到 Manus 式通用 Agent还需要补齐什么手写的最小 Agent 证明了原理但距离 Manus 这类产品还有很长的工程距离。下面这些方向是从 Demo 走向生产必须补的课。5.1 任务规划与状态管理简单 Agent 一次只处理一个工具调用复杂任务往往需要多个步骤并且步骤之间有依赖关系。例如“查询三只股票近一年的数据并对比走势”需要先搜索、再抓取、再分析、再画图。生产级方案通常引入任务队列或 DAG有向无环图把子任务的状态记录下来某个节点失败时只重试该节点而不是整个任务重来。5.2 更丰富的工具集Manus 之所以看起来“什么都能干”本质是接入了大量工具搜索 API获取实时网页信息。浏览器自动化模拟点击、填写表单、抓取动态页面。代码执行环境运行 Python 脚本并获取输出。文件读写生成 CSV、Excel、PDF 报告。第三方服务接口数据库、消息推送、办公软件。工具越多Agent 的能力边界越宽但维护成本和风险也随之上升。建议按需接入而不是盲目堆工具。5.3 长期记忆与用户画像生产环境需要把用户的历史偏好、项目背景、常用配置持久化。一种常见做法是每次任务结束后把关键信息写入向量数据库下一次任务开始时根据用户输入检索相关记忆并注入提示词。5.4 异步执行与进度反馈复杂任务可能耗时几分钟甚至更久不能要求用户一直等待。Manus 式产品通常把任务放到后台队列执行前端通过轮询或 WebSocket 推送进度。Agent 需要输出中间状态例如“正在搜索资料”“正在生成图表”让用户知道任务还在推进。5.5 可信与安全机制自动执行工具的 Agent 一旦权限过大风险极高。生产系统必须包含敏感操作人工确认、代码执行沙箱、工具调用审计日志、操作配额与熔断。安全不是上线后才补的而是在工具层就设计进去。6. 常见问题与排查思路在开发和调试 Agent 过程中下面几个问题出现频率最高。问题现象可能原因解决思路模型始终不调用工具模型不支持 function calling或工具描述不清晰更换支持工具调用的模型补充 description 和参数示例工具参数解析失败模型生成的 JSON 与声明的参数类型不一致在代码中对参数做类型校验解析失败时提示模型重新生成上下文超限多轮工具调用导致 messages 越来越长对历史消息做截断或摘要压缩只保留关键信息Agent 陷入死循环缺少停止条件或工具结果与问题不匹配设置 max_steps 上限增加“无法完成时主动放弃”的提示词工具执行产生副作用工具被无权限调用比如删文件、改配置按最小权限原则控制工具敏感操作加入人工审批接口响应超时网络问题或模型推理时间过长设置超时参数对失败请求做指数退避重试排查这类问题有个通用思路先看模型输出再看工具结果最后看消息历史。把日志打印完整尤其是每次 tool_calls 的原始返回绝大多数问题都能从日志里定位。7. Agent 工程最佳实践7.1 工具设计原则工具是 Agent 的“手”设计得好坏直接决定任务成功率。工具命名要语义清晰比如 get_stock_price 比 api_001 更友好。description 要写“什么时候用”而不是只写“是什么”。例如“当用户询问某个城市当前天气时使用”比“天气查询”效果更好。参数尽量少类型尽量简单。能用一个字符串参数解决就不要拆五个对象。工具返回统一结构优先返回 JSON 字符串方便模型解析。工具尽量保持幂等特别是查询类工具多次执行不应产生副作用。7.2 安全与权限Agent 自动调用工具意味着普通用户的操作行为可能被代理执行这是安全风险最大的地方。最小权限原则每个工具只授予完成任务所需的最低权限。代码执行必须沙箱化不要让模型生成的代码直接在本机跑至少使用容器或子进程隔离。危险操作人工审批删除、修改、支付、发送消息等操作必须由用户确认后执行。完整审计日志记录每次工具调用的人、时间、参数、结果便于回溯。API Key 永远不要出现在前端代码或日志里统一通过服务端环境变量管理。7.3 成本与性能控制Agent 的 token 消耗比普通聊天高很多因为每次工具调用都要把完整上下文重新发给模型。对历史消息做压缩过长的工具结果只保留摘要。简单任务用小模型复杂任务才用大模型做模型分级。相同工具的查询结果可以加缓存减少重复调用。设置单任务成本上限和步数上限防止异常任务耗尽预算。7.4 可观测性与测试Agent 的链路比普通接口长出现问题很难直接定位可观测性从第一天就要建立。日志里打印每一步的模型输出、工具参数、工具结果、耗时。用 trace 视角记录一次任务的完整调用链。指标至少包含成功率、平均步数、平均耗时、工具失败率。测试分两层工具函数做单元测试完整场景做端到端测试。每次调整提示词或工具描述后跑一遍回归防止“修一个任务坏三个任务”。8. 总结与学习路线回到开头的问题Manus 和林俊旸的回归本质上都在提示一个方向——大模型的下一站是 Agent。对开发者来说这意味着一套新的工程技能栈值得尽早掌握。如果你打算系统学习 AI Agent 开发可以按下面的路径推进先理解提示词工程学会用 system prompt 约束模型行为。掌握 Function Calling能自己定义工具并跑通调用闭环也就是本文的 Demo。学习 Agent 框架比如 LangChain、AutoGen、Dify了解别人如何封装规划、记忆和工具调度。自己做一个完整项目比如“自动生成周报的 Agent”或“PDF 内容提取与总结 Agent”把记忆、异步任务、权限控制都加进去。最后关注生产化成本、安全、可观测性。建议从改造本文的 Demo 开始给它增加一两个自定义工具比如天气查询或文件保存然后逐步扩展。技术方向每次迭代都会出现新的热点但 Agent 的核心循环不会变模型负责思考工具负责执行工程负责兜底。先把这条链路打通后面再多变化都不慌。