从Demo到生产:Agent核心技术全景解析——MCP、Skill、Function Calling与大规模工具治理
从Demo到生产Agent核心技术全景解析——MCP、Skill、Function Calling与大规模工具治理本文面向有一定LLM开发基础的工程师从底层交互原理到生产级架构设计完整拆解Agent生态的核心组件、交互逻辑与大规模落地难点。全文贯穿「LLM是推理引擎Agent是调度框架」的核心认知所有知识点均对应工业界落地实践。阅读指南新手开发者建议从第1-3章按顺序阅读建立完整的认知框架有经验的Agent开发者可直接跳转至第4章「生产级难题大规模工具治理」这是从Demo到生产的核心门槛架构师重点关注第4章的并发调度与返洪治理体系以及各方案的ROI权衡术语表统一认知术语定义LLM大语言模型仅负责文本/结构化输出推理无执行能力Agent运行在LLM之上的调度框架负责工具调用、流程控制、结果回填Tool可被调用的能力单元抽象分为本地Tool和MCP ToolMCPModel Context ProtocolAnthropic推出的工具远程调用标准协议SkillPrompt层的场景化剧本用于约束LLM的行为流程Function CallingLLM调用外部工具的标准机制OpenAI命名Anthropic称为Tool UseHandoff多Agent架构中父Agent将任务委托给子Agent的机制Context WindowLLM单次推理可处理的最大Token长度限制第一章基础认知——LLM与Agent的边界核心中的核心绝大多数Agent开发者的第一个误区是认为Agent的能力是LLM自带的。事实上二者是完全分离的⭐LLM是纯推理引擎Agent是调度框架二者通过Function Calling接口通信LLM本身没有任何执行能力它既不知道什么是文件、什么是数据库也不知道如何调用外部API。它能接触到的只有两个结构化输入messages对话历史包含system系统提示、user用户输入、assistantLLM历史输出、tool工具返回结果四种角色tools工具列表每个工具包含name名称、description功能描述、parameters参数JSON Schema除此之外LLM对外部环境一无所知——它不知道工具是本地函数还是远程服务不知道Skill的存在甚至不知道自己是运行在Agent框架中。1.1 单轮Agent-LLM交互全流程裸API版我们用最原始的OpenAI API调用还原一次完整的工具调用流程这也是所有Agent框架的底层逻辑Step 1Agent接收用户请求组装输入用户提问北京天气咋样顺便查订单888Agent框架完成三件事将系统提示含Agent身份、全局规则和Skill内容拼入system消息将本地Tool和MCP Tool统一注册到tools数组将用户问题拼入user消息最终发给LLM的请求如下简化版{model:gpt-4o,messages:[{role:system,content:你是智能助手。\n\n[Skill: 天气查询] 用户问天气时必须调用get_weather工具\n[Skill: 订单查询] 用户问订单时必须调用query_order工具},{role:user,content:北京天气咋样顺便查订单888}],tools:[{type:function,function:{name:get_weather,description:查询指定城市天气需传入city参数,parameters:{type:object,properties:{city:{type:string}}}}},{type:function,function:{name:query_order,description:查询订单详情需传入order_id参数,parameters:{type:object,properties:{order_id:{type:string}}}}}],tool_choice:auto}Step 2LLM推理输出工具调用请求LLM根据system中的Skill规则和tools中的描述判断需要调用两个工具输出结构化tool_calls而非自然语言{choices:[{finish_reason:tool_calls,message:{role:assistant,tool_calls:[{id:call_weather_001,type:function,function:{name:get_weather,arguments:{\city\: \北京\}}},{id:call_order_001,type:function,function:{name:query_order,arguments:{\order_id\: \888\}}}]}}]}⭐ 注意此时LLM的生成过程已经终止它在等待Agent框架执行工具并返回结果不会直接回答用户问题。Step 3Agent执行工具回填结果Agent框架拦截tool_calls根据工具名称路由到对应的执行器get_weather是本地Tool直接调用Python函数get_weather(北京)返回15℃, 晴query_order是MCP Tool通过MCP Client向远程MCP Server发送JSON-RPC请求返回已发货顺丰SF123框架将结果包装为tool角色的消息必须携带对应的tool_call_idLLM通过这个ID匹配调用请求和返回结果追加到messages中{role:tool,tool_call_id:call_weather_001,content:15℃, 晴}{role:tool,tool_call_id:call_order_001,content:已发货顺丰SF123}Step 4LLM二次推理生成最终回答Agent将更新后的messages再次发给LLM此时LLM已经拿到了工具返回结果finish_reason变为stop输出自然语言回答北京今天15℃晴体感舒适。您的订单888已发货由顺丰承运运单号SF123可通过顺丰小程序追踪物流。至此一次完整的Agent-LLM交互闭环结束。这个流程会循环执行直到LLM不再输出tool_calls这就是所谓的Agent Loop。第二章核心组件辨析——Skill、MCP、Tool的三层关系这三个概念是Agent生态中最容易混淆的部分我们从「LLM视角」和「Agent框架视角」两个维度拆解⭐ 三者处于完全不同的层级Tool是能力抽象层MCP是协议传输层Skill是Prompt编排层2.1 ⭐Tool能力单元的抽象Tool是所有可被调用的能力的统称是连接LLM和外部世界的桥梁。无论工具的实现方式如何在LLM视角中都是tools数组中的一个条目本地Tool运行在Agent框架进程内的函数比如read_file、bash框架直接调用无网络开销MCP Tool运行在远程MCP Server上的工具框架通过MCP协议转发调用请求支持跨进程、跨机器部署LLM完全无法区分这两类Tool的差异它只根据description判断是否需要调用根据parameters填充参数。2.2 ⭐MCP工具的远程调用标准协议在MCP出现之前每个Agent框架都需要为每个外部工具编写适配代码工具开发者也需要为不同框架开发不同SDK形成了严重的生态碎片。MCP解决了这个问题它定义了统一的JSON-RPC协议规定了工具发现tools/list、工具调用tools/call、进度通知notifications/progress等标准方法。只要工具实现了MCP Server任何兼容MCP的Agent框架都可以直接调用无需额外适配。⭐ MCP的核心价值是「解耦」工具开发者不需要关心调用方的框架Agent框架不需要关心工具的实现细节二者通过标准协议通信。2.3 ⭐SkillPrompt层的场景化剧本Skill是Agent框架层的概念本质是一段增强Prompt 触发规则 步骤约束用于解决两个问题LLM选Tool不准当注册的工具过多时LLM容易选错工具Skill可以通过明确的规则引导LLM决策复杂流程难以维护多步骤任务比如代码Review需要先diff、再lint、最后生成报告如果完全依赖LLM自主决策稳定性极差Skill可以将流程固化Skill不会被LLM识别为一个独立的Tool而是被Agent框架拼入system消息中作为LLM推理的上下文。例如一个code-review.skill的内容可能如下# Code Review Skill ## 触发条件 用户提及「review」「代码审查」「检查代码」 ## 执行步骤 1. 调用git_diff工具获取最近一次提交的变更 2. 调用lint工具检查代码规范问题 3. 结合上述结果按以下模板输出报告 - 变更概述 - 规范问题如有 - 性能风险如有 - 改进建议 ## 约束 - 禁止修改用户代码 - 报告必须使用中文避免技术黑话⭐ Skill的本质是「给LLM的干活说明书」它不改变LLM的调用能力只改变LLM的决策逻辑。2.4 三者的关联与映射组件LLM视角Agent框架视角作用Skillsystem消息中的一段文本Prompt编排模块负责注入和触发约束LLM的决策流程MCPtools数组中的普通条目工具注册模块负责拉取MCP Server的工具列表标准化远程工具调用Tooltools数组中的条目工具执行模块负责路由和执行提供具体的能力单元第三章多Agent架构——从单兵到军团当任务复杂度提升单个Agent会出现上下文膨胀、职责混乱、成本失控等问题此时需要引入多Agent架构。首先要明确一个核心区别⭐子Agent是独立的LLM会话实例Skill是同一会话下的Prompt切换3.1 多Agent的四种经典拓扑1. 监督者模式最常用监督者Agent / | \ 订单Agent 退款Agent 物流Agent只有监督者Agent直接与用户交互负责意图识别和任务分发子Agent只负责单一领域的任务完成后将结果返回给监督者子Agent之间不直接通信所有交互通过监督者中转适用场景客服分流、工单分类等职责清晰的场景代表框架OpenAI Agents SDK的handoffs机制2. 分层模式监督者 ├── 订单Agent │ ├── 查询Agent │ └── 退款Agent └── 技术Agent ├── 代码Review Agent └── 测试Agent监督者之下有多层子Agent每层只负责下一层的任务分发适合业务逻辑本身有层级结构的场景比如企业内部的部门-小组架构优势是职责边界清晰缺点是层级过深会导致延迟增加3. 网状模式群聊模式代码Agent ↔ 审查Agent ↔ 测试Agent ↑ ↑ └───── 共享消息池 ───┘没有固定的监督者多个Agent在同一个共享消息池中轮流发言每轮由一个Agent发言其他Agent可以看到全部历史消息下一个发言者由规则或专门的「发言选择器」决定适用场景头脑风暴、代码评审等多角色协作场景代表框架AutoGen的GroupChat4. 共享黑板模式AgentA AgentB AgentC \ | / └─ 共享State ─┘没有直接的Agent间通信所有Agent读写同一份共享State框架的调度器决定每轮由哪个Agent执行执行完成后更新State优势是状态可追溯、支持断点恢复缺点是调度逻辑复杂代表框架LangGraph的StateGraph3.2 Agent间的交互方式1. Handoff委托监督者Agent的LLM输出transfer_to_xxx的结构化指令Agent框架拦截后创建新的子Agent实例将原任务的摘要传递给子Agent子Agent执行完成后返回结果给监督者。⭐ 核心是上下文隔离子Agent看不到监督者的全部历史消息只接收必要的任务信息避免上下文膨胀。2. Tool伪装轻量多Agent将子Agent封装为一个Tool注册到主Agent的tools列表中。主Agent的LLM将子Agent视为普通Tool调用框架收到调用请求后创建子Agent实例执行任务返回结果作为Tool Result。这种方式的优势是实现简单缺点是不支持子Agent反向调用主Agent适合轻量级的职责拆分。3. 共享StateAgent之间通过读写共享State传递信息每个Agent只关注State中自己需要的字段执行完成后更新对应字段。这种方式适合长流程、多状态的任务比如科研助理、复杂数据处理 pipeline。第四章生产级难题——大规模工具治理核心干货前面的内容都是Demo级的基础当工具数量从几个增长到几百个单次工具调用返回结果从几百字增长到几万字时所有Demo级的方案都会失效。本章内容是工业界落地的核心经验。4.1 ⭐并发调度从一把梭到精细化控制LLM一次吐出20个tool_calls是常见现象但无脑并发asyncio.gather会带来灾难性的问题依赖冲突、资源耗尽、成本飙升。大厂的解决方案是分层调度1. 依赖解析构建DAG有向无环图框架首先对tool_calls做依赖分析区分三类工具只读工具read_file、grep、query_db等不修改外部状态可安全并发变更工具write_file、edit、send_email等修改外部状态必须串行执行避免竞态条件依赖工具比如read_file(A)的输出是write_file(B)的输入必须按顺序执行例如24个tool_calls中18个是只读工具6个是变更工具框架会将18个只读工具分成2批并发执行6个变更工具串行执行相比全串行效率提升8倍相比全并发避免了数据冲突。⭐ 关键优化减少LLM Round-Trip次数。每一次LLM调用都需要将全部上下文传给LLM分批处理的核心价值不是提高工具执行的并发度而是减少LLM调用的次数从而降低成本和延迟。2. Tool Necessity ScoreTNS过滤低价值调用当注册的工具过多时LLM容易出现「工具滥用」的问题——明明不需要调用工具却频繁发起调用。大厂会为每个工具计算TNS分数基于三个维度历史调用成功率成功率低于30%的工具TNS分数降低响应延迟平均响应时间超过10s的工具TNS分数降低用户反馈用户标记为「无用调用」的工具TNS分数降低当LLM发起TNS分数低于阈值的工具调用时框架会直接拦截并返回「工具暂时不可用」的模拟结果避免无效调用。3. 超时、重试、熔断三件套生产环境的工具调用必须具备容错能力大厂普遍采用三态生命周期管理PENDING → EXECUTING → FINALIZED ↓ FAILED / TIMEOUT超时控制不同类型的工具设置不同的超时时间用户可见的工具如查订单超时设为3s内部辅助工具设为30s日志类工具设为60s重试策略只读工具支持2次重试变更工具不支持重试避免重复修改状态熔断机制当某个工具的连续失败率超过10%时自动熔断5分钟期间所有对该工具的调用直接返回失败避免级联故障4. 异步解耦避免Agent Loop阻塞如果工具执行时间长达30sAgent Loop会被阻塞30s严重影响用户体验。大厂的解决方案是将工具执行和Agent Loop解耦Agent收到LLM的tool_calls后将调用请求写入WAL预写日志发送到消息队列如Kafka专门的Tool Executor集群异步执行工具调用执行完成后将结果写入RedisAgent Loop定期检查Redis中是否有对应结果有则回填并继续循环无则返回「任务处理中」的临时回复给用户这种方式下Agent不会被长时间运行的工具阻塞支持高并发场景。4.2 ⭐返洪治理从烧Token到精准控流用户之前提出的「先summary不是浪费Token吗」是一个非常典型的误区。事实上不控制工具返回结果的规模会带来更严重的成本和质量问题超过Context Window上限直接导致API调用失败前面所有的输入成本全部白费即使没超过上限过长的上下文会导致LLM推理速度下降、幻觉概率上升后续对话质量大幅降低大厂的解决方案是四层防御体系从根源上避免长结果进入Agent Loop第1层源头拦截——MCP Server侧分页⭐ 这是最有效的一层防御在工具返回结果之前就把规模控制住。MCP协议明确要求对于返回大量数据的工具如SQL查询、日志拉取必须支持游标分页{summary:{total:428,failed_count:12},top_items:[{id:INC-1842,status:open,created_at:2026-01-01}],next_cursor:eyJpZCI6MTg0Mn0}第一层只返回统计摘要和Top N条核心数据总数据量控制在1000Token以内LLM根据摘要判断是否需要更多数据如需则携带next_cursor发起第二次调用获取下一批数据这种方式下80%的请求都不需要获取全量数据从源头避免了返洪问题第2层单条截断——Micro-Compact对于无法通过分页控制规模的工具如读取单个大文件框架会在工具返回后、回填LLM之前做截断单条Tool Result超过10000字符时保留首尾各2000字符中间插入[...内容过长已截断...]⭐ 关键规则错误结果不截断。如果工具返回的是错误信息必须保留完整内容否则LLM无法诊断错误原因代表实现OpenAgent SDK的micro_compact_messages函数阿里AgentScope的tool_result_limit配置第3层上下文压缩——Auto-Compact即使单条Tool Result控制住了随着对话轮次增加整个messages的长度也会逐渐逼近Context Window上限。框架会定期触发Auto-Compact当上下文使用率达到70%时触发压缩将历史对话除了最近的20%内容发送给LLM要求压缩为一条摘要替换原有的历史消息保留最近N轮对话的完整内容避免信息断层代表实现Google ADK的EventsCompactionConfig设置compaction_interval3每3轮压缩一次overlap_size1保留最近1轮完整内容第4层超大卸载——Offload到磁盘对于超过1MB的超大型结果如50MB的日志文件即使截断也无法满足要求此时框架会将结果卸载到本地磁盘只将文件路径回填给LLM{role:tool,tool_call_id:call_log_001,content:日志文件过大已保存至/path/to/log.txt可使用read_file工具指定offset和limit读取特定片段}LLM后续如果需要查看具体内容可以调用read_file工具指定偏移量和长度按需读取避免一次性加载全部内容。4.3 成本账为什么Summary是值得的回到用户之前的问题「先summary不是浪费Token吗」我们假设一个场景Context Window剩余50k Token工具返回结果50k Token后续还有10轮对话。不Summary的成本直接塞入50k Token导致后续每轮对话都需要额外处理这50k Token10轮对话额外消耗500k Token上下文过长导致LLM推理速度下降50%用户体验变差极端情况下超过Context Window上限任务失败前面所有成本全部白费Summary的成本额外消耗50.5k Token50k输入0.5k输出约0.26美元后续对话只需处理0.5k Token的摘要速度和质量都有保障显然Summary的成本远低于不Summary的隐性成本ROI极高。这也是为什么所有生产级Agent都必须内置上下文压缩能力的原因。第五章生产级最佳实践清单最后我们将前面的知识点浓缩为可落地的实践清单方便读者直接应用到项目中Skill编写规范开头明确「触发条件」帮助框架精准召回避免误触发显式声明「覆盖规则」比如「本场景忽略全局简洁回答要求输出详细报告」避免和Agent自带Prompt冲突只写流程约束不要在Skill中重复定义Tool的Schema避免和MCP Server的定义不一致优先使用按需召回模式避免将所有Skill全量注入System Prompt节省TokenMCP Server设计规范所有返回大量数据的工具必须支持游标分页默认返回摘要Top N结果工具描述必须清晰准确避免歧义LLM完全依赖描述选择工具实现notifications/progress接口长时间运行的任务定期发送进度通知避免Agent误认为任务超时错误返回必须包含明确的错误码和错误信息方便LLM诊断问题Agent调度配置建议只读工具并发数不超过10变更工具必须串行执行设置Tool Necessity Score阈值拦截低价值调用为不同类型的工具设置差异化超时时间变更工具禁用重试开启Auto-Compact设置触发阈值为70%保留最近20%的上下文成本控制技巧子Agent使用小模型如GPT-4o-mini只有主Agent使用大模型降低整体成本非关键工具调用使用低优先级队列错峰执行定期分析工具调用日志下线低使用率、低成功率的工具对高频、稳定的工具调用结果做缓存避免重复调用结语Agent开发的核心矛盾是在LLM的「灵活性」和系统的「可控性」之间寻找平衡。Function Calling给了LLM调用外部世界的能力Skill给了LLM遵循流程的能力MCP给了工具标准化的能力而并发调度和返洪治理则是让这些能力在生产环境中稳定运行的保障。从Demo到生产差的不是某一个神奇的技巧而是一整套体系化的设计和工程实现。希望本文能帮助你在Agent开发的道路上少走弯路真正把Agent的能力落地到业务场景中。附录推荐阅读Anthropic MCP官方文档https://modelcontextprotocol.io/OpenAI Agents SDK文档https://platform.openai.com/docs/agentsLangGraph State Managementhttps://langchain-ai.github.io/langgraph/concepts/low_level/阿里AgentScope 2.0技术白皮书https://modelscope.cn/docs/AgentScope/intro

相关新闻