一、同一项脚本任务,为什么会长成两套 Runtime

假设用户交来一项很普通的任务:“把数据清洗脚本改成支持 region 字段,运行检查,再把结果交给我。” 我们先不问产品叫 Coding Agent 还是 General Agent,只看任务怎样发生。

第一种场景里,Agent 从已经打开的 repository 开始。它知道当前目录,读取源码和项目规则,修改文件,运行测试, 再把 diff、退出码和测试结果留在同一个工作区。用户第二天回来,文件与 Git 状态通常还在;但昨天启动的后台进程、 尚未完成的工具调用和模型会话是否还在,是另外三个问题。

第二种场景里,用户只上传了一份压缩包。服务先创建 task 与 session,再给这次运行分配 sandbox, 把输入材料恢复到 workspace。Agent 仍然可以改文件和跑命令,但当前 worker 与 sandbox 都可能被回收。 最终报告必须离开临时现场,保存成有用户、会话和版本归属的 artifact;下次请求也不能只靠“碰巧还在这台机器的目录”继续。

先记住结论: General / Coding 描述产品把哪种工作对象放在中心;Local / Cloud 描述执行环境在哪里,以及持久状态由服务还是用户机器保存。 它们是两条坐标,不是一条从“普通”到“高级”的能力等级。

这篇固定跟踪同一项脚本任务,只回答五个问题:

  1. “workspace 是第一公民”具体承诺了什么?
  2. 会执行代码,为什么还不一定是 Coding Agent?
  3. 云端 sandbox、workspace 与 durable storage 为什么必须拆开?
  4. Session、Artifact、Memory 和文件目录各自保存什么?
  5. 本地与云端恢复分别会在哪些地方停止?

本文依据。 本文用 Pi 的 coding harness、AgentScope 的 service example、Agno 的 AgentOS,以及 tRPC-Agent-Go 的 Session、CodeExecutor、Workspace、Artifact 与 Memory 公开源码说明实际行为。文中的四象限与“工作现场”是跨框架的比较方法; 不推断任何产品未公开的容器实现、存储拓扑、调度策略或保留时长。

二、第一公民不是“工具列表里有 bash”

如果 Agent 的 tools 里出现 read_file 和 bash,我们最多只能确认模型可以请求两种动作。 “第一公民”是更强的运行契约:runtime 不仅暴露操作,还要认识操作发生在哪个对象上,并接住它的整个生命周期。

回到这次脚本修改。一个真正的一等 workspace 至少要回答五件事:

  1. 身份:这是哪个 repository、branch、task 或 workspace,而不是一个随手拼出的路径。
  2. 操作:读取、搜索、patch、shell、测试和 Git 都围绕同一个现场发生。
  3. 限制:哪些路径、命令、网络和 Secret 可以使用,哪些动作需要审批。
  4. 结果:文件变化、命令退出码、测试报告和生成物可以被观察并关联到这次运行。
  5. 恢复:进程或客户端离开以后,runtime 知道哪些状态可以重新装载,哪些已经丢失。
只“拥有一个工具” 把对象做成第一公民 差别会在哪里暴露
bash(command) 命令绑定 workspace、权限、环境、取消和结果记录 失败后能否知道命令在哪运行、改了什么
write_file(path) 文件属于 repository 或 task workspace,并能形成 diff 下一轮读取的是同一份状态,还是另一台机器的空目录
返回下载链接 Artifact 关联用户或 Task,并保存版本、媒体类型和生命周期 链接失效后,服务能否按 task/session 重新找到结果
把几句话写进数据库 Memory 有用户作用域、更新、删除、检索和采用规则 旧事实怎样被纠正,多个用户怎样避免串线

所以,通用 Agent 加一个代码解释器后,可以完成代码任务;Coding Agent 也可以借助文件和 shell 写报告、整理数据、制作演示。 分类不能靠“能做什么”硬切。更稳定的判断是:产品默认围绕什么对象组织上下文、权限、结果和恢复。

