一、同一项脚本任务,为什么会长成两套 Runtime
假设用户交来一项很普通的任务:“把数据清洗脚本改成支持 region 字段,运行检查,再把结果交给我。”
我们先不问产品叫 Coding Agent 还是 General Agent,只看任务怎样发生。
第一种场景里,Agent 从已经打开的 repository 开始。它知道当前目录,读取源码和项目规则,修改文件,运行测试, 再把 diff、退出码和测试结果留在同一个工作区。用户第二天回来,文件与 Git 状态通常还在;但昨天启动的后台进程、 尚未完成的工具调用和模型会话是否还在,是另外三个问题。
第二种场景里,用户只上传了一份压缩包。服务先创建 task 与 session,再给这次运行分配 sandbox, 把输入材料恢复到 workspace。Agent 仍然可以改文件和跑命令,但当前 worker 与 sandbox 都可能被回收。 最终报告必须离开临时现场,保存成有用户、会话和版本归属的 artifact;下次请求也不能只靠“碰巧还在这台机器的目录”继续。
先记住结论: General / Coding 描述产品把哪种工作对象放在中心;Local / Cloud 描述执行环境与持久状态由谁拥有。 它们是两条坐标,不是一条从“普通”到“高级”的能力等级。
这篇固定跟踪同一项脚本任务,只回答五个问题:
- “workspace 是第一公民”具体承诺了什么?
- 会执行代码,为什么还不一定是 Coding Agent?
- 云端 sandbox、workspace 与 durable storage 为什么必须拆开?
- Session、Artifact、Memory 和文件目录各自保存什么?
- 本地与云端恢复分别会在哪些地方停止?
证据边界。 本文用 Pi 的 coding harness、AgentScope 的 service example、Agno 的 AgentOS,以及 tRPC-Agent-Go 的 Session、CodeExecutor、workspace、Artifact 与 Memory 公开源码说明可见契约。文中的四象限与“工作现场”是跨框架的工程归纳; 不推断任何产品未公开的容器实现、存储拓扑、调度策略或保留时长。
二、第一公民不是“工具列表里有 bash”
如果 Agent 的 tools 里出现 read_file 和 bash,我们最多只能确认模型可以请求两种动作。
“第一公民”是更强的运行契约:runtime 不仅暴露操作,还要认识操作发生在哪个对象上,并接住它的整个生命周期。
回到这次脚本修改。一个真正的一等 workspace 至少要回答五件事:
- 身份:这是哪个 repository、branch、task 或 workspace,而不是一个随手拼出的路径。
- 操作:读取、搜索、patch、shell、测试和 Git 都围绕同一个现场发生。
- 治理:路径、命令、网络、Secrets 与审批有明确边界。
- 证据:文件变化、命令退出码、测试报告和生成物可以被观察与关联。
- 恢复:进程或客户端离开以后,runtime 知道哪些状态可以重新装载,哪些已经丢失。
| 只“拥有一个工具” | 把对象做成第一公民 | 差别会在哪里暴露 |
|---|---|---|
bash(command) |
命令绑定 workspace、权限、环境、取消和结果记录 | 失败后能否知道命令在哪运行、改了什么 |
write_file(path) |
文件属于 repository 或 task workspace,并能形成 diff | 下一轮读取的是同一份状态,还是另一台机器的空目录 |
| 返回下载链接 | Artifact 有 owner、版本、媒体类型和生命周期 | 链接失效后,服务能否按 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。 可复用 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 为什么要把现场拆成多个 Owner
云端版本不能假定下一次请求一定落在同一进程。于是“一个目录”必须被拆成几种不同承诺: 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 Service plane 接住多用户与重连,但不能靠组件名证明恢复
AgentScope 的 example service 把 create_app、RedisStorage、message bus、
LocalWorkspaceManager、MCP 与 subagent template 接到一起。
这条装配路径
证明它考虑了 service、storage 和 workspace;但单独看见 RedisStorage,仍不足以证明 pending tool state、
event cursor 与 workspace snapshot 已经支持跨进程恢复。
Agno 把平台责任展示得更完整。AgentOS 同时装配 agents、teams、workflows、database、authorization、
registry、scheduler、tracing 和 interfaces;初始化时还会注入 OS-level database/checkpoint 并开启 event storage。
对应源码在
AgentOS.__init__
与
运行对象初始化。
这类 service plane 的第一公民是 run、session、identity 与 platform service,不是某台 worker 的 cwd。
5.3 CodeExecutor、Workspace 与 Artifact 解决三种问题
tRPC-Agent-Go 的源码把这条边界说得很直白:
CodeExecutor
回答“程序怎样运行”;
stageSkill
为一次执行准备可写工作副本;
artifact.Service
则按 Session、文件名与 revision 保存交付文件。
因此“支持代码执行”只覆盖中间那段尝试。若没有 workspace owner,输入、依赖与中间文件没有一致现场; 若没有 artifact owner,最终报告仍困在可能被回收的目录。三者可以由同一台机器实现,但语义上不能合并。
六、四种状态,不是一块磁盘
现在把同一项任务的状态摆在一起。Session、Workspace、Artifact 和 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,而不是每轮必写。
七、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 补发 missed events 并重连仍在运行的流。
两条路径分别见
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,就能看清每条协议连接的是哪两个工作现场。
参考源码与延伸阅读
- Pi Agent Harness README
- Pi
SessionManager - Pi Security
- AgentScope agent service example
- Agno
AgentOS - Agno AgentOS run routes
- tRPC-Agent-Go
CodeExecutor - tRPC-Agent-Go Artifact Service
- tRPC-Agent-Go Memory Service
- 本系列:Pi Agent Harness
- 本系列:AgentScope Runtime
- 本系列:Agno Agent Platform
- 本系列:tRPC-Agent-Go Runtime