跳转至

云端 Agent 基础设施两条硬经验:CreaoAI 联合创始人的状态/代码解耦 + 凭据隔离

Ch11.013 云端 Agent 基础设施两条硬经验:CreaoAI 联合创始人的状态/代码解耦 + 凭据隔离

📊 Level ⭐⭐ | 26.8KB | entities/cloud-agent-infrastructure-creaoai-state-code-credential-isolation-20260606.md

概述

CreaoAI 联合创始人总结的云端 Agent 基础设施两条硬经验——把桌面端 Agent 假设(用户 = 同一台机器 = 同一受信边界)搬到云端时踩出的两个核心设计原则:① 状态与代码解耦(frozen snapshot + hot-swap Runner,类比 OS 内核 vs 用户 home 目录)② 凭据隔离在执行边界之外(API bridge + IP 白名单 + 每次运行的短期 JWT)。这两条是云端 Agent 平台区别于桌面框架的根本性架构差异,而不是"加几个云服务就行"。

第一性原理:为什么桌面假设在云上失效

桌面 Agent 假设(隐含的"一次性都成立")

  • 一个用户、一台机器、一个进程
  • Agent 跟着笔记本电脑一起活
  • 写本地文件系统
  • API 密钥放在环境变量里
  • 终端一关进程就没了
  • 出了问题用户自己重试,缺个包就 pip install 装进本地 Python
  • 状态 / 密钥 / 生命周期全在同一个受信边界里——不需要额外操心

云端 Agent 现实

  • Agent 跑在每次全新启动的沙箱
  • 底下是多租户共享硬件
  • 触发它的可能是:定时任务 / HTTP 请求 / 另一个 Agent
  • 运行的时候用户多半不在线
  • 沙箱里的代码不一定可信(LLM 根据可能带恶意的 prompt 生成)
  • 文件系统要扛得住反复部署
  • 凭据不能跟 Agent 放在一起
  • 桌面端那些理所当然的东西——持久化 / 身份 / 网络信任 / 重试——到了云上全得自己建

关键判断今天大部分 Agent 框架的设计前提是桌面环境——搬到云上必须重新设计,不是简单迁移。

教训一:把变化慢的和变化快的分开(状态/代码解耦)

第一版方案:粗鲁的"全重建"导致用户环境丢失

第一版实现:启动时检查快照里的 Runner 版本是否和最新部署一致,不一致就丢掉快照、从干净模板重建。 - 确实能用 - 也没人投诉 - 代价只是每次部署后第一次运行要重建环境 - ——无人值守运行(unattended runs)暴露了这个方案的问题

失败场景:周一早上 9 点的定时任务不应该因为我们 8:55 做了一次部署就把用户环境搞丢。 - 我们实际上一直在违背一个隐含的约定:"你的环境会保持冻结,直到你自己去改它。"

根因诊断

用户环境和 Runner 代码的变更频率完全不同: - 用户自己决定什么时候改环境(可能 1 个月 1 次) - 我们每天要部署平台好多次

