Agent Droplets 今天正式对外开放了。这个项目从立项、内测到灰度,我前后折腾了八个多月,现在总算把面向 AI Agent 的云基础设施这条路跑通了。说人话,Agent Droplets 做的事情就是:给每个 Agent 分配一个轻量、可调度、能按需启停的云端算力单元,开发者把自己写的 Agent 服务往上一部署,不用再维护容器集群、不用为高并发头疼、不用手工处理会话隔离。这篇文章主要写给三类人看:正把 Agent 原型往产品化方向推的开发者、想搭建内部 Agent 平台的团队、以及准备做类似基础设施的技术同学。我会把设计思路、参数选择、上线流程和排障实录都摊开讲,尽量把"为什么这么做"也说清楚。
如果你还没接触过这类概念,可以把它类比成"给 Agent 开一个随用随走的云上工位"。传统云服务器是你租一个固定房间,人不在也得付房租;Agent Droplets 则是按会话分配工位,任务来了瞬间开灯,任务结束立刻关灯,水电费只按实际使用结算。这个差异听起来简单,真正落地时牵扯到调度、沙箱、状态持久化、预算控制一堆细节,下面逐一展开。
1. 为什么 AI Agent 需要一套专门的云基础设施
1.1 传统云服务器和 Agent 工作负载的错位
过去两年我用传统云主机跑 Agent 工作负载,踩了不少坑。核心原因在于:传统云服务器是为"常驻服务"设计的。进程一直活着、端口一直开着、流量来了就响应,资源需求相对平稳。但 Agent 的负载模型差得很远。
举一个最常见的场景。用户让 Agent"整理本月所有发票,按金额排序,再给财务发一封汇总邮件"。这个任务拆开看,是一个多步骤计划:调用搜索工具、遍历发票数据库、做排序、调用发送工具、等待邮件确认。整个链路可能持续几十秒甚至几分钟,期间 CPU 忽高忽低,内存里要暂存中间结果,还要持久化会话上下文。
这种负载落到传统云主机上会出现几个典型错位。第一,生命周期错位:一个任务完成后 Agent 进程往往还在等下一个指令,但下一个指令可能五分钟后才来,这段时间机器就这么空转着。第二,资源模型错位:任务峰值和低谷差距悬殊,按峰值配资源意味着大部分时间在浪费,按低谷配又会在任务跑到一半时被内存打爆。第三,状态管理错位:Agent 的会话上下文、工具调用的副作用、阶段性输出,都需要和单个会话绑定,而不是和一个常驻进程绑定。第四,安全和权限错位:Agent 会调用发送邮件、修改文件这类有副作用的工具,这在共享主机上很难做细粒度管控。
1.2 Agent Droplets 想解决的核心矛盾
既然错位这么明显,为什么市面上的方案不能直接套用?因为这里存在三个相互纠缠的矛盾,普通云产品往往只解决其中一个,剩下两个才是 Agent 基础设施真正的护城河。
第一个矛盾是弹性和成本。理想的 Agent 算力应该像打车一样,按单计费,用完即走。但弹性调度必然引入冷启动、资源碎片、调度延迟,这些都直接影响用户体验。第二是隔离和协作。用户的 Agent 之间必须隔离,不能互相窥探数据;但 Agent 们又要共享工具注册表、共享知识库、共享团队级配置,隔离和协作的边界怎么划,需要专门设计。第三是易用和可控。开发者希望一行配置就把 Agent 跑起来,平台方却必须把超时、并发、预算这些控制项暴露出来,否则一次死循环工具调用就可能烧掉全部预算。
Agent Droplets 的定位,就是围绕这三个矛盾来做一套专用基础设施。每个 Agent 分配一个独立算力单元,单元跟着会话走,会话结束就回收资源;控制面板提供预算、超时、并发等护栏;同时把工具调用、记忆存储、密钥管理做成平台的开箱即用能力。
2. 整体架构设计与关键选型
2.1 算力单元(Droplet)的生命周期设计
名字里的 Droplet 就是整套架构的最小单位。一个 Droplet 代表一个独立运行 Agent 服务的沙箱环境,包含固定配额的计算资源(CPU、内存、临时磁盘)、一个受管控的网络出口、以及一套会话级别的状态存储。
在设计生命周期时,我参考的是最常见的 Agent 使用节奏:一个任务通常几十秒到几分钟,任务之间可能有长时间空闲,也可能瞬间涌入大量并发。所以 Droplet 的状态机不是简单的"启动-停止",而是五个状态:休眠态、准备态、运行态、检查点态、回收态。休眠态不占计算资源,只保留镜像元数据和配置;准备态负责调度和拉起沙箱;运行态执行任务,期间支持按会话粒度记录进度;当任务空闲超过阈值,Droplet 进入检查点态,把内存快照和上下文序列化到存储;再次有任务进来时,直接从检查点恢复,而不是从零冷启动。任务彻底结束或超过生命周期上限,进入回收态释放资源。
这里最关键的选型是沙箱运行时。Agent 服务需要跑代码、调系统命令、访问文件系统,所以不能只靠普通进程隔离;但完全用重量级虚拟机,启动延迟和资源开销又扛不住高频创建销毁。最终方案是"容器边界 + 系统调用过滤 + 资源配额"的组合,既保证隔离性,又把冷启动时间控制在百毫秒量级。这个组合实测下来很稳,最大的好处是兼容性好,主流的 Agent 镜像不用改就能跑。
2.2 调度器与控制平面
控制平面是整套平台的"大脑",负责接收创建 Droplet 的请求、决定把它放到哪个物理节点、在资源不足时扩缩容、在节点故障时迁移重启。调度器采用两层设计:第一层是队列调度,按租户和优先级排队,保证公平性;第二层是放置调度,在具体节点上分配资源。
放置调度里最重要的一条经验是"内存优先,镜像就近"。Agent 工作负载的内存敏感性远高于 CPU,因为上下文、临时检索结果、工具返回都压在内存里,宁可高估内存也不要低估。镜像就近的意思是,调度时优先选择已经缓存了目标镜像的节点,否则一次镜像拉取可能让冷启动翻好几倍。这两条规则看起来简单,但对整体延迟的改善非常明显,灰度期对比数据里,开启镜像就近调度后,新 Droplet 的可用延迟从平均 4 秒降到 0.8 秒。
控制平面还有一个容易被忽视的组件:资源池预热器。它会根据历史并发曲线,提前把常用镜像的 Droplet 拉起到休眠态,用户请求一到,直接把休眠态切到运行态。预热池的大小按"最近一小时 95 分位并发"来算,不按峰值算,否则资源浪费又会吃掉弹性带来的成本优势。
2.3 工具链、记忆与密钥管理怎么落地
Agent 和普通 API 服务最大的不同,是它要调用有副作用的工具。发邮件、写数据库、执行数据分析,这些操作不能直接在 Agent 的主进程里乱跑,否则一个小 bug 就可能污染生产数据。
我们的做法是"工具沙箱化":每个工具调用在独立的工具沙箱里执行,沙箱通过网络白名单和文件系统白名单约束访问范围,主进程只能拿到结构化返回结果。工具注册表里维护了工具的元数据、参数 schema、调用权限和重试策略,Agent 通过注册表发现工具,而不是自己在代码里硬编码工具 URL。这个设计把安全边界从"进程内自觉"变成了"平台级强制",给后来的账号隔离省了大量麻烦。
记忆这块,我坚持把短期记忆和长期记忆分开。短期记忆是会话内的上下文,放在快速内存里,键名强制带 sessionId 前缀,会话结束立即清理;长期记忆是跨会话的知识沉淀,放在向量存储里,按团队和项目做权限隔离。密钥管理则完全交给控制平面:配置里只写密钥的引用 ID,启动 Droplet 时由平台注入到环境变量,开发者永远不需要把密钥明文写进镜像或配置文件。
3. 平台配置与上手实操
3.1 创建第一个 Agent Droplet
整个上手流程,我尽量压到三步:准备镜像、提交配置、开始会话。第一步,把你自己写的 Agent 服务打成标准容器镜像,平台对镜像格式没有特殊要求,只要进程能监听端口、健康检查通过就行。镜像构建文件里建议保留健康检查声明,方便平台判断沙箱是否真正就绪。
第二步,提交一份配置描述 Droplet 的资源、超时、工具权限和预算,配置格式长这样:
apiVersion: agent-platform.example.local/v1 kind: Droplet metadata: name: invoice-assistant spec: resources: cpu: 2 memory: 4Gi disk: 20Gi image: repo: registry.example.local/agent-runtime tag: "1.4.0" execution: timeoutSeconds: 900 maxConcurrency: 32 idlePauseSeconds: 60 tools: allowed: - search - email.send - database.query memory: shortTerm: kv-memory longTerm: vector-store budget: maxToolCallsPerSession: 200 maxSpendPerSessionMinutes: 30第三步,通过 API 或 SDK 启动会话。用 Python 侧代码大概是这样:
from agent_droplets import Client client = Client(api_key="<your-api-key>") droplet = client.droplets.create( name="invoice-assistant", image="registry.example.local/agent-runtime:1.4.0", resources={"cpu": 2, "memory": "4Gi"}, timeout_seconds=900, ) session = droplet.start() result = session.run("整理本月所有发票,按金额排序,并给财务发一封汇总邮件") print(result.status, result.output)如果你更习惯命令行,直接用接口创建也是一样的效果:
curl -X POST "https://api.example.local/v1/projects/default/droplets" \ -H "Authorization: Bearer ${AGENT_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "name": "invoice-assistant", "image": "registry.example.local/agent-runtime:1.4.0", "resources": {"cpu": 2, "memory": "4Gi"}, "execution": {"timeout_seconds": 900} }'这里有三点容易出错。第一,镜像仓库地址和标签必须写全,平台不会帮你补默认 tag,少写 tag 会直接拉取失败。第二,allowedTools里列的是工具在注册表里的逻辑 ID,而不是系统命令,别把shell.raw这种高危工具放开,除非你知道自己在做什么。第三,首次创建时可以先用小规格试试,确认服务能正常响应后再调大资源,避免一上来就浪费配额。
3.2 资源参数怎么定才不浪费
资源给多了浪费钱,给少了任务跑崩,这个平衡不能拍脑袋,得拿数据说话。我给一个自己常用的估算方法。
先看单会话资源。一个典型的 LLM 调用型 Agent,主要开销是请求构造、响应解析、工具结果暂存,2 核 CPU 加 4GB 内存基本够用。如果 Agent 还要本地跑检索增强、向量计算或者内嵌小模型,建议直接上 4 核加 8GB,不要省,因为这类负载的内存峰值很难预测,省下来的成本远不够赔任务中断的代价。
再看执行超时。我建议先跑一轮压测,拿到任务耗时的 95 分位,再乘以 1.5 或加上 30 秒作为默认超时。超时设太短,长任务会在正确路径上被误杀;设太长,死循环工具调用就会一直烧预算。这个值不是配置一次就完事的,每次 Agent 逻辑大改之后都要重新回测。
然后是并发度。maxConcurrency表示一个 Droplet 实例能同时处理多少个会话。经验做法是先压测出单实例的资源利用率拐点,再取拐点的 80% 作为并发上限,留一点余量给突发文本长度。至于需要多少个 Droplet 实例,拿峰值并发除以单实例并发度,再乘上 1.2 的安全系数,就是池子大小。比如预计峰值并发 200,单实例 32 并发,那就需要 7 个实例,实际按 10 个来配,既覆盖抖动又不会空转太多。
预算参数是我强烈建议默认开启的。maxToolCallsPerSession直接拦住失控循环,maxSpendPerSessionMinutes按额度控制单会话消耗。灰度期我们亲眼见过一个 Agent 因为检索函数没写终止条件,在一个会话里连续调了几千次工具,如果没有这道护栏,账单数字会非常难看。
3.3 和现有 Agent 框架的对接方式
不少团队不是从零开发 Agent,而是在现有框架上做二次开发,所以对接体验很重要。Agent Droplets 的对接思路很直接:框架负责推理和规划,平台负责执行环境。你只需要把框架里的工具执行层替换成平台的工具沙箱入口,把会话存储层替换成平台的记忆接口,其余逻辑不用动。
具体来说,注册回调地址指向 Droplet 的会话端点,框架调用工具时改成发往工具沙箱的请求,带上会话 ID;记忆存取改成调用短期记忆和长期记忆接口,键名由平台自动注入的 sessionId 拼接。整个改造量大概在一个工作日以内。
如果需要访问团队内部的数据库或 API,记住平台默认是不开放公网出站的。你需要在控制面板里配置出口白名单,把要访问的服务域名和端口加进去。这么做初期会觉得有点麻烦,但好处是任何一台 Droplet 被攻破后,能做的破坏都被限制在白名单范围内。灰度期间有合作伙伴提出过"不够灵活"的意见,可一旦出了安全事件,大家又都感谢这个设计。
另外建议把开发环境和生产环境拆成两个项目空间。同一份配置,字段不改,只改项目标识,就能在两边各跑一套,互不干扰。我在内部一直是用这种方式做灰度对比的,新版本先在生产项目空间挂一小部分流量,跑几天看错误率和耗时曲线,再决定全量节奏。
4. 上线后排障实录与避坑经验
4.1 上线初期高频问题速查表
上线第一个月我们接了不少工单,大多数问题集中在下面几类。我整理成了一张表,基本上照着排查就能解决七八成的问题。
| 现象 | 可能原因 | 处理建议 |
|---|---|---|
| 首次调用延迟特别高 | 冷启动阶段镜像拉取耗时过长 | 开启镜像预热池,常用镜像预置到节点 |
| 任务跑到一半进程被杀 | 内存配额不足或存在内存泄漏 | 提升 memory 配额,同时开启检查点恢复 |
| 多个用户看到彼此数据 | 会话上下文未按 sessionId 隔离 | SDK 自动注入 session_id,存储层强制前缀隔离 |
| 工具调用一直超时 | 出口白名单过严或工具沙箱参数不当 | 检查网络放行策略,适当放宽工具重试次数 |
| 账单金额异常飙升 | 缺少会话级预算护栏 | 默认开启工具调用次数上限和单会话预算 |
| 高峰时段部分 Droplet 创建失败 | 节点资源碎片化 | 调整放置调度策略,启用资源碎片整理 |
表格里的每一条,背后都有具体案例支撑。冷启动的问题我们在灰度期的压测里暴露得最明显:第一次压测时,请求量大增导致大量新建 Droplet,每个都要重新拉镜像,P99 延迟从平时的 300 毫秒直接飙到 8 秒,整个服务看起来像挂了。排查后确认是镜像在多节点间没有缓存,立刻加了镜像预热池和节点内缓存,第二次压测 P99 降到了 1.2 秒。
会话串数据的问题是最吓人的一类。某测试团队反馈,用户 A 能看到用户 B 的发票数据。排查过程很曲折,最后定位到原因:为了省资源,他们把多个会话复用同一个 Droplet,但会话变量存在了进程内的全局缓存里,没有按 sessionId 隔离。修复方案是平台在 SDK 层自动注入 session_id,所有缓存和记忆接口强制按 session_id 加前缀,任何不带的请求直接拒绝。这个案例也让我下定决心,隔离必须是平台默认行为,不能指望调用方自觉。
成本失控的问题在正式上线第二周出现。一个 Agent 的检索工具没有终止条件,单会话内连续调用了上千次,等我们发现时已经产生了远超预期的费用。事后我们给所有项目默认开启了工具调用次数上限和单会话额度,并加了实时告警,告警阈值设为额度的 80%,这之后账单就恢复正常了。
4.2 两个值得分享的优化手段
排障之外,有两项优化对整个平台的稳定运行帮助最大,值得单独拿出来说。
第一个是检查点恢复机制。Agent 任务动辄几分钟,期间节点做升级或迁移,如果直接杀掉进程,整个任务就得重来。有了检查点后,Droplet 会定期把内存快照和任务进度序列化到持久存储,节点需要回收资源时,就把检查点迁移到其他节点恢复,用户几乎无感知。上线后第一次节点维护演练,我们靠检查点把任务中断率从百分之百降到了接近零,这个机制也成为我推荐所有长任务场景必开的功能。
第二个是预算护栏的多层叠加。单靠一个工具调用次数上限不够,还要叠加会话额度、项目级月度额度、突发流量熔断。熔断规则我建议这样设置:当某个项目一分钟内的工具调用量超过过去七天同时间窗口均值的三倍,自动进入半熔断状态,新会话排队,已开始的会话继续跑完。这招在流量异常波动时特别管用,既保护了平台整体资源,也保护了用户自己的预算。
成本核算方面,我们按"单会话实际执行时长 + 存储占用"计费,空转的休眠态和检查点态不按运行计费,只按存储计费。这样设计是为了让用户在"挂了等消息"的状态下不至于持续烧钱,也倒逼我们在调度层不断优化资源利用率。
5. 从平台视角看 Agent 基础设施的下一步
5.1 可观测性:不能只看机器指标
运营 Agent 平台和运营普通 Web 服务有一个很大的区别:机器指标只能告诉你"发生了什么",却很难告诉你"为什么发生"。CPU 飙升可能是遇到了大请求,也可能是 Agent 进了死循环;内存涨了可能是有任务在正常检索,也可能是会话状态泄漏。所以我们在常规 CPU、内存、网络指标之外,重点做了三层可观测性。
第一层是任务轨迹。每个 Agent 任务都会生成一条链路,包含规划节点、工具调用、中间输出、最终回复,每个节点都打上时间戳和耗时。排查问题时,看这条轨迹比看任何仪表盘都直观。第二层是工具审计。每次工具调用都记录调用方、被调工具、入参、出参摘要和执行结果,这既是为了排障,也是为了安全审计。第三层是质量评估。我们沉淀了一套回归任务集,每次平台或 Agent 版本更新,都用同一批任务跑一遍,对比完成率、平均耗时、失败类型分布。
这里给个建议:可观测性不要等上线后再补,最好在设计阶段就把轨迹埋点定义清楚。我们前期就是因为没想清楚,上线后又花了两周时间手工补埋点,中间漏了不少历史数据,尤其可惜。
5.2 多租户隔离与成本治理的落地经验
最后一个话题,也是团队内部讨论最多的:多租户。Agent 平台天然是多人共用的,但"共用"不等于"混用"。我们在项目空间之上做了三层隔离:基础设施层,不同项目的 Droplet 分配在不同节点组,避免"坏邻居效应";数据层,记忆存储和向量空间按项目做强隔离,跨项目访问直接拒绝;控制层,项目配额和预算互相独立,一个项目把额度打爆不会影响其他项目。
成本治理方面,我比较推荐"默认开启,例外申请"的策略。新项目一创建,预算上限、工具调用次数上限、超时阈值就都开着,想放宽要走申请流程。这样做的原因是,人性倾向于不做设置,而预算护栏这种东西,漏配一次就可能造成大事故。上线以来我们处理的所有成本异常工单里,九成以上都是因为有人改了配置或绕过默认护栏。
从实际收益看,这套隔离和治理机制让平台可以从容接受更多类型的负载,也让用户敢于放大并发。我们内部已经把类似 Agent Droplets 的能力复用在好几个业务场景里,包括客服工单自动分拣、报表自动生成、代码评审辅助,效果都还不错。
最后分享一个我个人的心得:做 Agent 基础设施,最容易犯的错误是把它当成普通的容器调度平台来做,只关心资源和并发,忽略了 Agent 特有的会话、工具与状态问题。你真正要交付的不是一堆能跑的容器,而是一套让 Agent 安心的运行环境。按照这个标准去设计,很多细节选择就自然浮现了。如果在现阶段,你只能记住一句话,我建议先记住这个:预算和超时是 Agent 平台的功能需求,不是运维细节。