三、先分任务坐标,再分部署坐标

3.1 Coding / General:哪种工作对象处在中心

Coding-oriented Agent 通常把 project 或 repository 当作主对象。模型输入会主动吸收项目规则、文件结构和当前 diff; 工具结果天然表现为文件修改、命令输出和测试证据;完成标准往往是“patch 正确、测试通过、改动可审查”。

General-purpose Agent 更常把 user task、session 或业务记录放在中心。文件可能只是输入材料,代码执行只是处理材料的一种手段; 最终结果也可能是答案、表格、报告、CRM 更新或审批记录。它更关心用户身份、业务权限、跨渠道 session 与 artifact 交付。

3.2 Local / Cloud:谁拥有执行环境与持久状态

Local 不等于“只有命令行”,Cloud 也不等于“没有文件系统”。这里问的是 authoritative worksite 在哪里。 本地型 runtime 通常直接借用用户机器的目录、进程、凭据与操作系统身份;云端型 runtime 则由服务分配 worker 或 sandbox, 并把需要跨 worker 生存的状态放到外部 owner。

两条轴交叉后,四个象限都成立:

形态 工作现场 常见第一公民 首要工程压力
本地 Coding Agent 用户机器上的 repository cwd、files、Git、shell、tests 项目信任、权限、环境污染与可审查 patch
云端 Coding Agent 远程 repository workspace 或受管开发环境 task、repo snapshot、patch、build/test artifact 环境重建、Secrets、网络策略、并发与成本
本地通用 Agent 个人设备与桌面应用 用户文件、桌面工具、个人上下文 设备权限、隐私、应用间副作用
云端通用 Agent 多租户 service + 临时或受管 sandbox user、session、task、artifact、business tool 租户隔离、恢复、配额、审计与长期状态

这张表不是四种互斥产品。云端控制面可以把某些命令交给本地执行器;本地客户端也可以租用远程 sandbox。 混合架构里最重要的不是给整套产品贴一个标签,而是逐项标出 workspace、执行权限、durable record 和最终副作用的 owner。

四、本地 Coding Harness 为什么天然围绕 Workspace

Pi 提供了一个足够清楚的本地参照。它把模型接入、agent loop、coding harness 与终端 UI 拆成 四层 package。这描述的是本文采用的本地 coding harness 路径;仓库还包含 Chord、telemetry、durable 等独立包。 可复用 core 负责模型、工具调用和事件;coding-agent 层再装配 read、write、edit、bash、resources、session tree 与 compaction。 这说明 workspace 能力不是 provider API 自带的,而是产品 runtime 主动接走的责任。

把脚本任务写成运行记录,可以看到本地路径里哪些对象天然稳定:

Task C-17:增加 region 字段
worksite = repository / branch

read schema.py
edit cleaner.py
bash pytest -q
  -> exit 1:缺少 fixture
edit test_cleaner.py
bash pytest -q
  -> exit 0

observable result = files + diff + test output

会话账本与磁盘仍然不是一回事。Pi 的 SessionManager 用 append-only JSONL tree 保存 message、tool result、 model change、branch 与 compaction entry;当前 leaf 决定恢复哪条会话路径。 上下文重建 可以恢复 model-visible history,却不会把 repository 自动回滚到旧 leaf。真正试验另一份代码状态仍需要 Git branch、worktree 或 sandbox。

安全边界也直接继承现场。Pi 的 project trust 决定是否加载项目中的 settings、extensions、skills 和 prompts, 但官方 Security 文档 明确说它不是 sandbox。没有额外 gate 时,文件与命令仍继承启动进程的操作系统权限。 本地带来了丰富环境,也把用户机器变成了真实 blast radius。

本地磁盘存在,只能证明某些文件还在。 它不自动证明旧 shell 进程仍活着、外部 API 没有重复执行、会话可以重放,或模型能解释每一处现存修改。

五、云端 Runtime 为什么要把现场状态分开保存

