从零手撸AI Agent框架:工具调用、记忆与双模型调度深度拆解

一切从提示词说起:认清它的四大局限
作者的同事曾戏称大模型的核心就是提示词,称其为"掌管提示词的古希腊馆长"。这句话对,也不对。
在不做训练的前提下,我们能影响大模型的确实主要是提示词输入,由此衍生出零样本学习、少样本学习、思维链(CoT)等方法论。其中,**零样本学习(Zero-shot Learning)**指不提供任何示例,直接用自然语言描述任务让模型完成;**少样本学习(Few-shot Learning)**则在提示词中附带少量输入-输出示例(通常1-5个),通过上下文演示帮助模型理解任务格式与期望,两者均无需更新模型权重。**思维链(Chain-of-Thought,CoT)**则由Google Brain团队于2022年提出,通过在示例中展示逐步推理过程,引导模型在给出最终答案前先输出中间推理步骤,显著提升了数学推理、符号推理等复杂任务的表现,尤其对参数量超过100B的大模型效果突出。
但如果把系统完全建立在提示词之上,会暴露四个致命问题:
- 脆弱性与不可复现性:稍微改动几个对人类无差别的词,模型输出可能天差地别。做Demo时"看天吃饭"问题不大,但真正落地就相当危险。
- 扩展性差:随着挂载工具越来越多,纯提示词方案会变得难以维护。
- 用户负担重:把提示词工程的复杂度全部转嫁给用户,显然不现实。
- 无状态性:大模型本质上没有记忆功能,多轮对话难以处理。
正因如此,业界从单纯的"提示词工程"升级到了**"上下文(Context)工程"**。上下文工程是2024年以来业界对提示词工程的重要升级概念,由Anthropic等机构率先提出。它强调不仅要设计"说什么",更要精细管理"什么时候放入什么信息、信息以何种结构组织"。
这一理念有坚实的学术支撑。斯坦福大学2023年发表的"Lost in the Middle"研究通过系统性实验揭示了大模型对上下文位置的结构性偏差——模型对输入序列开头和结尾部分的信息记忆与利用能力,显著优于中间部分。换言之,将关键指令或重要背景埋在超长上下文的中段,模型极有可能视而不见。这一发现直接指导了上下文的信息编排策略:关键约束应置于开头,最新的工具返回结果应靠近末尾,而非随意堆叠。研究还表明,上下文中的噪声信息(与任务无关的冗余文本)会以非线性方式降低模型推理准确性,这为后文上下文精简设计提供了理论依据。
本文的实现涵盖了短时记忆、工具标准化输出等模块,唯独RAG(Retrieval-Augmented Generation,检索增强生成)部分未做设计。RAG是一种将外部知识库检索与大模型生成相结合的技术范式,由Meta AI于2020年提出,其核心思路是在生成回答前先从向量数据库或文档库中检索相关段落注入上下文,弥补模型训练数据截止日期的局限。向量数据库(如Faiss、Chroma、Weaviate、Pinecone)通过将文本转化为高维向量并建立近似最近邻索引,支持基于语义相似度的快速检索;RAG的离线阶段负责文档切片、向量化与入库,在线阶段则完成查询向量化、相似度搜索与结果注入上下文——这一模块留待读者自行扩展。

Function Call的本质:让大模型理解工具Schema
大模型本质是"字符串进、字符串出"的系统。做问答没有问题,但要调用外部工具,就需要一个中间桥梁——工具Schema(工具描述)。
Function Call(函数调用)是OpenAI于2023年在GPT模型中率先引入的能力,随后迅速成为行业标准。其本质是让大模型在生成回复时,能够输出一段结构化的JSON指令,告知外部系统"我需要调用哪个函数、传入什么参数",而非直接返回自然语言。
这一能力从OpenAI的专有设计演变为跨厂商的通用规范,经历了值得关注的标准化历程:Google Gemini的Function Calling、Anthropic Claude的Tool Use,以及开源社区的Mistral、Qwen等模型,均已实现对JSON Schema工具描述格式的兼容支持。JSON Schema规范本身起源于2009年,是一种基于JSON格式的元描述语言,允许开发者定义JSON数据的结构约束,包括字段类型、必填项、枚举值、嵌套结构等,被广泛用于API文档自动生成(如OpenAPI/Swagger规范)、前后端数据契约验证以及配置文件校验场景——大模型的Function Call借鉴了这套描述语言,使模型输出的工具调用指令具备机器可直接解析的结构化特征。这意味着开发者设计一套工具Schema,理论上可以在不同模型间复用,大幅降低了多模型切换的迁移成本。
Schema的结构设计
作者将工具Schema设计为分层结构:最上层是工具描述(说明这个工具的用途),下层是参数定义。每个参数需要明确:
- 参数类型:字符串、数字还是布尔值
- 参数说明:对该参数的详细解释
- required属性:该参数是否必填
这套格式并非随意规定,而是要尽量与模型训练时的工具格式保持一致,这样推理时模型才能准确解析、决定调用哪个工具并传入正确参数。
用大模型自动生成Schema
这是本文最巧妙的设计之一。传统做法(如某些同类教程)要求开发者严格按照Google或NumPy的标准注释格式书写函数注释,再用大量代码解析——规范但严苛,注释稍有偏差就解析失败。
作者的解法是:让大模型来完成注释到Schema的转换。流程如下:
- 用BaseModel定义目标Schema结构
- 将函数注释(
function.__doc__)拼进提示词 - 要求大模型按JSON格式输出结构化Schema,不附带多余内容
- 转成JSON结构后输出
考虑到大模型的随机性,作者设计了循环三次的重试机制——一次失败不代表下次也失败,三次仍失败则大概率无法转换,直接报错即可。这样开发者写注释可以相当随意,只要描述清楚,就能被自动解析。

