把运行时从沙箱中抽离,围绕可持久延续的智能体工作重建系统,以此扩展云端智能体。
扩展错了对象
去年年底,我开始构建云端智能体,目标只有一个:让它们能够扩展。在此之前,我已经花了几个月使用本地编程智能体,尤其是从早期研究预览版就开始使用的 Claude Code,以及后来的 Codex CLI。那时,智能体看起来就是安装在一台计算机上的程序,周围是这台计算机的文件、Shell 和工具。
Manus 关于上下文工程的文章让云端版本有了具体形态:操作在虚拟机沙箱中运行,沙箱的文件系统则充当可恢复的上下文。做第一个产品 Anoma 时,我选择了最直接的路径,把本地智能体循环搬进 E2B。沙箱成了智能体容量的单位;扩展智能体,也就意味着扩展沙箱。
使用 E2B 并没有免去管理沙箱集群的工作。用户越多,要按提供商的生命周期限制配置、复用和回收的沙箱就越多。清理之前,会话历史和追踪记录都留在沙箱里,调试因而依赖于访问存有用户私密数据的环境。为了把 API 密钥留在沙箱外,还得另设网关代理模型请求。为了让沙箱里的智能体正常工作,我们不断把职责移到沙箱外。
最初的架构把整个智能体循环放在一个 E2B 沙箱里。随后,沙箱外出现了控制平面,负责管理沙箱容量并代理模型流量。最后,Web 应用将用户连接到控制平面;扩展的仍是包含完整智能体的沙箱。
到了二月,这些限制让我确信架构必须改变。做第二个产品 Tetral 时,我想提供通用的智能体套件,而不是又一个界面固定的应用。开发者应当能通过 SDK 把云端智能体接入自己的产品,无需自己编写循环或运营底层基础设施。要交付这样的产品,我必须掌握托管层,但这仍以沙箱为容量单位。我考虑了两条路。
Kubernetes 可以运行这项服务,但频繁创建和销毁的沙箱不适合以 Pod 为单位管理。Modal 后来记录了大规模运行时同样的不匹配:在沙箱高速更替时,串行化的调度器和协调一致的 Pod 生命周期会成为瓶颈。
另一条路是使用 EC2、Firecracker,以及负责创建微型虚拟机、处理冷启动和回收的控制平面。这条路可行,却会把我带向自建沙箱提供商。智能体容量仍取决于沙箱集群能提供多少计算机。两条路都把沙箱供给留成一个独立、可替换的基础设施问题,而非智能体服务本身的一部分。
智能体与沙箱集群遵循不同的扩展曲线。智能体是稳定的共享服务,其容量可以在多项工作间复用;沙箱集群则需要隔离、应对突发需求,并且用完即弃。要让这种波动互不牵连,就得把两者分开。智能体成为稳定的服务,沙箱则是可丢弃的执行资源。这样设计,是为了让 Kubernetes 运行一组智能体运行时,把并发会话分配到各副本,而不必同时处理沙箱的频繁更替。
分离并不意味着沙箱不需要扩展,而是让沙箱与模型、记忆、文件、凭据和工具一样,成为各有生命周期的一种资源。Linux、Windows 和 macOS 则成为同类执行资源的不同形态。**计算机应当是智能体调用的资源,而不是智能体栖身的地方。**接下来的问题是:智能体自身的边界在哪里,围绕它的云端系统又从哪里开始?
构建系统,找出运行时
运行时的边界
智能体与沙箱分离之后,问题变得更具体了:如何把智能体抽象为可跨并发会话扩展的服务?
技术上的判断是把智能体视为运行时:一个持续运行的程序,负责解释模型输出,并让智能体受控地访问模型、网络、文件、工具、子智能体和外部世界。Claude Code 与 Codex 已经是本地运行时。在云端,只有身份、状态和资源都置于进程之外,同一个循环才能成为可替换的计算单元。这也划定了运行时边界:凡是拥有者、生命周期或扩展模式不同的职责,都必须移出去。
一个进程承担所有职责提供商集成、状态、投递、计算机生命周期和产品界面都在智能体进程内。
首先移出的是提供商集成。提供商格式、凭据、出站连接与流式协议并不决定智能体的下一步操作。Gateway 接手这些职责,向运行时提供统一的请求及流式响应契约。由于 Gateway 不在请求之间保存会话状态,提供商流量可以独立扩展。
已接受的输入、执行进度和结果必须在任意 Kubernetes Pod 消失后仍然存在,因此 PostgreSQL 成了事实来源。运行时并不直接访问它;否则每种运行时实现都会与数据库模式、事务、所有权、排序和重试协议绑定。Bridge 掌管这一边界,在提交状态转移并返回结果之前检查所有权和顺序。
只有状态还不够,工作也得送达。因此,生产者提交每项输入、智能体消息或资源操作时,同时提交一个 Queue 任务。这样,即使生产者消失,任何兼容的消费者仍可尝试投递。Queue 负责排序、租约、重试、取消和死信处理。
计算机生命周期是另一项需要移出的职责。Sandbox Service 管理由提供商支撑的计算机,并执行安排给它们的工作。运行时只声明某个线程需要一次计算机操作。
Public API 与 Event Stream 也留在执行路径之外:前者接收 SDK 请求,后者公开 PostgreSQL 中有序的记录。两者都不执行智能体。
最终留下的,是针对会话与线程进行的计算。
会话是一项持续进行的智能体工作,配置有一个智能体版本和一组选定资源。线程则是类似 Actor 的串行化边界:会话内一条独立排序的执行路径。一个会话从主智能体的根线程开始,也可以为子智能体创建子线程。
对于每个活跃线程,归约器检查由已提交输入和结果重建的状态,返回下一个有效的状态转移。它不做数据库或网络 I/O。其结果可能是调用模型、路由工具调用、等待更多输入,或结束。
运行时通过 Bridge 加载线程、应用归约器并声明下一步操作。运行时 Pod 只是可替换的计算宿主。它可以让多个会话和线程保持活跃,却不拥有其中任何一个;在声明获接受之前,也不能派发外部操作。
从一开始,我就考虑过把智能体循环放进通用的持久执行引擎。Cursor 使用 Temporal 走的是这条路:其工作进程运行智能体循环,Temporal 则依据事件历史重放工作流代码,以恢复控制流。Cursor 还另设只追加的对话存储,用于保存智能体输出并向客户端流式传送。
Tetral 选择了不同的恢复边界。PostgreSQL 保存智能体状态转移、对话历史和投影。替代运行时从这些记录重建线程检查点,再让纯归约器判断当前状态和下一步转移。Queue 承载围绕同一批提交登记的工作,因此在 alpha 阶段,持久化的智能体控制状态仍处于同一个事务数据库的权威之下。
先记录后执行
可替换的运行时带来一个棘手问题:Pod 消失后,替代者必须知道某项操作是尚未开始、仍在进行,还是已经完成。进程内存无法回答。猜错了,要么漏做工作,要么把同一个外部效果执行两次。
这套协议借用了预写日志(WAL)的顺序原则:先记录状态转移,再执行它授权的操作。因此,凡是会推进线程或产生外部义务的转移,都必须在派发前提交。故障发生后,运行时依据已提交的事实重建这一轮工作,而不是恢复丢失的进程。
派发前,运行时向 Bridge 提交一份身份稳定且不可变的声明。Bridge 核验所有权和顺序,在同一事务中提交状态转移及回执。只有收到确认,运行时才能派发操作。这个稳定身份就是幂等键:重试同一声明会返回已有回执,不会产生第二次状态转移。
01 · 恢复运行时根据已提交到 PostgreSQL 的记录重建这一轮工作。
以模型产生一次 Bash 调用为例。输入进入上下文前先提交;Gateway 收到请求前,span.model_request_start 会记录精确的上下文边界。模型返回 Bash 调用后,Bridge 先提交运行时的 agent.tool_use 声明,调用才能被路由。
Bridge 在同一事务中记录沙箱执行及对应的 Queue 任务。沙箱工作进程运行命令,把原始结果存为「已完成但尚未消费」。Bridge 把结果返回给等待中的运行时,后者为原工具调用声明 agent.tool_result。
在同一事务中,Bridge 追加 agent.tool_result,更新 session_messages 中对应的条目,将已存储的沙箱结果标为已消费,并记录幂等回执。只有收到确认,归约器才能依赖该结果计算下一步。
span.model_request_end 结束提供商请求。只有它和所有必需的工具结果都已提交,归约器才能准备下一个请求。
这套协议的存储模型始于 OpenCode v2 的两个思路:事件表与并列的会话消息投影。Tetral 在这一区分上增加了可替换计算所需的排序机制与回执。
session_events 是事件日志,按顺序保存执行历史,包括已接受的输入、请求边界、工具调用、工具结果、中断和收尾。session_messages 是供模型使用的上下文投影,存储可加载给模型的上下文。用户消息依次追加;一次模型请求期间,一条助手消息逐步累积文本、工具调用及工具结果。成功压缩之后(Tetral 的压缩机制借鉴了 OpenCode 的设计),后续加载从新的摘要检查点开始,先前的执行历史保持不变。压缩决定下次模型请求加载什么,不会抹去先前的会话日志。保留下来的历史日后可以成为可搜索的上下文,不必让一份摘要承载全部过去。session_bridge_operations 保存每项幂等声明的回执。
这些记录共同构成会话日志:它是逻辑上的执行记录,不是某一张物理表,也不只是对话转录。每个线程维护自己的顺序,事件流则为整个会话分配位置。
这些记录也足以恢复线程;系统不存储运行中状态机的可变快照。冷加载时,Bridge 返回已提交的消息、请求和工具边界,以及尚未解决的工作。运行时据此构建检查点,归约器判断线程是在等待请求、等待工具,还是可以继续。
如果提交确认丢失,运行时会用相同身份再次提交,Bridge 返回已存的回执。如果相同身份被用于不同内容,Bridge 会拒绝。
如果运行时 Pod 在模型请求尚未结束时消失,Bridge 会把请求记录为失败。持久化的待处理工作仍可恢复;否则线程回到空闲状态。替代运行时可以重建已提交的检查点,但不会恢复丢失的提供商数据流。已经提交的工作仍由相应服务负责。
这套协议不能让任意外部系统具备事务性。它为每个效果赋予已提交的身份和负责人,让重试汇聚到同一操作:先记录线程被允许做什么,再执行;先记录发生了什么,智能体才能依赖结果。结果不明确时,线程不能悄然推进。
持久投递
先记录后执行的协议决定了运行时如何安全地推进线程,但还不能保证已接受的输入一定能送到线程。
Bridge 的提交让活跃线程得以推进。Queue 则承载那些可以等待消费者、且生命周期长于生产者的工作。
假设用户消息到达时,没有运行时 Pod 就绪。通过发件箱式原子入队,一个 PostgreSQL 事务会追加输入事件、为目标线程创建 Inbox 条目,并创建指向该条目的 Queue 任务。
Queue 任务告诉 Bridge 的 Job Runner:投递还需要一次尝试。Inbox 是接收侧的记录,标明目标线程,并记录输入处于排队、投递中还是已被运行时接受的状态。
事务一经提交,Public API 就返回 200;投递在后台继续。只有运行时将输入提交到目标线程时,才会设置 processed_at。
事务提交后,PostgreSQL 发出 pg_notify,唤醒 Bridge 的 Job Runner。通知不包含消息内容,也不保存投递状态。如果通知丢失,运行进程的轮询循环稍后仍会发现同一个 Queue 任务;消息一直留在 PostgreSQL。
Job Runner 租用消息之前,Queue 会检查目标线程。推进同一上下文的输入必须保持顺序,后来的普通消息不能越过正在投递或重试的消息。其他线程则可以并行推进。
涉及整个会话的变更会在这些通道之间形成屏障。中断单独处理,以便它无需排在普通待处理输入之后,就能送到目标线程。
租到任务后,运行进程带着稳定的消息身份,把消息发送到负责该会话的运行时 Pod。如果另一个轮次正在推进,消息就在目标线程的输入队列中等待。
消息抵达运行时后,投递义务分两步结束:Bridge 先将 Inbox 条目标记为已接受,Job Runner 再确认 Queue 任务。至此,Job Runner 的工作结束。运行时是否以及何时把已接受的输入提交到线程,属于运行时自己的循环,不属于投递流程。
已接受的 Inbox 记录也封住了剩余的故障窗口。RPC 响应丢失时,系统以相同的输入身份重试;Queue 确认丢失时,下一个运行进程会看到已接受状态,直接结束任务,不再重复投递。
仅凭超时,无法证明旧运行时已停止处理消息。绑定代次与 Pod UID 共同充当隔离令牌:只有 Kubernetes 确认绑定的 Pod 身份已经消失,Bridge 才会把已接受的投递退回 Queue。替代运行时随后加载线程上次提交的状态,继续处理同一项 Inbox 投递义务。
调用模型
运行时提交已接受的输入后,归约器就可以声明模型调用。运行时根据指定的提供商与模型、线程上下文、系统指令、工具和附件,组装规范化请求。在请求离开运行时之前,Bridge 会记录 span.model_request_start 及准确的消息序列。
请求不携带 API 密钥或 OAuth 令牌。Gateway 会核验 Pod 的 Kubernetes 工作负载身份,以及由 Bridge 签发的短期令牌,证明该 Pod 仍拥有指定会话和线程。被替换的 Pod 无法再续期令牌,也无法替旧线程调用模型。
接着,Gateway 加载会话选定的凭据。如果选定凭据缺失、已撤销、已归档或无法解密,请求就会被拒绝,不会悄悄改用别的凭据;只有未选择凭据的会话才能使用平台密钥池。
OAuth 刷新也发生在这一边界。Gateway 锁定凭据行、刷新令牌、保存替换后的值,并且只把新的访问令牌注入发往提供商的请求。明文凭据从不进入运行时、Bridge、会话日志或沙箱。
Gateway 通过 Vercel AI SDK 转换请求,再通过 gRPC 返回规范化的 ProviderStreamEvent 值。它既不选择模型,也不保存会话状态,因此任何副本都能服务请求中明确指定的提供商和模型。
运行时累积这一轮的文本和工具调用。输出先经过 Bridge,才进入已存储的上下文;工具调用等待 agent.tool_use;span.model_request_end 则关闭提供商数据流。
如果运行时 Pod 在数据流开放期间消失,其他 Pod 可以恢复已记录的请求边界,却无法恢复丢失进程所拥有的网络连接。Bridge 将该请求以 runtime_pod_lost 结束,让归约器重建一致的线程状态,而不会把不完整且情况不明的响应当作完成。
MCP 把同样的边界用于工具。会话第一次运行前,Bridge 向 MCP 连接器索取已配置服务器的工具列表,并保存已接受的版本。运行时获得工具名称、说明和输入模式,却拿不到服务器凭据或连接细节。工具列表变化时,会产生新的已存储版本。
模型选择 MCP 工具后,运行时先提交 agent.mcp_tool_use。连接器核验这次调用的权限,仅在远程请求中注入会话凭据,并处理 OAuth 刷新。结果经过 Bridge 后,才进入线程上下文。
两条路径中,运行时都只声明需要哪项能力,以及应由哪个资源处理。Gateway 与 MCP 连接器负责外部连接、提供商格式和凭据。智能体因此可以使用这些能力,而底层密钥无需进入任何运行时 Pod 或沙箱。
把计算机当作资源
大多数能力都不需要计算机。模型与网页请求归 Gateway,MCP 调用归 MCP 连接器,记忆操作经过 Bridge。Shell 与文件系统工具则不同:它们需要执行环境。
计算机是暴露给智能体的资源。沙箱是当前由提供商支撑的隔离实例,其生命周期和执行由 Sandbox Service 负责。
这并不意味着每个会话一创建就需要沙箱。计算机按需分配,只有相关工具需要时才会创建。
前述 Bash 声明和 Queue 任务可以在计算机就绪之前存在。Sandbox Service 的工作进程租到任务时,会检查分配给该会话的计算机。
如果兼容的计算机已运行,并为当前会话资源准备妥当,工作进程就可以执行命令。否则,Sandbox Service 会启动激活流程。
激活是让计算机进入可执行状态。Sandbox Service 可以根据其当前状态复用、启动、创建或替换计算机。如果选定文件、辅助状态和会话访问权限尚未在该计算机上准备好,后续另有物化任务负责准备。
Queue 推进这两项依赖。第一个执行任务在将 Bash 执行关联到激活流程后结束,而声明仍在 PostgreSQL 中保持 waiting_activation 状态。并发调用可以共用同一次激活,避免争相启动计算机。激活与物化完成后,每项逻辑执行都会作为新任务回到 Queue。
一项 Bash 工具调用,即执行 42,先通过 Bridge 提交,再进入调度。Sandbox Service 发现计算机尚未启动,于是记录执行等待状态、激活计算机、将同一逻辑执行重新入队、运行 Bash、保存原始结果,并通过 Bridge 返回结果。Bridge 提交工具结果后,运行时才继续。
提交命令前,Sandbox Service 会把该执行绑定到当前那台确切的计算机。如果另一工作进程同时替换或释放了计算机,过期的工作进程便不能把已接受的命令发送到新机器。
随后,Sandbox Service 存储输出,等待运行时通过 Bridge 确认结果。运行时故障不会取消计算机操作,也不要求再次发出 Bash 命令。
当前实现会按需给每个会话分配一台由 Daytona 支撑的计算机,但这种映射并不是抽象本身。计算机是一种资源,其实现可随操作而变。文件访问将来可能使用虚拟文件系统;小型隔离任务可能只需轻量级容器;其他工作则可能需要 Linux、macOS、Windows 或专用算力。
在两个维度上扩展
让计算机可以独立调度,并不意味着同一份有序上下文能同时朝两个方向推进。并发模型请求会读取同一边界,产生互相竞争的后续状态,因此并行工作需要独立的执行路径。
工作空间保存文件和记忆等长期资源。会话是一项持续任务,拥有自己的配置、历史、生命周期及选定资源。线程是会话内一份有序的上下文和一条执行路径。
线程共享会话,却不共享上下文;会话共享工作空间,却不共享执行历史。
一个会话先从根线程扩展出两条独立的子线程。视图随后拉远,显示同一工作空间中的三个独立会话。每个会话都能扩展自己的线程,同时选用共享工作空间中的资源。
Tetral 的子智能体控制模型借鉴了 Codex 的多智能体设计。父线程可以从选定上下文生成子线程,自己继续工作,之后再发消息、等待完成或中断子线程。Tetral 将这些操作映射为子线程,并使用其他会话输入所用的同一条有序投递路径。
如果主智能体想在继续设计时让另一个智能体检查实现,就会创建一条子线程;它在独立上下文中运行同样的归约器和工具循环。独立审查可能不需要父线程历史,继续某项工作可能需要保留的全部上下文,专项调查则只需要最近几轮。
fork_turns 让选择变得明确:none 表示不带父线程历史,all 表示带上保留的全部父线程上下文,正整数则表示带上最近若干轮。运行时会把它解析为子线程精确且不可变的起始上下文。
仅存在内存中的子线程可能在收到指令前就消失;响应丢失后,也可能被重复创建。因此,运行时先提交 spawn_agent 工具调用。Bridge 在同一事务中创建子线程及父子关系,保存上下文和指令,把指令放进子线程的 Inbox,并创建投递任务。
只有 Bridge 确认该事务后,工具调用才返回子线程 ID。重试同一次已提交的调用会返回同一条子线程,不会再创建一个。
分叉之后,父子线程的上下文依旧分开。新的父线程消息不会自动出现在子线程中,两条线程也不能直接写入对方的上下文。后续沟通必须作为另一项有序输入投递。
消息和子线程的完成结果都以有序输入返回。Bridge 在同一事务中记录消息、目标、Inbox 条目及 Queue 任务。如果接收线程正忙,输入会排在当前轮次之后。
send_message、子线程完成通知和 wait_agent 都走这条路径。子线程的最终回答先提交,再进入父线程的 Inbox。等待不会另建一条持久内容通道,也不会重复子线程的工作。
当多条执行路径仍属于同一任务时,子线程很合适。但它不适合作为工作空间中所有职责的边界。代码实现、文档、审计和知识维护可能各自需要独立的根智能体、上下文、智能体版本、凭据集和生命周期;它们应属于不同会话。
不同会话仍可从同一工作空间选择文件、记忆存储、代码库、凭据及智能体版本。工具和技能来自解析后的版本。执行与历史仍然独立;产品日后可以决定哪些经过审查的结果成为共享资源。
独立作出的决定
智能体工作规模扩大,对外部世界的影响也随之增加。把凭据藏在 Gateway 之后,可以避免运行时及其计算机持有提供商密钥或 OAuth 令牌,但无法决定某项拟议操作能否使用该凭据。
凭据隔离控制的是能力的访问。授权决定的是某项具体操作能否行使这项能力。
这个决定必须发生在执行前,并由提出操作的智能体之外的机制来作出。云端边界可以跨客户端和执行环境统一施加确定性策略、内容检查、分类器和服务端强制控制;Claude Code 自动模式展示了这种做法。
OpenAI 的 Hugging Face 事件说明,执行操作的智能体内部能识别风险,不等于系统已经在其周围建立了强制边界。这并不意味着 LLM 审查者一定能阻止那次事件,而是说工具调用必须先通过授权边界,才能影响外部世界。
approve_for_me 是在这一边界上实现的第一个模式。它的审查模型受到 Codex 自动批准审查器启发,并针对先记录后执行协议作了调整。
假设模型提出一条策略为 always_ask 的 Bash 命令。运行时首先让提案通过确定性的工具关卡(Tool Gate)。Tool Gate 综合会话的批准模式、工具目录及该工具附带的策略。在 approve_for_me 模式下,第一次评估会判断需要独立审查。
此时还没有任何内容被接受执行:没有公开的 agent.tool_use,没有沙箱任务,也没有外部效果。Bash 命令仍是尚未结束的模型请求产生的提案。
示意地说,系统根据工作空间、会话、线程、模型请求、模型工具调用、工具名、规范化操作和策略,为提案生成稳定的审查身份:
review_id = H(workspace, session, thread, request, tool_call, tool, action, policy)
这个哈希把审查决定绑定到一项精确的提案。重试审查时使用原有身份;命令或策略一变,就会生成不同的审查。
审查者作为内部线程运行,使用与其他智能体工作相同的运行时机制。它接收拟议操作、相关的父线程上下文、当前助手输出、同一模型轮次的其他工具调用,以及生效的策略。这些输入是证据,不是指令。文件、网站、工具结果,甚至执行操作的模型都可能含有提示注入,因此平台拥有的审查策略必须与待审材料分开。
审查者只返回风险等级、上下文中可见的用户授权、allow 或 deny 结果,以及理由。输出格式错误属于审查失败,不能算作许可。
在父线程所在的运行时持续运行期间,后续审查可以复用一条审查线程,一次处理一项审查。重叠发生的审查则使用临时线程:它们从持久审查线程最近一次提交的状态复制而来,因而可以并行作出决定,而不会交错各自的上下文历史。
主线程上出现三次工具调用。每次完成的调用都先进入 Tool Gate。一次审查在持久审查线程上运行。如果它尚未完成,另一次工具调用也需要审查,系统就从持久线程最近提交的状态复制一条临时审查线程,使两次审查并行推进。每项决定都先提交到 PostgreSQL,才返回 Tool Gate 重新评估。临时线程在决定确定后关闭;持久线程留待后续审查。
审查者的输出还不等于授权。Bridge 先以提案的稳定身份将决定记录到 PostgreSQL。只有提交之后,结果才能返回父线程。
随后,运行时带着已提交的审查结果第二次运行 Tool Gate。获准的决定产生可执行的工具调用;拒绝则在不运行命令的情况下记录被拒的工具结果。审查失败时,只有 Bridge 确认失败记录后,系统才回退到用户批准。如果提交失败或运行时失去权限,工具调用不会推进。
第二次评估完成后,运行时才提交公开的 agent.tool_use。这一事件是接受边界:跨过之后,执行才能放进 Queue,并路由到拥有所需能力的服务。
取消也遵循同样的顺序。如果父线程轮次在审查决定得到确认前被取消,迟到的结果可以留作审计,却不能推进已取消的工具调用。
在公开工具调用提交前,alpha 版本刻意采取保守做法。如果运行时在提案之后、授权完成之前消失,请求将以 runtime_pod_lost 结束;提案以后既不会被重建,也不会执行。系统在这条边界牺牲恢复能力,避免失去归属的决定变成许可。
审查者可以与执行智能体使用同一个模型,其策略也还处于早期阶段。系统保证的是更窄的性质:经过审查的操作,在决定记录之前不能进入调度;平台指令与审查证据分离;每项决定只属于一项提案;不确定性永远不会变成许可。审查者日后可以在这条边界内改进,而不必改变运行时或执行服务。
下一个扩展难题
一旦智能体工作可以比任何单个进程或计算机活得更久,扩展它就不再只是增加运行时容量。它的权限、身份、历史和资源使用也会一起增长。因此,隔离方式必须跟着产品走:智能体能触及什么、能行动多久,以及策略可以在哪里强制执行。Tetral 将智能体留在沙箱外,凭据留在两者之外,并把计算机作为临时资源,让执行、身份和历史可以独立故障、变更与扩展。
要让身份和资源彼此独立,就需要一套分别命名它们的公开契约。Managed Agents API 提供带版本的智能体、固定到已解析版本的会话、按会话覆盖的配置,以及作为一等资源的文件、记忆存储、保险库、技能和环境。Tetral 分叉了该 SDK,在已实现的 Managed Agents 接口范围内保持兼容,同时登记偏差之处,并构建底下的运行时与云端系统。这套契约分别命名智能体、版本、会话和资源,让智能体能在单一客户端之外被寻址。
持久存在的参与者
可寻址的智能体能够跨终端、浏览器、手机、GitHub 或团队产品继续工作,因为这些界面共享一份有序的会话历史。关闭客户端不会结束会话,也不会在计算机之间搬迁智能体。
身份让这种延续性可以追责。一次外部操作能追溯到智能体版本、会话、线程、策略与审查。部署者仍承担责任,但智能体成为这条链上独立的行动者。
RoboBun 让 GitHub 上的工作归属于公开的智能体身份。Raft 将有名字、带状态的智能体放在多智能体工作空间中。Claude Tag 则为 Slack 频道提供异步工作的 Claude,让团队同时委派任务给多个 Claude。界面虽不同,它们都把智能体视为可寻址的参与者,而不是藏在用户账户背后的一次无形补全。
身份承载委派权限时,才真正进入运行层面。智能体可以开通账户、获取 API 令牌、购买域名并部署,也可以申请绑定商户与金额、却不暴露卡片信息的支付凭据。用户或组织仍是授权主体;有明确身份的智能体获得有限且可追踪的权限。
Tetral 让身份归智能体,凭据、策略、批准和执行则由系统控制。CLI 适合绑定操作系统、代码库、编译器或调试器的工作。读取议题或发送消息不该需要一台计算机:MCP 暴露能力,连接器提供会话凭据,运行时的 Tool Gate 则应用策略与批准机制。
规划中的 Code Mode 受到 OpenCode 启发,计划让受限制的 JavaScript 程序发现和组合获准的 MCP 工具、转换结果,并并行运行独立调用。CLI 仍是计算机原生工作的接口;对于云端智能体原生的能力,MCP 则成为首选接口。
能不断积累的工作
增加沟通渠道或参与者,并不会自动改善协作;协调行动的智能体群和各自独立的并行智能体,每份成果可能消耗相近的 token,而规模更大的共享编程智能体群,合并工作成果的比例可能更低。
Tetral 的判断是先进行对抗性审查,再综合成果。工作进入共享空间前,其他智能体必须主动质疑其结论与证据,而非只是附和。然后由人决定接纳什么。这种审视很重要,因为已接受的工作会成为后续探索的基础:一个未经检查的错误可能扩散到建立在它之上的一切。工作空间保存工作成果,也保存审查所需的推理和证据。智能体可以探索多条路径,但进展来自在经过验证的结果上继续构建,而非继承彼此未经审视的结论。
这里比较两种协作结构。在以对话为中心的结构中,三个智能体在共享频道交流,各自却保留不同的工作记忆。在以成果为中心的结构中,会话从已接受的工作空间版本出发,提出独立方案、相互审查成果,把候选成果交给人类审查,最后将获接受的结果合并到下一版工作空间。
工作空间将保存团队接纳的内容;会话日志已经保存了每个候选成果的产生过程。
用不同的智能体版本执行同一任务,可以把各自的运行轨迹变成可比较的评估。被拒绝的工具调用、被推翻的审查、失败的验证和人的修正,都会指明具体问题,成为评估与对齐数据。同样的部署轨迹也可用于在真实工具和外部状态下评估后续模型。
因此,长周期产品可以为未来的评估和训练提供证据,前提是保留来源、去除私密数据,并由人判断成败。训练应减少有害提案,但外部效果仍需确定性策略、验证、内容检查、分类器、独立审查、组织规则和人工升级处理。
扩展围绕智能的系统
模型越强,周围每个系统要承担的工作就越多。更长的工作周期与更多并行路径,意味着更多运行时状态转移、测试、计算机、文件、网络请求、存储的轨迹与外部效果。其中容量最先见底的环节,就是下一个扩展难题。
编程语言和工具链也属于这片范围。运行时 Pod 可用于活跃线程的 CPU 和内存有限,而每次生成的修改都可能开启新一轮编辑、构建和测试。Bun 从 Zig 转向 Rust 后,在解决稳定性与内存安全问题的同时,降低了内存占用并提升吞吐量。TypeScript 的原生 Go 移植版之所以启动,是因为原有实现无法适应最大的代码库;早期构建速度约快十倍,内存占用也显著降低。在我的开发服务器上,Tetral 的一条集成路径可能花上七八分钟,完整验证则大约需要半小时。编译与验证可能比推理更早成为瓶颈。
执行环境承受的负载与稳定服务不同。短生命周期的环境需要调度、创建、供给资源、暂停、恢复、释放和回收。突发创建、挂载与恢复延迟、高频更替下的调度,都与启动时间一样重要。达到足够规模时,它们会碰上常规服务编排原本未针对其设计的协调与控制平面限制。
不是每项操作都值得启动一个沙箱。文件访问可能只需虚拟文件系统;不可信代码需要更强的隔离;平台特定工作则需要相应机器。问题不只是能运行多少沙箱,还在于有多少工作必须经过完整计算机,以及能多快提供所需的每种边界。
Actor 系统提供了另一种设计思路:轻量、可寻址、能休眠与唤醒,却不必配置整台计算机的计算单元。这种原语该如何映射到 Tetral 的会话、线程或资源工作进程,目前仍是开放问题。眼下只能得出一点:完整沙箱不应是每项操作的默认边界。
只有产出能在执行环境消失后继续存在,一次性环境才有用。这暴露了另一条资源边界:存储。会话事件、工具结果与日志必须进入有序的会话历史;代码、文档与构建产物则必须回到代码库、对象存储或工作空间文件中,以便其他环境日后加载。
并行智能体越多,状态转移、文件、提交、拉取请求和测试运行就越多,把这些接口背后的系统推向新限制。会话日志可以借助 PostgreSQL 副本、连接池、缓存、工作负载隔离,以及写入密集型数据的拆分来扩展。当智能体产生的 Git 操作超出传统托管服务的能力,代码存储可能需要新实现,例如围绕对象存储中的预写日志和可替换本地代码库重建的 Git 兼容托管服务。
智能体依旧请求会话历史、文件或代码库。随着需求增长而改变的,是这些存储接口背后的基础设施。
模型本身也正成为更大交付单元的一部分。对于 Claude Opus 4.6 之后发布的模型,temperature、top_k 和 top_p 已被弃用;当前智能体接口则更强调推理力度、工具、技能、MCP 服务器、上下文、策略与编排。现行模型指南也转向推理控制、托管工具和多智能体执行。未来配置的产品可能越来越像包含模型的智能体系统,而不是外围堆满产品专用基础设施的裸模型端点。
从 alpha 走向智能体原生云
Tetral 目前是运行在个人 k3s 集群上的 alpha 版本,尚不是经过生产验证的云服务。运行时的放置尚未考虑容量;背压还没有打通准入、Queue 压力和扩展;持续的多节点恢复也尚未得到证明。由于尚未实现跨版本的优雅排空,运行时发布也会打断进行中的轮次。当前服务拓扑还需要生产环境的证据,因为这次发布首先聚焦运行时、声明与恢复边界。
每一项限制都指出下一步的建设方向。会话需要按运行时容量放置,并能跨节点恢复。Queue 压力必须控制准入和工作进程供给。执行层需要更快的激活、挂载与恢复,更轻量的文件访问、自托管提供商,以及让一个智能体同时协调多台计算机的能力。小型部署还应能将逻辑服务合并到较少进程,而生产部署能独立扩展它们;Temporal 的服务部署模型已经展示了这种灵活性。
产品方向是一项托管的智能体系统服务。产品团队应能定义自己的工具、审查者、线程策略、资源、模型和界面,而不必先重建连续性、身份、授权、恢复和资源调度。相同的系统还应支持更安全的执行、跨越多个客户端和计算机的新产品,以及回顾、评估和未来训练所需的会话证据。
随着这些工作负载真正出现,实现方式也会改变。服务可能合并,运行时可能不再依赖 Bun,存储可能拆分,Queue、Bridge 或 Kubernetes 拓扑也可能被替换。三个判断会保留下来:智能体是云原生的;需要扩展的是整个智能体系统,而不只是模型;运行时让智能体保持计算中心的地位,周围的系统则维系连续性与控制。
这些判断现在足够具体,可以和其他人一起检验。Tetral 以 MIT 许可证开源,让产品开发者、基础设施工程师、安全研究者及模型提供商都能质疑其边界、实现新的运行时、连接新资源,构建当前系统未曾预见的产品。这套主张已足够具体,可以公开接受检验。这个 alpha 版本,是探索更广阔的智能体原生云的起点。