云端版本不能假定下一次请求一定落在同一进程。于是“一个目录”必须被拆成几种不同承诺: task/session 保存运行身份,sandbox 提供当前执行环境,workspace 承载可变文件,artifact store 保存已交付结果, memory store 保存以后还要检索的知识。

5.1 先创建运行身份,再租用执行环境

一个典型的服务路径会先把用户请求正规化成带身份的 run,再为需要执行代码的步骤准备 sandbox。 下面只是 shape-level 路径,不对应任何私有产品 schema:

request
  {user_id, task_id, session_id, input_refs}

service plane
  -> authorize tenant and tool policy
  -> lease sandbox
  -> restore task workspace
  -> run agent loop and stream events
  -> promote selected outputs to artifacts
  -> persist run/session state
  -> release or snapshot sandbox

顺序里最关键的是“promote selected outputs”。临时目录中的 cache、依赖、半成品与日志不会因为任务结束就全部成为永久资产; 应用必须决定哪些文件带着 owner、版本和媒体类型离开现场。

5.2 服务层接住多用户与重连,但组件名不能证明恢复能力

AgentScope 的 example service 把 create_app、RedisStorage、message bus、 LocalWorkspaceManager、MCP 与 subagent template 接到一起。 这条装配路径 证明它考虑了 service、storage 和 workspace;但单独看见 RedisStorage,仍不足以证明 pending tool state、 event cursor 与 workspace snapshot 已经支持跨进程恢复。示例默认仍是 InMemoryMessageBus,注释给出了多进程时改用 RedisMessageBus 的方式;知识库示例的 QdrantStore(location=":memory:") 也不能证明向量跨进程持久化。

Agno 把平台责任展示得更完整。AgentOS 同时装配 agents、teams、workflows、database、authorization、 registry、scheduler、tracing 和 interfaces;初始化时为未单独配置的 Agent 注入 OS-level database/checkpoint,并开启 event storage。 对应源码在 AgentOS.__init__ 与 运行对象初始化。 这类 service plane 的第一公民是 run、session、identity 与 platform service,不是某台 worker 的 cwd。

后台执行还要把“已接受”与“已完成”分开。Agno 的 后台接受路径在配置持久队列、请求满足入队条件且新任务成功入队后返回 202 与 PENDING;它只确认任务已进入执行体系,不能作为报告已经生成的证据。不满足持久入队条件的请求可能走进程内后台路径,因此仅凭 202 也不能断言任务已持久化。队列与事件传输配置也区分并发排队与跨副本传输:配置 queue.redis 可联通取消与事件流,显式 event_stream 可覆盖事件后端。事件可重连仍不等于任意进程状态都能重建。

5.3 CodeExecutor、Workspace 与 Artifact 解决三种问题

tRPC-Agent-Go 的源码把这条边界说得很直白: CodeExecutor 回答“程序怎样运行”; stageSkill 为一次执行准备可写工作副本; artifact.Service 则按 Session、文件名与 revision 保存交付文件。

因此“支持代码执行”只覆盖中间那段尝试。若没有 workspace owner,输入、依赖与中间文件没有一致现场; 若没有 artifact owner,最终报告仍困在可能被回收的目录。三者可以由同一台机器实现,但语义上不能合并。

工作区身份还要分成两层。tRPC-Agent-Go 的 WorkspaceInstanceProvider / IsWorkspaceRetrySafe 允许同一个逻辑 Workspace.ID 和路径对应新的物理执行实例;支持该可选能力的后端可以让缓存句柄失效并重新准备现场。workspace_exec仅在 stale 错误被判定为可安全重试时重新执行一次;超时、丢失响应、部分产物提交或其他副作用不确定的失败不能靠自动重放解决。实例编号不是文件版本,也不是持久化内容的证明。

六、四种状态,不是一块磁盘

现在把同一项任务的状态摆在一起。Session、Workspace、Artifact 和 Memory 都可能最终落到文件或数据库, 但存储介质相同不代表生命周期相同。