MCP服务:把远程工具镜像成本地函数
本地工具问题解决了,但很多工具实际部署在远程的MCP(Model Context Protocol)服务上,本地无法直接调用。
MCP是由Anthropic于2024年底开源的标准化协议,旨在解决AI模型与外部工具、数据源之间集成碎片化的问题。类比USB-C接口统一了硬件连接标准,MCP为AI工具调用提供了统一的通信规范,涵盖工具发现、调用请求和结果返回的完整流程,使不同服务商提供的工具能够以一致的方式被AI模型消费。
MCP协议的深远意义还在于它定义了工具发现(Tool Discovery)机制——Agent无需在部署时硬编码工具列表,而是能够在运行时动态向MCP服务器查询其提供的工具能力及对应Schema。这使得工具生态具备了真正的可扩展性:新工具上线后,无需修改Agent主体代码,系统即可自动感知并纳入调度。这一设计思路与微服务架构中的服务注册发现机制(如Consul、Eureka)高度相似——服务提供方主动向注册中心登记自身能力,消费方按需查询与调用,是构建企业级AI工具平台的重要基础设施理念。
镜像的实现原理
作者的方案是"远程服务镜像"——把远程MCP服务直接镜像成本地工具函数。
通过get_tools获取远程函数的工具名称和描述,拼成一个函数体,实际执行时直接远程调用MCP。这些镜像出的本地函数无需落盘,直接加载进内存即可。
在Demo中,一个远程MCP服务提供了两个工具:查询天气(对接阿里云官网真实数据)和货币汇率兑换(为演示方便使用随机值)。镜像后,它们在本地就变成了两个普通的本地函数。
MCP标准化协议的核心价值
这里凸显了MCP这类标准化协议的关键意义。作者打了个比方:如果没有统一标准,张三搞一套服务、李四搞另一套,每个人对外的接口都不同,做远程镜像就要为每个服务单独适配,成本极高。
有了MCP统一标准,任何服务都能用一套逻辑转成本地工具函数。 这样在主函数中,本地工具(百度搜索、获取时间、加法等)与MCP工具就能统一管理,整个结构非常清晰。

双模型调度:分发模型与聊天模型的分工
整个Agent的执行流程可以概括为一个循环:用户输入 → 思考(是否需要调用工具)→ 调用工具 → 返回结果 → 再次思考 → … → 直到无需工具,给出最终回答。
比如"查询北京和上海天气"会触发两轮工具调用:第一轮查北京,第二轮查上海,最后汇总总结。
为什么需要两个模型
作者在标准流程上做了一个关键改进——引入双模型架构:
- 分发模型(Dispatch):使用能力更强的模型,负责判断是否需要调用工具以及调用时的参数生成,这一步对模型推理能力要求较高。
- 聊天模型(Chat):使用能力相对较弱、成本更低的模型,专门处理闲聊对话。
双模型或多模型协作架构是企业级AI系统的常见成本优化策略,也被业界称为"LLM路由"(LLM Routing)。大型推理模型(如GPT-4o、Claude 3.5 Sonnet)的API调用成本通常是轻量模型(如GPT-4o-mini、Claude Haiku)的10至20倍。LLM路由的核心挑战在于分类器本身的准确性——过于激进的路由会将本需强模型处理的复杂推理错判为简单闲聊,导致输出质量下降;而过于保守则失去了成本节约的意义。业界已出现RouteLLM、Martian等专项研究方案,以及基于查询复杂度评估的动态路由和级联推理方案(先用小模型回答,置信度不足时升级至大模型),在保持用户体验的前提下可将API调用成本降低30%-70%。本文采用状态机驱动的规则路由,简单可靠,是工程实践中务实的起点。
系统通过状态机管理两种模式的切换(chat状态 vs tool状态)。**有限状态机(Finite State Machine,FSM)**是计算机科学中描述系统行为的经典形式化模型,由有限个状态、状态间的转移条件和对应动作三要素构成,在编译器词法分析、网络协议实现、游戏AI行为树等领域有广泛应用。在Agent系统中引入状态机,可以将复杂执行流程分解为明确的状态集合,每个状态对应特定的处理逻辑,状态转移由预定义条件触发,从而避免条件判断逻辑散落各处导致的维护困难。LangGraph等主流框架正是将有向图作为状态机的可视化表达,通过节点代表状态、边代表转移条件,构建可调试、可回溯的Agent执行流,这也是其核心设计理念所在。

