每次开始构建一个新的 Agent,我都会跟自己说:这次要设计得优雅一点。

然后大概写到第三个的时候,开始感觉不对劲。

不是功能不对,是结构开始重复——模型初始化的代码复制过来改一改,Prompt 直接硬编码在代码里,工具列表在构造函数里一个个手动注册。每个 Agent 看起来都挺独立,但你一眼看过去,这些代码基本上都长一个样。

更难受的是,你想改个 Prompt 试试效果,得改代码,然后重新部署。你想给某个 Agent 加一个新工具,也得改代码,再重新部署。Agent 还在跑着,但你没有办法在不停服的情况下更新它。

做过的人大概都有这种感受:明明每个 Agent 干的事情不一样,但构建和维护它们的痛苦却惊人的相似。


这不只是工程问题,是认知问题

在我真正意识到问题之前,我以为这只是「代码写烂了」的问题——多抽象几层,写个基类,加个接口,就解决了。

但后来我发现,这个判断本身就是错的。

因为我一直在用管理代码的方式去管理 Agent,而 Agent 根本不是普通的代码。

普通的代码,你写完它,它就确定了。但 Agent 是动态的:你每次调优 Prompt,Agent 的行为就变了;你给它换个模型,它的能力边界就变了;你改一组工具的组合方式,它能处理的任务范围就变了。Agent 的「身份」是可以独立于代码演进的——但只要 Agent 的定义还藏在代码里,这件事就做不到。

这才是真正的问题所在:我们把「Agent 是什么」和「Agent 怎么跑」混在了一起。


重复是因为我们没想清楚”变的”和”不变的”

回头看这些重复,根源其实很清晰。

每个 Agent 里,有些东西是不变的:推理引擎、工具调用的执行逻辑、记忆的读写、上下文的组装方式——这些是通用的基础能力,每个 Agent 都需要,但每个 Agent 写一遍,是在重复造同一台发动机。

有些东西是变的:这个 Agent 用哪个模型、Prompt 是什么、挂了哪些工具、可以调用哪些子 Agent——这些是这个 Agent 区别于其他 Agent 的真正原因。

把变的和不变的混在一起写代码,是让 Agent 管理越来越难的根本原因。

但更关键的一步,是把这两类东西的生命周期也分开

「不变的」那部分,走代码 review、工程测试、版本发布——节奏慢、成本高、风险低。「变的」那部分,应该走完全不同的通道:快速迭代、灰度验证、随时回滚——甚至不需要工程师介入,业务侧自己就能操作。

你不可能既要这种灵活性,又让两件事混在同一个代码库里。


解法:Agent Spec + 执行引擎

这里借鉴一个大家都熟悉的思路。

k8s 里你不会直接去操作某个容器,而是写一份 YAML,告诉 k8s「我要什么」:用哪个镜像、要几个副本、资源限制是多少。具体怎么拉镜像、怎么调度、挂掉了怎么重启——你不用管,控制面帮你搞定。

你描述的是意图,不是过程。

Agent 完全可以照这个思路来。

给每个 Agent 写一份 Agent Spec——一份声明式的配置文件,描述这个 Agent 是谁。

举个例子,假设你在做一个电商客服系统,里面有一个专门处理售后问题的 Agent:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 售后客服 Agent 的 Spec
promptKey: after-sales-assistant # 用哪个 Prompt
model: gpt-4o # 用哪个模型
mcpServers: # 挂哪些工具
- order-query-service # 订单查询
- refund-system # 退款系统
- logistics-tracker # 物流追踪
partnerAgents: # 可以转交给哪些兄弟 Agent
- complaint-escalation-agent # 投诉升级 Agent
- vip-service-agent # VIP 专属服务 Agent
memory:
storageType: redis
maxIterations: 8

一个通用的 Agent 执行引擎读取这份 Spec,动态组装出完整的运行时。这里有三个配套组件是让 Spec 真正能活起来的基础:

  • Prompt Center:Spec 里的 promptKey 只是一个指针,真正的内容在 Prompt Center 里管理——版本控制、灰度发布、效果对比都在那边,Prompt 能独立迭代的基础就在这里。
  • MCP Registry:Spec 里的 mcpServers 只是工具名字,执行引擎通过 Registry 发现实际服务地址和协议——这是工具能标准化、可插拔的基础。
  • Agent Registry:Spec 里的 partnerAgents 也只是名字,Agent 间能互相发现和调用,靠的是这层注册——多 Agent 协作能动态组合的基础。

Spec 是声明,三个 Registry 是实现。 没有这三个组件,Spec 就只是一份格式好看的配置文件;有了它们,Spec 才能成为真正驱动 Agent 运行的”意图描述”。

这套机制建立之后,日常的变更就变得极其简单:

你要新建一个「物流咨询 Agent」?照着写一份新的 Spec,换几个工具和 Prompt,启动引擎,完成。

你想针对春节大促优化一下售后话术?改 Prompt Center 里的版本,配个灰度比例,执行引擎监听到变更,热加载,不停服。

退款流程加了一个新的审批工具?在 Spec 里加一行工具名,MCP Registry 里注册一下,重载配置,生效。