Agent Runtime 四种状态手绘图:Session 账本保存运行经过,Workspace 承载可变文件,选中的文件被提升为 Artifact,Session 证据沿可选提炼路径进入跨会话 Memory;文件持久化不等于进程恢复或长期记忆
四类状态各有生命周期。Workspace 中选中的文件才保存为 Artifact;Session 到 Memory 是可选提炼路径。
状态 owner 这次任务里保存什么 谁会再次读取 它不承诺什么
Session ledger 消息、事件、tool call/result、暂停点与 run 状态 恢复 runtime、构造下一轮 model view、前端回放 不保存完整工作目录,也不撤销业务副作用
Workspace 源码、输入文件、依赖、临时输出与当前修改 文件工具、shell、代码执行器和测试 目录还在不代表进程、会话和网络连接还在
Artifact 被选中交付的报告、图片、压缩包或构建结果 用户、前端、后续工具或业务系统 生成成功不代表内容已经验证或正式采用
Memory 跨会话仍有价值的 fact、episode、偏好或方法 未来 session 的检索与上下文装配 不是原始 transcript,也不应该收下全部文件

6.1 为什么 Artifact 必须经过“提升”

Workspace 是尝试现场,允许出现失败脚本、未完成报告和大量缓存;Artifact 是产品承诺,应该只保存明确选择的输出。 tRPC-Agent-Go 的 workspace_save_artifact 就把已有 workspace 文件保存成 artifact reference, 并把引用写进 state delta。源码在 文件提升路径。 这不是一次普通 copy,而是 owner 从“当前执行现场”变成“按 session 可引用的交付物”。

6.2 为什么 Memory 必须经过“提炼”

如果把每条日志、每份文件和每个失败尝试都写进长期 Memory,未来检索只会得到噪声。 tRPC-Agent-Go 的 Memory Service 把跨 Session 的 fact 与 episode 放在独立接口中; 当前 Session 仍保存原始运行记录。公开边界见 memory.Service。 自动抽取还要在 run 完成后读取增量消息、判断是否值得提炼,再执行 add/update/delete,而不是每轮必写。

外部检索内容也不能自动当成用户事实。对使用 AutoMemoryWorker 的后端,可以显式开启 WithDisableAutoMemoryOnExternalContext(true):成功的知识检索等工具通过外部内容标记设置 memory:mode = polluted,提炼入口以及实际消费队列的 worker 都会检查这一状态并跳过后续自动提炼。该选项默认关闭,也不禁用记忆预加载或显式 memory_add/update/delete。它保护的是自动写入边界,而不是清空整个会话的记忆能力。

七、Coding Agent 的 Memory 为什么看起来不一样

Coding Agent 有一个很强的外部状态源:repository 本身。项目规则可以写进说明文件,设计决策可以留在文档, 代码变化进入 Git,测试把预期固化成可执行证据。未来任务重新打开同一个 project 时,这些材料无需先被压成一段“用户记忆”。

但不能因此说“filesystem 就是 Memory”。文件可能只是当前实现,也可能包含过时注释、构建缓存和用户不希望长期保留的材料。 Session compaction 解决模型窗口压力,Git 记录代码版本,project instructions 约束工作方式,semantic Memory 才负责跨任务检索事实或经验。 它们可以都落在文件上,却仍然有不同 owner 与采用规则。

云端通用 Agent 更难借用一个稳定 repository 作为共同事实源。同一用户可能从多个入口发起任务,请求落到不同 worker, 业务数据还分散在外部系统。因此它通常更依赖 user/app-scoped Memory store、Session store、knowledge retrieval 与 Artifact store。 这不是因为 General Agent “记性更好”,而是因为状态必须从单机环境外部化,才能被多节点重新找到。

