ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

九周上线第二个Agent项目:MCP协议与工程化实践

九周上线第二个Agent项目:MCP协议与工程化实践 1. 为什么第二个 Agent 项目能九周上线1.1 从零造轮子的代价做过第一个 Agent 项目的人大概都有体会前三个月基本都在填坑。工具调用协议要自己定上下文管理要自己写状态机要自己维护重试和超时逻辑要自己兜底。等到真正开始写业务逻辑的时候人已经疲了。我第一个 Agent 项目从立项到勉强能用花了将近五个月其中至少三个月是在造基础设施。第二个项目就完全不一样了。九周上线听起来很激进但拆开看其实很合理——因为我们几乎没有从零写任何基础设施。Agent 框架用的是现成的工具调用协议用的是 MCP模型接入层用的是社区维护的 SDK连可观测性都是直接接的现成方案。我们做的事情本质上只有一件把业务逻辑和现成的基础设施对接起来。这个思路说起来简单但真正落地的时候有几个关键决策点需要想清楚。下面我把整个项目的设计思路、技术选型、实操过程和踩过的坑完整拆一遍。1.2 核心思路复用优先自建兜底整个项目的设计原则就一句话能复用的一律复用只有业务强相关的部分才自己写。具体来说我们把 Agent 系统拆成了四层层级职责来源模型接入层模型调用、流式输出、重试现成 SDK工具协议层工具注册、调用、结果回传MCPAgent 编排层任务规划、状态管理、循环控制现成框架业务逻辑层具体任务处理、数据转换自研前三层全部复用只有第四层是自己写的。这样做的直接好处是代码量少了将近 70%而且前三层的稳定性由社区保证我们不需要花精力去维护。但这里有个前提你得对现成基础设施的能力边界有清晰认知。如果盲目复用遇到框架不支持的需求时反而会更痛苦。所以选型阶段我们花了整整一周做技术调研把每个候选方案的优缺点都列出来对比。1.3 九周时间线拆解很多人好奇九周是怎么分配的我直接把实际的时间线列出来第 1 周技术选型 架构设计。确定用哪个 Agent 框架、哪个 MCP 实现、模型接入用哪套 SDK。第 2-3 周搭骨架。把模型接入、工具注册、Agent 循环跑通用一个最简单的 demo 验证整条链路。第 4-6 周业务逻辑开发。这是真正花时间的部分包括 prompt 设计、工具实现、数据处理。第 7 周联调 边界情况处理。各种异常场景、超时、重试、降级。第 8 周压测 性能优化。并发、缓存、流式输出调优。第 9 周灰度 上线。小流量验证逐步放量。可以看到真正写业务逻辑只有三周剩下六周都在做工程化的事情。这个比例其实很健康——Agent 项目的难点从来不是业务逻辑而是工程稳定性。2. 技术选型为什么是 MCP Python 现成框架2.1 MCP 协议到底解决了什么问题MCP 这个词最近热度很高但很多人其实没搞清楚它到底解决什么问题。用一句话概括MCP 是 Agent 和工具之间的标准接口协议。在没有 MCP 之前每个 Agent 框架都有自己的工具定义方式。LangChain 有一套AutoGPT 有一套你自己写的又有一套。结果就是你为一个框架写的工具换到另一个框架就得重写。MCP 的出现把这个事情标准化了——工具只需要实现一次 MCP 接口任何支持 MCP 的 Agent 都能直接调用。我们项目里用 MCP 主要解决三个问题工具复用社区已经有大量现成的 MCP 工具文件操作、数据库查询、HTTP 请求这些常见需求直接拿来用。解耦工具的实现和 Agent 的编排完全分离工具可以独立开发、独立测试、独立部署。可观测MCP 有标准的调用日志格式排查问题的时候非常方便。提示MCP 目前还在快速演进中选型时一定要确认你用的 Agent 框架支持的 MCP 版本不同版本之间可能有兼容性问题。2.2 Python 生态的取舍Agent 开发用 Python 几乎是默认选择原因很简单生态最全。模型 SDK、数据处理、Web 框架、异步编程Python 都有成熟的方案。但 Python 也有明显的短板主要是并发性能。我们项目对并发的要求不算特别高峰值 QPS 大概在 200 左右Python 的 asyncio 完全能扛住。如果你的场景需要更高的并发可能需要考虑 Go 或者 Rust但那样会牺牲开发效率。我的建议是先用 Python 把业务跑通真的遇到性能瓶颈再考虑换语言。过早优化是万恶之源。Python 版本我们用的是 3.11主要看中它的性能提升和更好的 asyncio 支持。依赖管理用 uv比 pip 快很多而且锁文件机制更可靠。2.3 Agent 框架选型的三个维度选 Agent 框架的时候我们主要看三个维度第一是否支持 MCP。这是硬性要求不支持 MCP 的框架直接排除。第二编排能力是否够用。有些框架只支持简单的 ReAct 循环复杂一点的任务规划就搞不定。我们选的是支持 DAG 编排的框架可以定义复杂的任务依赖关系。第三可观测性是否完善。Agent 的执行过程是个黑盒如果没有完善的日志和追踪出问题的时候根本无从下手。我们选的框架内置了 OpenTelemetry 支持可以直接接入现有的监控体系。具体是哪个框架我就不点名了因为这类框架迭代很快今天的推荐明天可能就过时了。关键是掌握选型的维度你自己去评估。3. 核心实现从骨架到业务逻辑3.1 搭骨架两小时跑通最小链路搭骨架的阶段我们的目标很明确用最少的代码跑通一条完整的 Agent 链路。具体来说就是用户输入 → 模型规划 → 调用工具 → 返回结果。这一步的关键是不要贪多。很多人一上来就想把所有的工具都接进去结果调试的时候根本分不清是哪个环节出的问题。我们的做法是先接一个最简单的工具比如获取当前时间把整条链路跑通确认模型调用、工具调用、结果回传都没问题再逐步加工具。最小链路的代码大概长这样import asyncio from agent_framework import Agent, MCPTool async def main(): agent Agent( modelyour-model, tools[MCPTool(get_current_time)], ) result await agent.run(现在几点了) print(result) asyncio.run(main())这段代码看起来简单但背后涉及的东西不少模型调用、prompt 组装、工具描述注入、结果解析、循环控制。这些都由框架处理了我们只需要关注业务逻辑。3.2 工具实现MCP 工具的开发要点MCP 工具的开发有一套固定的模式。一个标准的 MCP 工具需要定义三部分工具名称、参数 schema、执行逻辑。from mcp import tool tool def query_database(sql: str, limit: int 100) - list: 查询数据库并返回结果。 Args: sql: SQL 查询语句 limit: 返回结果的最大条数 # 实际执行逻辑 return execute_query(sql, limit)这里有几个容易踩的坑第一参数 schema 要写清楚。模型是根据 schema 来决定怎么调用工具的如果 schema 写得模糊模型就会乱传参数。每个参数都要有明确的类型和描述。第二工具描述要精准。描述太短模型不知道什么时候该用描述太长又会占用宝贵的上下文。我的经验是控制在 50-100 字说清楚这个工具做什么和什么时候用。第三错误处理要完善。工具执行失败的时候要返回明确的错误信息而不是直接抛异常。模型看到错误信息后可以决定重试还是换一种方式。注意MCP 工具的执行时间不宜过长超过 30 秒的工具建议改成异步任务模式先返回任务 ID再通过轮询获取结果。3.3 业务逻辑Prompt 设计的实战经验业务逻辑层最核心的工作是 prompt 设计。这块我踩过的坑最多分享几条实战经验。经验一系统 prompt 要短而精。很多人喜欢在系统 prompt 里写一大堆规则结果模型反而抓不住重点。我的做法是把核心规则控制在 5 条以内其他的通过工具描述和示例来引导。经验二用 few-shot 示例代替长篇说明。与其写一大段你应该这样做不应该那样做不如直接给两三个输入输出的例子。模型对示例的理解能力远强于对规则的理解能力。经验三给模型留退路。当模型无法完成任务时要有一个明确的我做不到的输出格式。否则模型会硬编一个答案反而更难排查。经验四prompt 要版本化。每次修改 prompt 都要记录版本和修改原因因为 prompt 的改动对效果的影响非常大没有版本管理的话根本回溯不了。3.4 流式输出提升用户体验的关键Agent 的响应时间通常比较长如果等全部处理完再返回用户会以为系统卡死了。所以流式输出是必须的。流式输出的实现分两部分模型输出的流式和工具调用状态的流式。模型输出的流式大部分 SDK 都支持直接开启 stream 模式就行。工具调用状态的流式需要自己处理我们的做法是在工具开始执行和结束执行的时候各发一个事件前端根据事件更新 UI。async for event in agent.stream(帮我查一下今天的订单): if event.type tool_start: print(f正在调用工具: {event.tool_name}) elif event.type tool_end: print(f工具执行完成: {event.tool_name}) elif event.type text: print(event.content, end)流式输出有个细节要注意工具调用的中间状态不要暴露太多技术细节。用户不需要知道你在调用哪个 API只需要知道正在处理中。技术细节放在日志里给开发看。4. 工程化让 Agent 稳定跑起来的关键4.1 并发处理Agent 怎么扛住 200 QPSAgent 的并发处理和普通 Web 服务不太一样因为每个请求的执行时间很长通常几秒到几十秒而且涉及多次模型调用和工具调用。我们的方案是异步 队列 限流三件套。异步是基础Python 的 asyncio 可以轻松处理几百个并发连接。队列用来缓冲突发流量避免瞬间打满模型 API 的配额。限流是保护下游服务防止工具调用把数据库打挂。具体参数上我们的配置是参数值说明最大并发请求数300超过则排队模型调用并发上限50受 API 配额限制单工具并发上限20保护下游服务请求超时120s超时自动取消队列最大长度1000超过则拒绝新请求这些参数不是拍脑袋定的是压测出来的。压测的时候重点关注两个指标P99 延迟和错误率。P99 延迟超过 30 秒就要考虑优化错误率超过 1% 就要排查原因。4.2 可观测性Agent 的黑盒怎么打开Agent 最大的问题是不透明。用户输入一句话中间发生了什么完全看不到。所以可观测性是工程化的重中之重。我们的做法是全链路追踪 结构化日志。每个请求分配一个 trace_id从入口到出口的所有操作都带上这个 ID。模型调用、工具调用、状态转换每个环节都记录开始时间、结束时间、输入输出。日志用 JSON 格式方便后续检索和分析。关键字段包括trace_id请求唯一标识span当前操作类型model_call / tool_call / state_transitionduration_ms耗时status成功/失败error错误信息如果有有了这些日志排查问题的时候可以直接按 trace_id 过滤把整个请求的执行过程完整还原出来。4.3 降级与容错模型挂了怎么办Agent 系统依赖的外部服务很多模型 API、工具背后的各种服务、数据库。任何一个挂了都会影响整体可用性。所以降级和容错是必须的。我们的降级策略分三级一级降级模型 API 超时或失败时自动重试 2 次。重试间隔用指数退避避免雪崩。二级降级重试仍然失败时切换到备用模型。备用模型可以是能力稍弱但更稳定的版本。三级降级所有模型都不可用时返回预设的兜底回复并记录告警。工具调用的容错类似但多了一个熔断机制。如果某个工具连续失败超过阈值直接熔断不再调用避免拖垮整个系统。提示降级策略一定要在测试环境充分验证否则真出问题的时候降级逻辑本身可能就是新的故障点。5. 踩坑记录与排查技巧5.1 常见问题速查表问题现象可能原因排查方法解决方案模型不调用工具工具描述不清晰检查工具 schema 和描述优化描述增加示例工具调用参数错误参数 schema 不明确查看模型输出的参数补充参数类型和描述响应时间过长工具执行慢或模型慢看 trace 各环节耗时优化慢环节加缓存并发上不去同步阻塞或连接池不足检查是否有同步调用改异步扩大连接池内存持续增长上下文未清理监控内存和对象数及时释放上下文流式输出中断网络问题或超时检查网络和超时配置增加心跳和重连5.2 三个印象最深的坑坑一工具描述里的隐藏字符。有一次模型死活不调用某个工具排查了半天才发现工具描述里混入了一个不可见字符导致模型解析失败。这种问题非常隐蔽建议工具描述写完后用工具检查一下有没有异常字符。坑二上下文无限增长。Agent 的多轮对话会把历史消息全部塞进上下文跑久了上下文越来越长不仅慢而且贵。我们的解决方案是滑动窗口 摘要保留最近 N 轮完整对话更早的对话用模型生成摘要。坑三工具调用的幂等性。有些工具比如创建订单重复调用会产生副作用。模型在重试的时候可能会重复调用同一个工具。解决方案是给工具加幂等键同一个键的重复调用直接返回缓存结果。5.3 性能优化的几个实用技巧技巧一工具结果缓存。很多工具的调用结果是可缓存的比如查询类工具。加一层缓存可以显著降低延迟和成本。缓存 key 用工具名 参数的哈希。技巧二并行调用无依赖的工具。如果模型一次要调用多个没有依赖关系的工具可以并行执行。我们的框架支持这个能力实测下来能省 30%-50% 的时间。技巧三prompt 精简。prompt 越长模型推理越慢。定期 review prompt删掉不必要的内容。我们有一次精简 prompt 后平均延迟降了 20%。技巧四模型分级。不是所有任务都需要最强的模型。简单任务用便宜快速的模型复杂任务才用强模型。我们按任务复杂度做了分级成本降了将近一半。6. 关于复用与自建的边界思考6.1 什么该复用什么该自建九周上线的核心经验就是复用优先但复用不是无脑复用。我的判断标准是该复用的协议标准MCP、模型接入、可观测性、通用工具。这些部分社区方案成熟自己写纯属浪费时间。该自建的业务逻辑、prompt、特定领域的工具、数据转换。这些部分和业务强相关没有现成方案必须自己写。边界模糊的Agent 编排逻辑。有些框架的编排能力够用有些不够用。这个需要根据具体需求评估。如果框架的编排能力覆盖了 80% 的需求剩下 20% 通过扩展实现那就用框架。如果只能覆盖 50%那可能自己写更合适。6.2 复用的隐性成本复用不是没有成本的。现成的基础设施虽然省了开发时间但带来了学习成本和约束。学习成本好理解你得花时间搞清楚框架怎么用、MCP 协议怎么实现。这部分成本通常在项目前期一次性投入。约束就比较麻烦了。框架有它自己的设计理念你的需求如果和框架的理念冲突就会很别扭。比如有些框架强制要求所有工具都是无状态的但你的业务需要维护会话状态这时候就得想办法绕过去。所以选型的时候一定要做概念验证用真实的业务场景去试看看框架能不能满足。不要只看文档文档里写的和实际用起来可能差很远。6.3 给后来者的建议如果你也在做 Agent 项目我的建议是第一先花一周做选型。不要急着写代码把可选方案都调研一遍做几个小 demo 验证。这一周的投入能省后面几个月的时间。第二骨架优先。先把最小链路跑通再逐步加功能。不要一上来就搞大而全。第三可观测性要早做。不要等到出问题了才想起来加日志。Agent 的调试难度远高于普通服务没有完善的日志根本没法排查。第四prompt 要当代码管理。版本化、review、测试一个都不能少。第五留足工程化的时间。业务逻辑可能只占 30% 的工作量剩下 70% 都是工程化。这个比例要提前有心理准备。我在第二个项目里最大的体会是Agent 开发的难点不在 AI在工程。模型能力已经足够强了真正决定项目成败的是工程化水平。把基础设施复用做好把工程稳定性做扎实九周上线完全可行。反过来如果基础设施从零造工程化又没做好那九个月也未必能上线。
返回列表