整个过程,没有改一行执行逻辑的代码。


Spec 化带来的另一个推论:Agent 可以弹性扩缩容

这是很多人没想到的一个推论,但它其实是 Spec 化最重要的工程价值之一。

逻辑链是这样的:

Agent Spec 定义了 Agent 是谁 → 执行引擎动态组装运行时 → Agent 实例本身不需要持有任何状态。

这里的关键是状态外置。对话历史、用户上下文、中间推理结果——这些全部存入独立的 Session/Memory 服务,Agent 实例本身只负责”给我一个 Spec 和一条消息,我返回一个结果”。

一旦 Agent 变成无状态的,很多事情就变得可能:

  • 某个 Agent 实例挂了?立刻启动一个新实例,从 Session 服务里恢复上下文,用户无感知。
  • 某个 Agent 流量突然暴增?横向扩出更多实例,负载均衡,就像 k8s 扩 Pod 一样。
  • 低峰期流量下降?缩减实例,节省资源。

这和 k8s 管容器的逻辑是完全一致的——容器之所以能弹性扩缩,前提就是应用本身是无状态的,状态外置到数据库或缓存服务。Agent 的 Session/Memory 服务扮演的就是这个角色。

反过来也说明了一件事:很多团队现在构建的 Agent 天然无法扩缩——因为对话历史存在进程内存里,实例挂了状态就没了,更没法横向扩展。这不是 Agent 框架的问题,是架构选择的问题。Spec 化 + 状态外置,才是解决这件事的正确方式。


这套架构真正解放的,是迭代速度

光说「代码更整洁了」有点低估这件事的价值。

这套思路实际上是在把 AI 能力的迭代,从软件工程的交付节奏里解放出来

以前,业务侧发现某个 Agent 的回答在一个场景下答非所问,想调整一下 Prompt,正常流程是:提需求 → 排期 → 工程师改代码 → 测试 → 上线,可能要一两周。Prompt 这件事本质上是业务认知问题,跟工程师的软件能力毫无关系,但它被工程交付流程卡住了。Prompt Center 解决的就是这个问题——业务侧直接操作,24 小时内完成一个完整的调优循环。

工具层同理。MCP 协议把工具能力标准化成可发现、可插拔的服务,能力组合可以动态调整,不用每次改代码。

执行引擎的升级也是如此。想给所有 Agent 加统一的重试机制?引擎升级,所有 Agent 自动获益,和任何一个 Agent 的业务逻辑改了完全不相干,两件事可以并行发生。

当 Prompt、工具、引擎三件事都能独立迭代,整个 Agent 系统的演进速度是不一样的。


真正难的部分:语义对齐

工程架构能解决的,只是其中相对容易的那部分。

Spec 化之后,Agent 间的发现和连接问题是解决了。但多个 Agent 协作时,真正的难题不是「找到彼此」,而是「理解彼此」。

一个 Agent 输出的结果,另一个 Agent 能不能正确解读和使用?上游 Agent 的意图,能不能准确传递给下游?在一个复杂的多 Agent 系统里,一个中间 Agent 的判断偏差,会在整条链路上产生多大的放大效应?

这些问题,在 Spec 里写几行配置是解决不了的。

它需要的是:精心设计的 Prompt 接口约定、明确的输入输出格式规范、在关键节点上设置人工审核的介入点、大量的真实场景测试。说白了,是把软件工程里接口设计的严谨性,带入到 Prompt 设计里来

而目前大多数团队做 Agent 系统,在这件事上的投入还远远不够。


基础设施之下的那个问题

还有一件事值得单独说。

这套架构的前提,是每个 Agent 本身的能力是可靠的。

Spec 再标准、执行引擎再完善、Registry 体系再健全,如果你塞进去的 Agent 在核心任务上经常出错、推理经常偏轨、工具调用经常失败——用户最终感受到的,还是一个不好用的系统。

基础设施能让你管理 Agent 的规模,但它不会自动提升单个 Agent 的质量。这两件事是正交的,都需要投入,都不能偷懒。


最后

这套思路,其实是把云原生工程领域里一个非常成熟的判断——「定义与执行分离」——用到了 Agent 的构建上。

容器时代,我们花了很多年才想清楚「应用的运行环境」和「应用本身」要分开管理,才有了今天 k8s 的弹性扩缩、滚动升级、故障自愈。Agent 时代,「执行引擎」和「Agent 的业务身份」,大概也值得被同等认真地分开对待。

但有一点不完全一样:容器里跑的应用是静态代码,但 Agent 的「业务身份」里包含 Prompt——Prompt 是会说话的,它直接决定 AI 的行为边界。这意味着 Agent Spec 不只是工程配置文件,它更接近于一份「行为合同」——定义了这个 Agent 能做什么、应该怎么做、不应该做什么。

把这份合同从代码里分离出来,单独管理、单独版本控制、单独审计,可能比你想象的更加重要。

如果你也在构建越来越多的 Agent,不妨回头看看:你每次重复的那些代码,是不是其实都可以变成一份配置文件?

也许真正该被重新设计的,不是某一个 Agent,而是你管理所有 Agent 的方式。