需要留下的东西 Coding-oriented 默认落点 Cloud general-purpose 默认落点 采用前要检查
项目约束 repository instructions、Skill、配置 应用策略、tenant 配置、tool policy 作用域和优先级是否正确
当前任务进度 session ledger + workspace + Git run/session store + sandbox snapshot 能否关联同一个 task 与副作用
跨任务知识 项目文档、已审查 Skill、可选 Memory user/app Memory、knowledge store 来源、更新、删除和隐私边界
最终交付 commit、patch、build/test artifact versioned artifact 或业务记录 内容校验、回归、审批与发布

八、恢复时,最容易混淆的是四种“还在”

用户说“昨天的任务还在吗”,可能同时在问四件事:对话记录还在吗,文件还在吗,进程还活着吗,外部副作用已经发生了吗。 Runtime 若只回答一个“是”,就会把不同恢复层级混成虚假保证。

中断 本地现场通常还剩什么 云端现场必须外部化什么 恢复边界
客户端断线 本地进程可能仍运行 run id、event cursor、buffer 或 event store 重连事件流不等于重启计算
Agent 进程退出 磁盘文件通常仍在 Session、pending state、workspace snapshot 未持久化的工具内部状态会丢失
执行环境回收 不常发生或由用户自己管理 输入引用、环境描述、snapshot、artifact 文件可重建不代表后台进程可续跑
外部写入超时 都需要幂等键、业务回执或补偿记录 恢复 agent loop 不能证明副作用 exactly-once

Agno 的 API 路由提供了一个很好的区分:continue 可以从持久化 run state 推进执行, resume 则用 last_event_index 补发缺失事件:仍活跃(包括排队中)的 run 继续接入事件流,已结束的 run 只回放已有事件。 两条路径分别见 continue run 和 resume stream。 “继续计算”与“重新看见事件”是两种恢复,不能因为都叫 resume 就合并。

九、把同一项任务完整重放一遍

本地 Coding 路径

用户选择 repository
  -> Agent 读取项目规则
  -> files / shell / tests 在同一 cwd
  -> Session 记录工具与模型过程
  -> Git diff 保存可审查修改
  -> 测试与人工 review 验证
  -> 用户决定是否 commit / merge

云端服务路径

服务创建 task / session
  -> 鉴权并分配 sandbox
  -> 恢复 workspace 与输入
  -> Agent 执行并流式发事件
  -> 选中输出提升为 artifact
  -> 校验器或审批验证结果
  -> 产品决定发布或交付

两条路径最后都必须分开三个状态。Agent 产生 patch 或报告,只能说明 output produced; 测试、schema 校验、安全扫描或业务规则通过,才是 output validated; commit、merge、发布、写入业务系统或由用户接收,才是 output adopted。 本地丰富的工具面与云端完整的 service plane 都不能替代最后两道门。

十、最后用这组问题选择 Runtime

设计问题 答案偏左时 答案偏右时
主要对象是长期 repository,还是一次 user task? 优先 coding-oriented workspace 优先 task/session service plane
authoritative files 在用户设备,还是由服务管理? 本地权限、project trust、Git 是核心 snapshot、artifact、tenant identity 是核心
依赖与后台进程是否必须跨天保留? 可复用现有开发环境 需要 named environment 或明确重建合同
请求是否会跨 worker、入口或设备继续? 本地 session 可能已经足够 必须外部化 run、event、pending state
哪些知识要跨任务生效? 项目文件、文档、Skill 可先承担 需要 user/app Memory 与检索治理
最终产物怎样进入真实世界? patch/test/review/merge artifact validation/approval/publish

可复用判断: 不要问“这个 Agent 能不能写代码”,要问 workspace 是否有稳定身份,执行权限由谁治理, Session、文件、进程和 Artifact 分别能活多久,Memory 对谁可见,以及最终结果由谁验证并采用。

下一篇把这些 owner 放到系统边界上。 当前端、工具服务、远程 Agent、编辑器与模型 provider 可以独立实现和升级时, runtime 还需要公开约定怎样发现能力、创建任务、传输事件和关联结果。 这时再读 MCP、A2A、AG-UI 与 Agent Client Protocol,就能看清每条协议连接的是哪两个工作现场。

参考源码与延伸阅读