上下文精简的工程智慧
这里有一个容易被忽视却极其重要的细节。在思考(判断是否调工具)阶段,作者会把工具Schema和一段临时引导message放进去诱导模型调用工具,但这些临时信息不会进入正式上下文。
原因在于:上下文过长会影响大模型效果。工具Schema只在调度模型那一步使用,正式对话时并不携带,让模型输入更短、有效信息密度更高。这一设计与前文提及的"Lost in the Middle"研究结论高度呼应——主动控制上下文长度、剔除阶段性噪声信息,是提升模型稳定性的工程必选项,而非可选的优化项。
这也解释了一个业界现象:为什么很多公司做Demo时会用LangGraph、Swarm等框架,但项目做深了以后反而倾向于自研实现。核心原因正是灵活性——想要什么就写什么,想去掉什么就去掉什么。当业务有大量特殊需求时,现成框架的种种限制反而成了障碍。
短期记忆:Agent的"记性"从哪来
Demo中有个有趣的演示:直接问模型"我是谁",原生模型当然不知道;但告诉它"我是皮坦爸爸"后再问,它就能答出来。这就是短期记忆能力的体现。
实现依赖一个Memory Manager——把多轮对话信息全部存储起来,作为短期记忆注入上下文。
大模型的无状态本质决定了记忆系统必须依赖外部工程实现。业界通常将对话记忆分为四个层次,各有其适用场景与权衡:
- 对话缓冲记忆(Buffer Memory):保留完整的历史对话序列,信息无损但Token消耗随对话轮次线性增长,本文实现的Memory Manager即属此类,最为直观,适合理解记忆系统的基本原理。
- 滑动窗口记忆(Window Memory):只保留最近N轮对话,在Token效率与短期连贯性间取得平衡,适合对话轮次较长但无需追溯远期历史的场景。
- 摘要记忆(Summary Memory):定期用模型将历史对话压缩为摘要,以少量Token换取较长的历史感知,但存在摘要失真风险,关键细节可能在压缩中丢失。
- 向量检索记忆(Vector Memory):将历史对话向量化后存入Faiss、Chroma、Weaviate等向量数据库,按语义相关性按需检索,是实现"长期记忆"的主流方案,也是RAG技术在记忆场景的具体应用。
作者也指出,如果要做得更完善,可以:
- 存入Redis实现更持久的缓存
- 落库到数据库实现长期记忆
玩法可以有很多种,但核心思路一致:用工程手段弥补大模型天生的无状态缺陷。 大模型每次推理都是独立的无状态过程,它并不天然"记得"上一轮说了什么——所谓记忆,本质上都是将历史对话序列化后重新塞回输入,工程化地模拟出连续对话的效果。
结语:智能体的本质是工程封装
这篇从零手撸Agent框架的实录,最大的价值在于"祛魅"。当你亲手实现了Function Call的Schema解析、MCP的远程镜像、双模型的状态调度以及记忆管理,你会得出和作者一致的结论:
智能体与AI算法本身关系并不大,它更多是一系列工程化的良好封装。
对于处于学习或过渡期的开发者而言,与其一味调用黑盒框架,不如动手把每个环节实现一遍。理解了底层逻辑,无论是应对"提示词四大局限"这类面试问题,还是在真实业务中做深度定制,都会游刃有余。
核心要点
相关推荐

美墨边境缉毒实录:CBP多层次拦截体系与技术解析
深度解析美国海关与边境保护局(CBP)在圣地亚哥地区的缉毒行动,涵盖行为识别、缉毒犬协作、便携式光谱检测、空运货物查验及高速公路追踪等多层次拦截技术与实战案例。

AMD CDNA5架构深度解析:技术演进与AI算力竞争格局
深度解析AMD CDNA5架构的技术方向,包括Chiplet封装升级、HBM内存演进、低精度计算优化等核心看点,分析AMD如何通过下一代Instinct加速器挑战NVIDIA在AI芯片市场的主导地位。

Netflix信任练习变解雇陷阱:企业信任的边界在哪
Netflix员工在团建信任练习中分享隐私后遭解雇,引发科技圈热议。本文深入分析企业信任练习的风险、Netflix文化的双刃剑效应,以及员工如何在职场坦诚与自我保护之间找到平衡。