从 MCP 到扣子:Agent 平台化演化路径

📅 2026/7/11 20:00:24
从 MCP 到扣子:Agent 平台化演化路径
本文档假设读者已经了解 MCP 协议本身的调用机制initialize 握手、tools/list、tools/call、stop_reason 循环判断等不再重复讲解协议细节。这里聚焦的是从一次裸的模型调用到扣子/百炼这种平台化 Agent中间每一步是为了解决什么问题、具体是怎么实现的。演化总览每一步都是在解决上一步遗留的具体工程问题不是凭空设计出来的下面逐个拆开讲。阶段0裸调用 一问一答没有工具没有循环 ↓ 阶段1接入 MCP 工具接入标准化 ↓ 阶段2加上循环 从一次调用变成自主决策循环这一步开始叫 Agent ↓ 阶段3配置化 Agent 定义从写死在代码里变成数据库里的一条配置记录 ↓ 阶段4服务化 配置被发布成一个可远程调用的 HTTP 接口AK/令牌鉴权 ↓ 阶段5多租户运行时 执行引擎做成无状态共享服务不为单个 Agent 常驻资源 ↓ 阶段6状态外置 会话历史、执行现场从进程内存搬到外部存储支持中断恢复 ↓ 阶段7推理层独立 大模型推理单独拆成常驻共享集群和执行引擎解耦阶段 0 → 1为什么要引入 MCP阶段 0 的问题一个 Controller 直接拼 messages 发给 Claude API模型只能凭自己已有的知识回答接触不到外部实时数据天气、订单、知识库。如果想让模型能查天气最直接的做法是在代码里写死一个get_weather()函数塞进 tools 参数里——能用但每加一个新工具就要改一遍代码、重新发布。如果这个工具还想给别的项目复用得把代码复制一份过去工具的实现和调用逻辑散落在各个业务代码里没有统一的接入方式。阶段 1 怎么解决把工具这个概念从业务代码里剥离出来做成独立进程/服务MCP Server用标准协议MCP暴露给任何 Host 使用。Host 只需要实现一次 MCP Client 逻辑就能对接市面上所有遵循 MCP 协议的工具工具本身可以被多个项目复用不需要每个项目各写一份。这一步解决的是“工具接入的标准化和复用性”问题跟要不要自主循环完全无关——阶段 1 结束时系统依然可能是一次调用、最多调一次工具这种简单模式。阶段 1 → 2为什么要加循环这一步开始叫 Agent阶段 1 的问题调用一次工具后谁来决定要不要再调下一个工具“什么时候该把结果整理成文字回复用户”如果这个判断需要人工介入比如工程师看到stop_reason: tool_use后手动写代码触发下一步、手动判断循环该不该停系统就没办法自动化处理复杂任务比如先查城市编码再用编码查天气最后总结成一句话这种多步骤任务。阶段 2 怎么解决把要不要继续调工具、什么时候停这个判断逻辑写成一个自动化循环——读stop_reason字段是tool_use就自动执行工具并把结果喂回去是end_turn就自动结束返回结果全程不需要人工介入。这个自动化循环本身就是 Agent 和普通单次工具调用的分界线。这一步解决的是“自主性”问题系统从人工按步骤驱动变成模型自己驱动多步骤任务。到这里为止Agent 已经具备完整能力了只是它还是写死在某个具体项目代码里的——比如你们的 Copilot这套循环逻辑是 Copilot 专属的换一个项目就得重新实现一遍。阶段 2 → 3为什么要配置化这是走向平台的分水岭阶段 2 的问题Copilot 这类系统的循环逻辑、system prompt、工具列表全部是代码里的常量。如果业务方想要一个客服 Agent另一个业务方想要一个数据分析 Agent两者的模型选择、提示词、挂载的工具完全不同——按阶段 2 的做法每换一种 Agent 都要重新写一份代码、重新部署一套服务普通业务人员完全没法参与只能靠工程师一个个写。阶段 3 怎么解决把一个 Agent 是什么这件事从写在代码里的常量抽象成存在数据库里的一条配置记录——模型选哪个、system prompt 内容、关联哪些工具对应哪些 MCP Server 或平台内置插件、挂哪个知识库全部字段化存进一张表。执行循环的代码只写一份通用执行引擎运行时现读这条配置、现组装请求而不是把这些信息硬编码在执行代码里。这一步是执行逻辑和Agent 定义解耦的关键执行引擎变成了可以服务任意 Agent 配置的通用组件普通用户在控制台上填表单、点几下鼠标就能拼出一个新的 Agent不需要工程师写代码、不需要重新部署服务。这正是阿里云百炼、字节扣子这类平台零代码/低代码搭建智能体能力的底层实现原理。阶段 3 → 4配置怎么变成一个可以远程调用的服务阶段 3 的问题一条数据库配置记录只在平台自己的控制台里能用比如在网页上跟它对话调试业务方的系统没办法通过代码去调用它没法集成进自己的产品里。阶段 4 怎么解决——发布这个动作具体做了什么给这条配置记录分配一个全局唯一标识阿里云叫 APP_ID扣子叫 Bot_ID本质上就是这条数据库记录的主键对外暴露出来生成一个固定的 HTTP Endpoint 路由比如阿里云百炼的应用调用地址是https://dashscope.aliyuncs.com/api/v1/apps/{APP_ID}/completion路径里的{APP_ID}就是用来在这次请求里定位是哪条配置配一层鉴权机制防止任何人拿着 APP_ID 就能白嫖调用阿里云用 DASHSCOPE_API_KEYAK权限归属于某个业务空间同空间内的 AK 可以调用空间下所有已发布的应用扣子用个人访问令牌PAT前缀pat_简单场景用权限等同你的账号、服务端专属令牌SAT前缀sat_企业版专属用于后端常驻服务、或者标准 OAuth2 流程应用先用私钥签发 JWT拿 JWT 去换短期 access token代表某个终端用户身份实现多用户会话隔离。调用方发请求时带上 APP_ID/Bot_ID 鉴权凭证平台服务端收到请求后第一步就是拿这两个信息去查这个凭证有没有权限调用这个配置、这个配置具体内容是什么。这一步解决的是“可远程调用性”问题一条数据库配置通过分配 ID 固定路由 鉴权这三件事变成了一个标准的、可以被任意外部系统集成的 HTTP 服务接口。阶段 4 → 5配置能被远程调用了执行的时候资源怎么分配阶段 4 遗留的问题知道调哪条配置了但真正执行这个 Agent 的循环逻辑是用什么资源去跑的如果给每个 APP_ID/Bot_ID 都分配一个专属的常驻进程或容器等着随时被调用——问题很明显平台上有几百万个用户创建的 Agent其中绝大多数长期没人调用24 小时常驻等于给几百万个空转的进程占着资源不做事成本完全扛不住。阶段 5 怎么解决不为单个 Agent 分配专属资源而是做一套无状态、多租户共享的执行引擎服务集群。以扣子开源的 Coze Studio 为例它的后端是一套 Golang 微服务采用领域驱动设计DDD原则构建核心是常驻运行的coze-server服务——这是所有租户共用的同一份代码不是一个 Agent 一个容器的关系。具体执行流程请求带着 APP_ID/Bot_ID 和鉴权信息进来执行引擎的某一个任意一个实例接手这个请求从数据库现查这条配置记录模型、prompt、工具列表用通用的循环逻辑阶段 2 讲的那套 chatLoop去执行其中如果配置里关联了外部工具这一步会走 MCP 协议或平台内置插件协议去调用执行完这个实例被释放回到资源池等待处理下一个请求可能是另一个用户、另一个完全不同的 Agent 的请求。这一步解决的是“规模化成本”问题只有真正发生调用的那一刻才消耗计算资源Agent 本身闲置时不占任何执行资源这也是为什么平台能免费、无限量地让用户创建 Agent——创建这个动作本身几乎零成本阶段 3 已经把它变成了一条数据库记录。阶段 5 → 6多轮对话、长耗时任务状态怎么保证连续阶段 5 遗留的问题既然执行引擎是任意实例都可能接手那一个用户跟同一个 Agent 进行多轮对话时第二轮请求万一被另一台机器上的另一个实例接手它怎么知道第一轮聊了什么如果历史状态存在第一个实例的内存变量里换一台机器接手就直接断片了。再进一步有些任务执行到一半需要暂停——比如工作流跑到某个节点需要用户确认才能继续这种暂停等待、之后再恢复的场景靠进程内存也无法跨请求保留。阶段 6 怎么解决把所有状态都外置存储不依赖任何一个具体进程的内存对话历史存进数据库/Redis用session_id/conversation_id作为检索键。下一轮请求进来不管被哪台机器接手都先按这个 ID 去外部存储里查出完整历史拼进请求里跟前面讲过的 Claude API 无状态调用的处理方式是同一个思路只是现在维护历史这件事从调用方自己做变成了平台代为维护。长任务的执行现场快照以 Coze 的工作流引擎为例节点执行到需要暂停时会把当前执行到哪个节点、所有变量的值、每个节点的状态、历史交互记录打包成一份快照ExecutionSnapshot通过一个外部状态存储接口StateStore写进持久化存储需要恢复时从存储里读出这份快照重建出完整的执行上下文继续跑。配合 SSEServer-Sent Events做流式通信服务端可以随时向客户端推送进度需要时抛出中断事件实现暂停-恢复的效果。这一步解决的是“状态和执行实例解耦”问题任何一台执行引擎的机器都是无状态、可替换的真正有价值的会话数据、执行进度全部在外部存储里这才是阶段 5 提到的水平扩容、故障转移能够安全实现的前提——机器可以随便宕、随便扩容只要外部存储没丢数据用户的对话和任务进度就不会丢。阶段 6 → 7模型推理这一层为什么不能跟着一起无状态化前六个阶段遗留的问题执行引擎可以做到用完即走、不为谁常驻但真正做推理计算的大模型呢模型权重动辄几十上百 GB加载到显存需要时间如果也跟执行引擎一样每次请求现加载现算完就释放每次推理前都要重新把模型权重灌进 GPU这个延迟是用户完全无法接受的。阶段 7 怎么解决把模型推理这一层单独拆成一套持续在线、常驻显存的独立服务集群通义千问、豆包等模型各自的推理集群跟执行引擎解耦——执行引擎每次需要推理时是发一个 HTTP/RPC 请求过去不需要自己管理模型加载。这套推理集群是所有 Agent、所有租户共享复用的靠整个平台的总请求量去做弹性扩缩容而不是为某一个具体 Agent 单独准备。这样整个系统里真正贵、需要一直开着的只有这一层前面几层Agent 配置、执行引擎、状态存储都可以做到按需伸缩、闲时几乎零成本。总结表每一步解决什么问题靠什么手段阶段遗留问题解决手段0→1工具接入没有标准代码耦合、不可复用MCP 协议Host ↔ Server 标准化通信1→2多步骤任务需要人工触发下一步自动化循环读 stop_reason 驱动这一步开始叫 Agent2→3Agent 定义写死在代码里不可配置、不可复用把 Agent 定义抽象成数据库配置记录执行引擎与定义解耦3→4配置只能在平台内部用业务系统调不到发布分配 ID 固定 HTTP 路由 鉴权AK/PAT/OAuth4→5为每个 Agent 分配专属资源成本扛不住无状态、多租户共享的执行引擎集群现查现执行现释放5→6状态依赖单个进程内存换机器/暂停就丢状态外置到数据库/Redis长任务做快照-恢复6→7模型推理不能像执行引擎一样按需加载推理层单独拆成常驻共享集群和执行引擎解耦一句话看懂整条演化路径MCP 解决的是工具怎么接循环解决的是怎么自主执行多步任务配置化解决的是怎么让 Agent 可复用、可被非工程师创建发布鉴权解决的是怎么被外部系统远程调用无状态执行引擎解决的是怎么用最低成本服务海量 Agent状态外置解决的是怎么保证多轮对话和长任务不因为换机器而丢失推理层独立解决的是真正昂贵的资源怎么共享复用。每一步都是对上一步在真实业务规模下暴露出的具体工程问题的针对性回应不是设计上的巧合。