把两者打包在一起,每次部署都得做一个两难选择: - 要么容忍过时的 Runner(有安全风险) - 要么毁掉用户辛苦搭建的环境(违背承诺

解决方案:借鉴 OS 的内核/home 分离

内核升级不影响用户的 home 目录,打安全补丁不需要格式化硬盘。

CreaoAI 在沙箱上画了同样的线

启动流程: 1. 启动时照常从用户的冻结快照加载,不做任何修改 2. 然后单独热替换(hot-swap)Runner——这是关键创新

Hot-swap 步骤6 步保证原子性): | 步骤 | 动作 | 目的 | |------|------|------| | 1 | 把新版 Runner 放到沙箱内的临时目录 | 准备 | | 2 | 用 node --check语法校验 | 保证在触碰运行中的代码之前就能发现问题 | | 3 | 原子替换:先解锁旧 Runner 的不可变标志 | 解除锁定 | | 4 | 把新文件复制过去 + chattr +i 锁上 | 写入 + 重新锁定 | | 5 | 把 chattr 命令本身藏起来 | 防止沙箱内的代码反向解锁 | | 6 | 清掉 V8 编译缓存(/home/user/.cache/v8-compile-cache/*) | 确保加载的是新文件而不是旧字节码 |

关键不变量: - 以上任何一步出错,直接杀掉沙箱换一个新的重试——不允许出现半升级的状态 - 整个替换耗时约 300 毫秒 - 当一次运行中发生了 Runner 替换,运行成功后会重新生成快照,把更新后的代码固化到用户镜像中,后续运行就不再需要替换了 - 平台部署永远不会丢弃用户的状态,只是把新版 Runner 融合进去——用户的包 / 文件 / 定制化配置全部原样保留

核心判断标准

对于云平台上持久化的每一样东西,都要问清楚,谁控制它的变更节奏? 如果用户和平台都要改同一个制品,迟早会出问题。按所有权边界把它拆开,让各自按自己的节奏演进

应用启示: - 状态层 = 用户所有 = 冻结快照(用户主动改才动) - 代码层 = 平台所有 = 热替换(平台主动部署就动) - 两者通过 hot-swap 协议连接(保证原子性 + 可回滚) - 所有权清晰 → 各自的演化节奏独立 → 不会相互冲突

教训二:把凭据隔离在执行边界之外

云端 Agent 的安全前提

  • 桌面 Agent:用用户的身份运行 + 用用户的密钥 + 在用户的机器上 + 访问用户的网络
  • 云端 Agent跑在共享硬件上 + 以无特权身份运行 + 面对开放互联网 + 执行的代码由 LLM 根据可能带有恶意的提示词生成

CreaoAI 原则沙箱内的代码已经不可信。这是与桌面模型完全相反的安全前提。

核心原则

长生命周期的凭据绝不进入沙箱。

当 Agent 需要调用有认证要求的外部服务(Slack / GitHub / 用户自己的 API)时: - 它不持有令牌 - 而是向沙箱外部的 API 桥接层(API bridge)发一个本地 HTTP 请求 - 桥接层在宿主侧把 OAuth 令牌挂上去,再转发调用 - 响应返回的全程中,令牌从未进入过沙箱的内存或环境变量

桥接层身份验证:两层校验,刻意叠加

第一层:IP 白名单(网络层) - 桥接层只接受沙箱宿主所在内网网段的连接 - 其他来源的请求在网络层就被丢掉,不会走到应用代码 - 等于把桥接层绑定在了特定的物理基础设施上 - 外部拿到地址也没用

第二层:每次运行生成的短期 JWT(应用层) - 沙箱启动时,平台签发一个专属于本次运行的令牌 - 限定了用户 / 应用 / 会话和有效期 - 沙箱在每次调用桥接层时都要出示这个令牌 - 桥接层验签 + 检查有效期,通过后才去查用户存储的凭据并在服务端附上 - 即使沙箱被劫持,攻击者拿到的也只是一个随运行结束即失效、且只对当前会话有效的令牌 - 没有长期凭据可以泄露

边界归一:唯一双向通道

  • 同一个桥接层也承载计费扣款 / 日志 / 指标的传出
  • 所以它是沙箱边界(execution boundary)上唯一的双向通道
  • 沙箱内部的一切,默认视为已被攻破

实战假设

假设明天有一次提示词注入(prompt injection)成功让 Agent 把 process.env 发到外部 webhook,攻击者拿到的也只是一个短期 JWT,只在内网有效,运行结束即作废。

这个性质是 CreaoAI 能在共享基础设施上放心跑不可信代码的底气

底层设计模式:4 条铁律

可靠、安全的云端 Agent 基础设施不需要什么新发明,它就是几条严格执行的原则:

  1. 状态在沙箱里,冻结到用户主动改变为止。(用户所有 = 慢变)
  2. 代码可热替换,不依赖状态。(平台所有 = 快变)
  3. 凭据在宿主侧,永远不进 Agent。(执行边界外)
  4. 同一条执行管道服务所有调用方,不管触发源是人 / 调度器 / 其他程序

第 4 条最值得说: - 一个 executeAgent 函数同时处理 UI 点击 / 定时触发 / API 调用 - 计费 / 额度扣减 / 日志 / 可观测性信号不管谁触发的运行,走的都是同一套逻辑 - 新增一种触发方式只是加一条路由,不涉及架构改动 - Agent 本身不知道、也不需要知道是谁启动了它

与桌面框架的本质区别

维度 桌面 Agent 云端 Agent
生命周期 跟着笔记本 跟着运行(沙箱)
状态 本地文件系统 冻结快照
凭据 环境变量 沙箱外 API bridge + 短期 JWT
代码更新 pip install 平台部署(带 hot-swap)
触发源 唯一(用户交互) 多样(人 / 调度 / Agent)
用户在线 几乎一直在线 多半不在线
重试责任 用户 平台(计费/扣减/日志统一)
多租户 不需要 必须(共享硬件)

关键洞见笔记本上的 Agent 跟那台笔记本绑死了云端的 Agent 是技术栈里其他系统可以随时调用的函数用户只需要写一次,平台负责让它扛住部署、在共享硬件上安全运行、接纳用户没有预想过的调用方

实践启示

对 Agent 平台建设

  • 所有权边界优先于技术实现:先问"谁控制变更节奏",再决定技术方案
  • 代码与状态必须解耦:把"快变"和"慢变"分开演进,不要让平台部署打掉用户环境
  • 凭据 = 永远不进沙箱:API bridge + 短期 JWT + IP 白名单 = 沙箱内部不可信前提下的可执行安全模型
  • 统一执行管道:一个 executeAgent 服务所有触发源,避免 N×M 复杂度

对 Agent 框架设计者

  • 桌面假设 ≠ 云端现实:今天大部分 Agent 框架的设计前提是桌面环境,搬到云上必须重新设计
  • 沙箱里跑的是不可信代码:LLM 生成的代码可能带 prompt injection 风险,凭据绝不能进沙箱
  • Hot-swap 协议是核心工程:300ms 原子替换 + 失败立即换沙箱 + V8 缓存清理——这是"既能快迭代又不毁用户环境"的最小可行解

对 Agent 应用开发者

  • 用户环境是承诺:平台每次部署都不应该丢用户的状态——这是隐含但绝对不能违反的约定
  • 多触发源 = 同一管道:用 UI 触发的 Agent 应该和用 cron 触发 / 跨 Agent 触发走同一套逻辑,避免架构分裂

对安全架构师

  • 零信任在沙箱边界 = 必要前提:把沙箱内部"默认已被攻破"作为安全模型起点
  • 短期 JWT > 长期 API Key:即使 token 泄露也只对单次运行有效,不会造成大范围损失
  • 唯一通道 = 唯一审计点:所有进出沙箱的流量都走桥接层,日志/计费/可观测性集中可查

核心命题

Agent 本质上是一个带自然语言接口的函数。实现归用户,触发面、运行时、安全边界归平台。关键在于把这些层建好,让每一层按自己的节奏演进,并且赶在别人之前找到层与层之间的缝隙。

这就是让下一个触发面能快速、安全上线的根本。

深度分析

1. 所有权边界是云端 Agent 基础设施的设计原语,而不是实现细节

文章的核心判断标准是"谁控制变更节奏"——这个设问方式本身就是一种设计原语,而非技术选型建议。在桌面环境里,所有权边界是模糊的(用户 = 机器 = 进程),所以不需要思考这个问题。云端多租户环境下,平台和用户对同一个制品有方向相反的更新需求,这个问题就被强制暴露出来了。

把这条原则一般化:云端 Agent 平台上的每一份持久化制品,都必须有且只有一个变更节奏控制器。如果两个控制器竞争同一份制品,要么损失安全性(用过时的 Runner),要么损失可复现性(摧毁用户环境)。CreaoAI 的 hot-swap 协议,本质上是在 OS 内核/home 目录分离这个成熟模式里找到了一个特化实现,但驱动这个实现的底层逻辑是所有权边界原则。

2. Hot-swap 协议把"平台迭代"和"用户状态"从耦合态解耦为独立演化树

文章揭示的工程对局是:平台需要快速迭代安全补丁和功能更新,用户需要环境永远可复现。第一版"全重建"方案的失败,不是因为实现有 bug,而是架构上就不可行——它要求每次平台部署都在"安全性"和"用户承诺"之间二选一。

Hot-swap 的工程意义在于:它把"平台升级"和"用户状态"从必须同时发生的耦合事件,变成了可以独立发生的事件。平台可以在任何时候发布新版 Runner(通过热替换注入),用户状态可以在任何时候被用户修改(通过冻结快照固化)。两者通过一个轻量协议(6 步原子替换)连接,保证任何一步失败都走向可观测的降级路径(换沙箱重试),而不是静默的半升级状态。

这个模式的更深远启示是:平台工程团队和用户之间的接口,不是代码,而是协议。这个协议规定了谁在什么时候可以对什么东西做什么操作——这是 API 设计层面的问题,不仅仅是运维层面的问题。

3. "沙箱内代码不可信"是云端 Agent 的核心安全公理,它翻转了桌面 Agent 的整个信任模型

桌面 Agent 的安全前提是代码来自用户本地进程,安全边界实际上是用户的笔记本电脑——攻击面是外部的。云端 Agent 的安全前提是沙箱里的代码由 LLM 根据可能带有恶意的提示词生成,安全边界必须从物理边界转向身份边界。

这个翻转的影响是架构性的:桌面 Agent 的安全模型是"内网可信,外网危险";云端 Agent 的安全模型是"沙箱内部默认已被攻破"。这意味着零信任必须在执行边界(execution boundary)内落地,而不仅仅是在网络入口处。API bridge 作为唯一双向通道,正是这个安全公理的可执行实现——它把"沙箱内不可信"变成了一条有工程约束的 invariant。

4. 短期 JWT + IP 白名单的双层校验,是把"零信任"从概念变成可执行工程约束的最小方案

零信任是一个被广泛引用的安全概念,但文章给出了一个在云端 Agent 场景下可执行的最小实现:网络层 IP 白名单 + 应用层短期 JWT。两层叠加的目的是让每一层的失效都有独立的兜底

IP 白名单解决的问题是:网络层拒绝所有非内网来源的请求,即使有人拿到了沙箱地址也無法绕过这一层。这绑定了桥接层对特定物理基础设施的依赖,消除了"地址泄露 → 外部直连"这条攻击路径。

短期 JWT 解决的问题是:即使沙箱被完全攻破,攻击者拿到的也只是一个随运行结束就失效的令牌,而且这个令牌只在本次会话内有效。这意味着 credential 的泄露窗口被压缩到了单次运行的时长,而不像长期 API Key 那样是一颗定时炸弹。

这两层的叠加不是过度设计,而是把零信任原则具体化为工程约束的必然要求——每一层独立校验,失效路径独立可见。

5. "统一执行管道"是把 Agent 从"产品"变成"基础设施"的关键架构决策

文章把 Agent 定义为"带自然语言接口的函数",并指出这个函数必须通过一个统一的 executeAgent 管道服务所有触发方。这个定义不是一个隐喻,而是一个架构约束:如果 Agent 对不同的触发源有不同的执行路径,它就不再是一个函数,而是一个需要维护 N×M 复杂度矩阵的产品。

这个架构决策的商业含义是:平台可以低成本地引入新的触发源(加一条路由,不需要改 Agent 本身),而 Agent 开发者可以假设运行时行为与触发方式无关。这把 Agent 从一个"用户交互产品"提升为"技术栈内部可随时调用的基础设施函数"——这是云端 Agent 平台能够形成网络效应的技术基础。


实践启示

对 Agent 平台建设者

  • 先问所有权,再定技术方案:在设计任何共享制品(镜像、配置、Runner)的变更机制之前,先明确"谁控制它的变更节奏"。如果两个主体都需要修改同一个制品,架构上一定会出问题——解决方案是拆分所有权边界,而不是优化协商机制。
  • Hot-swap 是平台的基础设施投资,不是优化项:300ms 原子替换 + 失败换沙箱 + V8 缓存清理,这套机制让平台可以在任何时候发布新版 Runner 而不丢失用户状态。这是"既能快迭代又不毁用户环境"的最小可行解,不是可选项。
  • API bridge 是安全模型的可执行版本,不是安全附加项:凭据永远不进沙箱 + 唯一双向通道 + 双层校验,这三条一起构成了"沙箱内代码不可信"这个安全公理的可执行工程约束。

对 Agent 框架设计者

  • 桌面假设是当前大多数框架的隐含前提,迁移到云端必须重新设计架构:不是加几个云服务,而是重新定义生命周期、状态管理、身份和网络信任模型。桌面框架和云端框架的根本差异不是部署位置,而是谁控制变更节奏信任边界在哪里
  • 在框架设计阶段就要考虑多触发源:如果框架只考虑了用户交互触发的场景,后续引入定时任务或跨 Agent 调用时会面临架构分裂的成本。在设计阶段就把"执行管道归一"作为约束,可以显著降低未来的扩展成本。

对 Agent 应用开发者

  • 用户环境是承诺,不是实现细节:平台对用户的核心承诺是"你的环境会保持冻结,直到你自己去改它"——这个承诺在无人值守运行(定时任务、API 调用等用户不在线的场景)下会直接暴露架构设计是否尊重了这个承诺。任何平台部署都不应该因为自身的迭代而违背这个承诺。
  • 理解执行边界归一的含义:Agent 不知道自己是被 UI 用户、定时任务还是另一个 Agent 启动的——这是设计意图,不是实现限制。开发者应该假设运行时行为与触发方式无关,这使得相同的 Agent 可以安全地横跨多个触发面。

对安全架构师

  • 零信任在沙箱边界内是必要前提,不是额外加固:把"沙箱内部默认已被攻破"作为安全模型的起点,意味着所有进出沙箱的流量都必须经过显式授权和校验,而不能依赖"这个沙箱是安全的"这个前提。
  • 短期 JWT 优于长期 API Key:即使 token 泄露也只对单次运行有效,不会造成大范围损失。结合 IP 白名单的双层校验,把 credential 泄露的窗口压缩到了单次运行的时长,同时绑定了桥接层对特定物理基础设施的依赖。
  • 唯一通道 = 唯一审计点:所有外部认证调用、日志、计费、指标都走 API bridge,使得安全审计和可观测性在一个集中的地方落地——这是"沙箱内部不可信"前提下保持全局可观测性的最小方案。

与现有 Wiki 的关系

与 Cloud Agent 基础设施

与多租户 / Serverless Agent

与 RAG / Agent 评估

  • RAG 技术框架的演进方向 = 关注 retrieval 充分性(充分上下文智能体 = 信息的"够不够"判断)
  • 本文 = 关注 runtime 充分性(状态 / 代码 / 凭据的"够不够"判断 + ownership 边界)

与上下文隔离

  • 上下文隔离 = 关注 context window 内的多任务隔离
  • 本文 = 关注 execution boundary 内的多租户隔离——两者维度不同,但思想相通:"默认不可信 + 强制隔离 + 边界归一"

与阿里云 Agentic Cloud

  • 阿里云 Agentic Cloud = 关注 云平台级别的 agent-as-a-service(Bailian/Qwen/MaaS)——关注平台对外的能力
  • 本文 = 关注平台对内的工程化(snapshot + hot-swap + 凭据隔离)——关注平台自身的建设

实战检查清单(4 条铁律 → 9 项检查)

  • 状态层:用户环境冻结快照,平台部署不重置用户数据
  • 代码层:Runner 代码独立热替换机制(< 500ms 原子替换 + 失败回滚)
  • 变更所有权:明确每个制品的"变更节奏控制器"是谁
  • 凭据隔离:长生命周期凭据绝不进沙箱
  • API Bridge:所有外部认证调用走桥接层
  • 双层校验:IP 白名单(网络层)+ 短期 JWT(应用层)
  • 执行边界归一:所有触发源走同一 executeAgent 入口
  • 可观测性:所有进出沙箱的流量在桥接层集中审计
  • 失败兜底:任何 hot-swap 失败立即换新沙箱,不允许半升级状态

原文存档