五类 Agent Harness 对比:Session Compact、长任务与 Memory
对比五类 Agent Harness 后可以看到:长任务的核心不只是压缩上下文,而是保存状态、控制副作用并允许人重新介入。
Agent Harness 很容易被理解成“给模型装上工具”。但只要任务持续得足够久,真正困难的部分就会浮现:上下文会膨胀,执行现场会消失,副作用无法简单回滚,人也需要在中途重新介入。
因此,比较 Harness 不能只看一次 Agent Loop 跑得多漂亮。更有价值的问题是:Session 如何保存,Compact 丢掉了什么,长任务怎样恢复,Memory 又在哪一层发挥作用。下面从这些边界出发,对比 Codex CLI、Mastra、Pi、DeepSeek Harness 与 Downcity。
先说结论:Compact 只是长任务的一环
五个系统表面上都在做“让模型循环调用工具”,但它们对状态的基本判断完全不同:
- Codex CLI:Session 是可恢复的工程线程,compact 是服务化的上下文维护能力。 它把模型调用、线程存储、usage、沙箱、审批和审计放进一个强工程化运行时。压缩既可以本地完成,也可以交给 Responses API 的服务端
/responses/compact;子 Agent 通过父子 thread 树派生,适合一次任务内的短生命周期并行执行。 - Mastra Agent:Session 是 workflow 的运行实例,compact/memory 是框架内置的 context runtime。 Agent loop 被表达为可快照的 workflow,支持 pending、paused、suspended 和
resumeStream()。Memory 不只是历史消息,而是 working、semantic、observational、history 等多层能力;Observational Memory 用 Observer/Reflector 后台把原始轨迹压成 observation log。 - Pi Agent:Session 是可导航的分支树,compaction 是可回溯的有损压缩。 历史以 JSONL 保存,
/tree、/fork、/clone让用户在历史任一点分叉。压缩只改变当前工作上下文,不删除完整历史;压缩摘要还会保留 readFiles、modifiedFiles 等文件级工作线索。它是五者中 Session UX 最成熟、最适合人工探索和回溯的系统。 - DeepSeek Harness:Session log 是唯一事实源,compact 是插件化的可替换能力。 dsh 以 “Everything is a Plugin” 为架构原则,agent loop、模型、工具注册表、会话日志和 compaction 都位于插件树中。它用
Model-visible ⟺ logged约束模型所见内容必须可由日志重建,并通过 Cordis 的可逆副作用和响应式依赖支持组合、热替换与自修改。 - Downcity SDK:以既有 Workspace 为边界的分层 Agent Runtime。 Downcity 把 Agent、Workspace、Session、Turn 分开,
SessionLoop负责命令队列和 turn 生命周期,Executor负责单次执行编排,CoreEngineRunner负责工具循环;compact 基于 provider 返回的真实 usage,memory 保持为插件而不是核心状态系统。它的重点不是做一个全栈 Agent 产品,而是让 Agent 进入用户已有项目,并在其上叠加 Shell、Sandbox、Plugin、City/Federation 等产品化能力。
最重要的结论不是谁“压缩算法最好”,而是五者在解决四个不同层面的问题:
- Compact 解决的是当前请求如何不超过窗口,以及如何降低 context rot。
- Session 解决的是一次对话/线程如何持久化、分支、恢复和审计。
- Long-running execution 解决的是模型循环、工具进程、审批等待、网络中断和跨进程恢复能否继续。
- Memory 解决的是哪些经验应跨 turn、跨 session、跨 agent 留存,以及如何被检索、修改、审计和遗忘。
如果把这四层混成一个“memory”对象,系统很快会变得不可解释。正确的设计应当是:
Session log / event journal = 事实与审计层
Compact summary = 当前上下文的有损视图
Execution checkpoint = 运行现场的恢复层
Working / semantic / episodic = 可检索的记忆层
Files / skills / artifacts = 人可编辑的外部知识层
四种状态不能混为一谈
Conversation history 不等于 Memory
最小 Session 通常保存:用户消息、assistant 消息、tool call、tool result、系统事件和运行元数据。它回答“这次发生了什么”。
Memory 则回答“哪些内容值得在未来再次使用”。它需要 scope、重要性、时间、来源、冲突、权限、召回和淘汰策略。把完整 transcript 每次原样塞回 prompt,只是 history persistence,不是长期记忆。
Compact 不等于 checkpoint
Compact 通常是把旧消息压成摘要,替换当前 prompt 中的一段历史。它保存的是模型继续工作所需的语义状态,不一定保存执行现场。
Checkpoint 保存的则可能是:当前 workflow step、pending tool call、审批状态、重试次数、任务预算、子进程句柄、内核状态或 event offset。摘要告诉模型“之前做了什么”,checkpoint 让 runtime 知道“下一步从哪里继续”。
Memory 不等于“越多越好”
长上下文存在 context rot:输入越长,相关但不能回答问题的干扰项越多,检索和推理互相挤占。LongMemEval 类问题也显示,只给相关片段时表现较好,把完整长历史全部塞入时反而显著下降。
因此,Memory 的核心不是存储容量,而是在正确时机,以正确粒度,向模型暴露正确内容。这也是 token budget、priority、recency、scope 和 progressive disclosure 必须成为一等设计的原因。
Codex CLI:以工程线程为中心
Session/Thread 的基本模型
Codex CLI 的 Session 更接近“工程任务线程”,而不是一个长期人格 Agent。核心循环在 ModelClientSession 中通过 Responses API 流式运行;thread store、状态数据库、audit、rollout、usage 和 TUI/IDE app-server 共同支撑它。
在多 Agent 场景中,Codex 采用父子执行树,而不是长期 Agent 团队:
Parent thread/session
├─ spawn child task
├─ send_message / followup_task
├─ wait
└─ resume / interrupt / close
子 Agent 有 parent session、path、depth、任务名和生命周期状态。派生时可以继承完整历史、使用压缩后的上下文、切换角色指令、指定模型和 reasoning effort。因此,spawn 本身也是一次上下文切分:父线程保留控制权,子线程只承接完成局部任务所需的上下文。
Compact 的实现逻辑
工作区源码索引显示,Codex 的压缩由 compact.rs、compact_remote_v2.rs 和 compact_model_fallback.rs 等模块组成,主要逻辑可以还原为:
- 读取 provider 返回的真实 usage,而不是完全依赖本地估算。
- 根据 token budget 判断当前上下文是否接近或超过窗口。
- 选择本地或服务端压缩路径。
- 将较早的消息、工具事务和工作进展压缩为 checkpoint/summary。
- 保留不能被破坏的最新 user 消息和最新工具事务。
- 将压缩后的上下文继续交给 Responses API 执行。
其关键特点是服务端 compact:本地运行时只需要关心预算、历史边界和恢复;模型侧的压缩可由 OpenAI 服务完成。这减少了客户端对具体摘要 prompt、tokenizer 和 provider 差异的负担,但也进一步强化了对 OpenAI Responses API 的绑定。
长任务策略
Codex 的长任务能力主要来自四个部分:
- 真实 usage 驱动的上下文维护:避免因为本地估算误差导致请求突然溢出。
- 可恢复的 thread/store:会话、rollout、audit 和状态库让任务具备暂停后重启的基础。
- 父子执行树:把大任务切成短生命周期子任务,由父 Agent 汇总,降低单个上下文不断膨胀的压力。
- 安全运行时:Linux 的 bubblewrap、Landlock、seccomp,macOS Seatbelt,Windows sandbox,以及网络代理和 guardian 审查,使长任务不等于长时间无限制执行。
但 Codex 的长任务本质仍是“工程线程持续推进”,不是 Prime Agent 那种 daemon + heartbeat + autonomous goal,也不是 Mastra 那种通用 durable workflow。它擅长把一次编码任务跑完并可恢复,不以长期后台人格或跨任务自我学习为中心。
Memory 设计
Codex 具备 memories、thread-store、状态日志和 skills 等能力,但应区分:
- thread store:保存当前/历史线程;
- rollout/audit:保存执行和安全审计;
- memories:提供更长期的经验或偏好入口;
- skills:人或系统维护的可复用程序性知识。
Codex 的优势是“模型所做过的事情”被工程日志、usage 和审计体系包围;局限是长期 Memory 的领域模型不是它最突出的产品中心,而且完整云侧能力与 ChatGPT/OpenAI 服务绑定。它更像强 Session + 强安全 + 可选 Memory,而不是 memory-first 框架。
评价
Codex 的设计取舍是:宁可绑定一个强大的云端协议,也要把安全、用量、恢复和可观测性做成完整系统。它适合企业级 coding agent、受控工作区和一次任务内并行协作;不适合需要多模型一等公民、跨 provider 的本地长期记忆实验。
Mastra:把 Agent Loop 变成可恢复 Workflow
Session 与 Workflow 的关系
Mastra 最关键的判断是:Agent loop 不应只是一个不可见的 while,而应是可以持久化和恢复的 workflow。其 agentic loop 以 createWorkflow().dowhile(agentic-execution) 表达,并拆成多个步骤:LLM execution、tool call、mapping、background-task check、signal drain、task completion 和 goal step。
因此,Mastra 的 Session 更接近一个 workflow run:
Session / Run
└─ Workflow execution
├─ LLM step
├─ Tool step
├─ background/signal step
└─ checkpoint snapshot
快照重点覆盖 pending、paused、suspended 三类状态,resumeStream() 从暂停点继续;DurableAgent 则把这个能力延伸到跨进程恢复。
Compact 与 Observational Memory
Mastra 将“历史太长”拆成两个相互配合的机制:
第一层是 history/context 管理。 当前对话历史仍然需要进入运行上下文,框架通过 token threshold、context budget 和 storage adapter 控制加载范围。
第二层是 Observational Memory。 Observer 和 Reflector 作为后台 Agent:
- 读取增长中的 message/tool history。
- 形成密集的 observation log,而不是继续保留全部原始轨迹。
- 在需要时通过 temporal marker、extractor 和 working-memory update 重组上下文。
- 通过异步 buffering 尽量不阻塞主 agent loop。
这不是简单的“把前 N 条消息截断”,而是把历史转换为另一种面向任务的表示:保留目标、事实、进展、决策和重要观察,减少模型每轮重新扫描工具输出的成本。
Prompt cache 的取舍
Observational Memory 的工程难点是压缩会改变 prompt 前缀。即使最近消息保持原样,只要 system/history 前面的结构从原始 transcript 变成 observation,provider 的 prompt cache 也可能失效。因此 Mastra 通过阈值、异步 buffer 和密集 observation 来减少频繁重写。
这里存在三角权衡:
信息保真度 ↔ 上下文长度 ↔ Prompt cache 命中率
压缩过频,缓存不断重建且摘要会有损;压缩过晚,context rot 和请求成本上升。Mastra 的方向是后台观察和批量压缩,而不是每个 tool call 后立即总结。
长任务策略
Mastra 是五者中对“长任务运行时”抽象最完整的之一:
- workflow snapshot:记录步骤和状态;
- pause/resume:审批、外部事件或资源不足时挂起;
- signals:运行中注入异步事件;
- schedules/background tasks:把工作移出当前请求;
- DurableAgent/EventedAgent:支持跨进程和事件驱动;
- workspace/process 工具:执行长进程、读取输出、kill process;
- 远程 workspace:Docker、E2B、Daytona、Modal 等后端。
这套逻辑解决了“模型还没完成,但 HTTP 请求已经结束”的问题。需要注意,workflow checkpoint 和 shell 子进程现场仍是两个层次:恢复 workflow 不必然能恢复一个已经消失的操作系统进程,除非 workspace backend 自己提供进程持久化。
Memory 设计
Mastra 的 Memory 是内置能力,至少包含:
- history:会话消息历史;
- working memory:当前用户/任务的结构化状态,通常通过工具调用或 schema 更新;
- semantic memory:跨 session 的事实和相似内容召回;
- observational memory:从长轨迹沉淀出的密集观察。
同时它拥有多种 storage adapter,以及 RAG、embedding、rerank 等配套。优点是开箱即用,应用很快得到一条完整链路;代价是 Memory 与 Mastra Agent、Storage、RAG 生命周期耦合较深。观察日志仍是模型派生物,不能自动当成不可争议的事实源。生产系统仍应保留原始证据、来源和可编辑的 canonical data。
评价
Mastra 的核心创新不是某一个摘要 prompt,而是把上下文、执行、存储和记忆统一成可持久化 runtime。它最适合作为 TypeScript Agent SDK 的默认参考:如果产品需要 HITL、后台任务、RAG、working memory 和 durable execution,Mastra 的完成度很高。缺点是全内置带来复杂度、耦合和较重的依赖面,且开源框架层与托管云能力需要分开评估。
Pi:用 Session Tree 支持回溯
Session 是树,不是线
Pi 的 Session 采用 JSONL 持久化,但逻辑上是一棵树。每个节点是消息/事件,分叉点保留 parent 关系。用户可以:
/tree:浏览历史树;/fork:从任意历史点开新分支;/clone:复制当前分支继续实验;- bookmark/label:给重要状态打标。
这意味着“错误尝试”不必被删除,“新方向”也不必污染主线。Session 不只保存最终 transcript,还保存用户对执行历史的导航选择。
Compaction 的具体流程
Pi 的压缩逻辑具有四个要点:
- 自动触发 + 手动触发:turn 结束后检查上下文占用,接近窗口时自动 compact;用户也可用
/compact主动触发。 - 保留最近窗口:按可配置 token budget 原样保留最近一段消息,默认约 20K token;之前历史交给独立 LLM 请求总结。
- 摘要请求与主对话隔离:改变 system prompt 和 user instruction,让模型输出覆盖目标、进展、决策、关键上下文的结构化交接摘要;可以使用更便宜的模型。
- 溢出兜底:如果 turn 执行中已经撞到窗口上限,先 compact,再恢复未完成的任务,而不是直接让会话报废。
压缩后的摘要写回 Session,作为纯文本继续参与后续请求。模型切换时摘要可移植,不必因换 provider 重新压缩。
Pi 的独特性在于:压缩是当前分支的工作视图变化,不是历史事实的删除。 完整历史仍在 JSONL 中,可通过 /tree 回看和从旧节点 fork。
文件级上下文追踪
Coding agent 的摘要不能只写“完成了若干工作”。Pi 的 compaction utils 会统计 readFiles、modifiedFiles 等文件操作,提醒后续 Agent 哪些文件已经读过、改过、验证过。这个设计把“代码工作状态”显式写进 handoff briefing,减少压缩后模型重新扫描整个仓库的需要。
长任务策略
Pi 的长任务主要依靠:
- 持续的流式 agent step;
- queue mode 和 steering,在运行中插入用户引导;
- abort signal 与工具输出截断;
- 文件 mutation queue,避免并发写文件互相覆盖;
- session tree/fork/clone,让人可以在长任务中保留多个方案;
- 扩展系统接入 sandbox、permission gate、subagent、SSH、git checkpoint 等能力。
Pi 原生更强调“一个人和一个可导航的 Agent 一起工作”,而不是 durable workflow 平台。默认没有内建强沙箱,安全主要通过扩展实现;也没有 Codex/Mastra 那样系统级的跨进程 workflow 恢复。对于交互式 coding,它的可控性和可探索性极强;对于无人值守长任务,需要额外 daemon、sandbox、heartbeat 和外部 supervisor。
Memory 设计
Pi 的核心 memory 是“可回看的 Session 历史 + 压缩摘要 + 文件工作线索”,而不是内置企业级长期事实库。它通过扩展实现更强的 memory、skill、subagent 或外部检索。
这是一种有意的窄内核策略:
- 原始证据留在 JSONL;
- 当前 prompt 使用 compact summary;
- 可复用知识沉淀到扩展、skill 或项目文件;
- 其他长期 Memory 由插件决定。
优势是可移植、透明、不会强迫用户接受某一种向量数据库;缺点是跨 session 事实提炼、冲突治理、权限和自动召回需要自行搭建。
评价
Pi 解决的是“长对话如何不丢失可回溯性,以及人如何继续掌控分支”。它证明了 compact 不必等于不可逆删历史:压缩当前上下文,保留完整事件源,是 coding harness 非常值得采用的模式。
DeepSeek Harness:不可变日志与可逆 Runtime
Session log 是唯一事实源
dsh 的架构铁律是:Model-visible ⟺ logged。凡是到达模型请求的内容,都必须能够从 session log 重建;fork、resume、transcript、telemetry 和持久化都从这条日志派生。
这与普通“保存聊天记录”不同:日志不是 UI transcript 的附属物,而是 runtime 的 canonical event stream。它使以下能力具有共同基础:
- 重建某次模型请求;
- 审计模型看到了什么;
- 从历史 fork 出新 Session;
- 在压缩后解释摘要来自哪些事件;
- 在插件卸载/替换后恢复运行状态。
Compact 作为插件
dsh 的包结构包含 compaction/ 和 context/,但它们不被设计成不可替换的核心黑盒。Profile、bundle、patch 可以组合插件树;agent loop、session log、工具和模型也都是插件。
因此 dsh 的 compact 逻辑可以理解为:
- session log 持续追加原始事件;
- context 插件根据 token budget/上下文策略决定需要压缩的范围;
- compaction 插件生成新的上下文表示;
- 新表示仍作为可重建、可记录的事件/派生视图进入日志体系;
- 后续 fork/resume 使用同一事实源,而不是只依赖内存中的 prompt 数组。
dsh 的重点不是公开一个固定的摘要参数,而是让压缩成为可替换的 runtime seam。这允许不同 profile 使用不同 compact 策略,也符合其“能力定义 + provider + consumer”的三角色能力缝。
长任务与可逆副作用
DeepSeek Harness 的长任务优势不主要体现在一个专门的 autonomous scheduler,而在于运行时组合能力:
- 插件树:可以替换模型、工具、loop、workspace、sandbox、session 和 compaction;
- Cordis temporal composability:插件产生的副作用带有可追踪逆操作,卸载时可以 unwind;
- Cordis spatial composability:插件声明依赖并响应式获取服务,能力变更能通知消费者;
- headless/web/ACP:同一个 runtime 通过不同宿主运行;
- self-modification:Agent 可以自省并挂载插件,但这依赖严格的权限和可回退机制;
- 可替换 sandbox:本地、E2B、远程执行世界可以通过 provider 迁移。
这是一种“runtime 长寿命”而非“单任务无限变长”的路线。它回答的是:当任务需要热装卸能力、改变工具面、切换执行后端或从中断点继续时,如何不把系统变成一堆残留回调和隐式状态。
Memory 设计
dsh 的 Memory 基础首先是 event log,而不是内置的 semantic memory 产品。它提供了形成 Memory 所需的正确锚点:模型可见内容可重建、工具轨迹可审计、fork/resume 有统一来源、插件可替换。
但“日志是事实源”不意味着“日志就是长期记忆”。要实现跨 session 的用户事实、团队知识、skill 或向量检索,还需要额外的 memory plugin。dsh 的强项是为这些插件提供一致的 runtime 生命周期和事件输入;弱项是 developer preview 阶段仍不应把插件化能力等同于成熟的长期记忆治理。
评价
dsh 把问题下沉到组合语义:如何把一个能力装上、使用、卸下并干净回滚。它最值得借鉴的不是“所有东西都插件化”这句口号,而是两个工程不变式:
- 模型所见必须可重建。
- 运行时副作用必须可回退。
这会让 compact、memory、self-modification 和长任务恢复拥有共同的可审计基础。代价是架构复杂度和学习成本较高,且 developer preview 的 breaking change 风险需要单独计入。
把五种 Harness 放在一起
核心机制矩阵
| 维度 | Codex CLI | Mastra Agent | Pi Agent | DeepSeek Harness | Downcity SDK |
|---|---|---|---|---|---|
| Session 隐喻 | 工程 thread | workflow run | 可导航 session tree | append-only session log | Workspace 内的 Agent Session |
| 原始事实源 | thread/store + audit/log | storage + workflow snapshot | JSONL 全历史 | session log,模型所见必记录 | JSONL message store + SessionEventHub |
| Compact 触发 | usage/token budget,含服务端 compact | context budget + observational pipeline | turn 后自动、手动、溢出兜底 | context/compaction 插件策略 | provider 真实 usage,约 95% 触发并回落至约 50% |
| Compact 结果 | checkpoint/summary,偏继续执行 | observation/working context | 结构化 handoff summary | 可替换的 context 派生视图 | checkpoint summary,原子保留最新 user/tool transaction |
| 原始历史是否保留 | 由 thread/store 与 rollout 能力支持 | 取决于 storage/config,通常与 memory 分层 | 保留,压缩可回溯 | 日志作为 canonical source | JSONL 持久化,checkpoint 作为当前视图 |
| 运行恢复 | thread、app-server、状态/审计基础 | workflow snapshot + resumeStream | 交互式 resume,非完整 durable workflow | log + plugin runtime + resume 方向 | SessionLoop/Executor 恢复策略,尚未等同 durable workflow |
| 运行中注入 | parent message/followup、控制面 | signals/background tasks | steering/queue mode | interaction/event/plugin 机制 | Session command queue、stop/cancel、ActionSchedule |
| 长任务重点 | 安全、恢复、父子并行 | durable workflow、HITL、后台任务 | 人机导航、分支、扩展 | 热替换、可逆副作用、可组合 runtime | Workspace 边界、审批、usage、可复用 runtime |
| 内置长期 Memory | 有入口但非中心 | working/semantic/observational/history | 核心较轻,扩展为主 | 事件源为基础,Memory 插件化 | Memory 插件化,Session 不与 Memory 混同 |
| 多模型 | OpenAI 绑定较深 | AI SDK + gateway/router | 30+ provider 一等支持 | provider 可插件化 | AI SDK 注入,City 负责路由/计量 |
| 安全 | 最强:沙箱 + guardian + 网络策略 | native/remote workspace,能力丰富 | 默认安全依赖扩展 | sandbox provider 可替换,需看 profile | deny-default 沙箱 + ShellApprovalRuntime |
| 适合场景 | 企业 coding、受控执行 | 全栈 Agent 应用、durable workflow | 交互式 coding、探索和分叉 | 可组合、自修改、可替换 harness | 多产品 Agent 基础设施、repo-native workflow |
四种不同的 Compact 哲学
Codex:服务化压缩。 重点是让强 provider 处理压缩,客户端保持工程边界和恢复能力。
Mastra:观察式压缩。 重点是把历史持续转成 observation,借后台 Agent 和异步 buffer 维护长会话。
Pi:交接式压缩。 重点是摘要像换班 briefing,当前上下文变短,但完整历史仍可回看和分叉。
dsh:组合式压缩。 重点是 compact 不应成为核心魔法,而应通过插件、日志和 capability seam 被替换、审计和回退。
Downcity:Workspace-native 的分层 Harness
它解决的问题不同
Downcity SDK 不把自己定位成另一个面向终端用户的编码 Agent,也不把 Agent loop 做成一个全栈应用框架。它的基本边界是:Agent 进入一个已有 Workspace,在项目原生的文件、目录、脚本、文档、配置和工作流中执行。
对象关系可以概括为:
Agent
├─ model / instruction / plugins
└─ enter(Workspace)
└─ AgentWorkspace
└─ Sessions
└─ Turn
Workspace 负责项目路径、Shell、Sandbox 和环境;Agent 负责模型、指令和插件;Session 负责连续交互;Turn 表示一次 prompt 到结果的执行过程。这个所有权划分很关键:它避免把项目文件、模型身份、会话历史和长期 Memory 塞进一个大对象。
执行循环的分层
已有源码拆解显示,Downcity 的执行链分成三层:
- SessionLoop:Session command queue 的唯一消费者,拥有 turn 生命周期。Prompt 进入 FIFO 队列,stop 可以取消排队项。
- Executor:编排一次 session execution,处理 recovery policy、重试以及错误后的压缩恢复。
- CoreEngineRunner:执行模型与工具的循环;
CoreEngineLoopDecision将“不完整响应恢复、工具调用续跑、text-only 续跑、停止”等判断抽成纯函数。
这套分层与 Mastra 的 workflow 不同。Mastra 把循环表达为可快照 workflow;Downcity 把循环表达为命令队列 + 执行器 + 纯函数决策。前者天然适合 durable step resume,后者天然适合在一个 Workspace 中插入 prompt、取消排队命令、连接插件和控制执行边界。
Compact 的实现取舍
Downcity 的 compact 不是按字符长度或调用前估算触发,而是根据 provider 返回的真实 usage 管理上下文。已有源码分析记录的策略是:上下文使用量达到窗口约 95% 时触发,压缩后回落到约 50% 以内;历史折叠成 checkpoint,并原子保留 user 消息与最新 tool transaction。
这带来三个工程收益:
- provider 的 tokenizer 和实际计费差异不会完全由客户端猜测;
- 最新用户意图和正在完成的工具事务不被摘要过程拆散;
- Executor 可以把“出错 → 压缩 → 重试”作为明确的恢复路径,而不是把 overflow 当成终止错误。
它的主要不足也很清楚:当前模型更接近“checkpoint 压缩 + session continuation”,还没有 Pi 那样完整的 session tree/fork UX,也没有 Mastra 那样成熟的 observational memory 后台流水线。若要达到 durable execution,必须进一步持久化挂起点、当前 loop step、审批状态、重试预算和外部进程状态,而不只是保存一份摘要。
长任务与 Workspace 边界
Downcity 的长任务能力主要建立在 Workspace 和控制面之上:
SessionLoop提供命令排队、停止和 turn 生命周期;ExecutorRecoveryPolicy负责失败恢复与压缩重试;ShellApprovalRuntime把需要授权的命令放到审批网关;- macOS Seatbelt、Linux Bubblewrap、Windows MXC/SRT 提供可替换沙箱后端;
ActionScheduleStore支持定时动作;SessionEventHub、JSONL message store 和 usage 记录提供可观察性;- City/Federation 负责模型目录、路由、认证、计量、计费和跨 Agent/Workspace 的产品化边界。
这里的长任务不是“一个 Agent 在后台自主运行”的默认形态,而是“一个可进入既有项目的 runtime 能持续、安全、可计量地执行工作流”。与 Prime Agent 的 daemon、heartbeat、autonomous goals 相比,Downcity 的主线更偏多产品基础设施;与 Mastra 的远程 workspace 相比,它更强调 repo-native 边界和审批控制。
Memory:明确保持为插件
Downcity 当前有意不把 Memory 做成 Agent 核心。这个决策与 Session 边界有关:Session 保存这次运行发生的事实,Memory 插件决定哪些事实值得跨 session 保留。
其合理的最小 Memory SPI 可以覆盖:
read / write / observe / consolidate
这样可以接入本地文件或 SQLite,也可以接入 Mastra memory、mem0、Cognee 等外部实现。关键是适配器不应取代 Session 的 canonical history,也不应让某个向量数据库定义 Downcity 的领域模型。
这个选择牺牲了 Mastra 式的开箱即用,但保留了更强的替换自由度。对 Downcity 来说,长期差异化不应是再实现一个通用向量记忆,而是把 Memory 与 Workspace、项目文件、Skill、权限、usage 和 City 计量连接起来。
Downcity 的独特层:City/Federation
Codex、Pi、Mastra 和 dsh 主要竞争 Agent 运行时本身;Downcity 额外提供 City/Federation:
- Agent、Workspace 和 Plugin 的服务化索引;
- 模型路由和 fallback;
- AI usage 和 metering;
- 账户、余额、支付和组织服务;
- bureau token、远程 Agent 和跨组织连接。
这使 Downcity 更像“Agent Harness + Agent Productization Base”。它的竞争问题不是“是否比 Mastra 多一个工具”,而是能否让多个 Agent 产品共享相同的执行、计量、权限和工作区边界。
评价
Downcity SDK 最值得保留的设计是边界清晰:Workspace 不拥有 Agent,Session 不冒充 Memory,Executor 不直接承担 City 的产品逻辑,插件提供能力而不是把核心循环复制一遍。
它当前最明显的缺口也与这个定位直接相关:测试数量、durable pause/resume、Memory 默认实现、evals 和跨进程执行恢复仍需要补齐。换句话说,Downcity 的架构方向与成熟方案一致,但可信度必须由恢复测试、压缩测试、沙箱测试、计量测试和 Memory adapter 测试来兑现。
长任务的难题远不止 Compact
一个任务要持续数小时甚至数天,至少要同时解决以下问题:
上下文膨胀
工具结果、文件内容、失败尝试和模型中间轨迹不断增加。解决方案是 compact、prune、渐进披露和检索,而不是简单扩大 context window。
执行现场消失
HTTP 请求结束、进程重启、机器断电后,模型摘要不足以恢复 shell 进程、审批等待、未完成工具调用和外部资源锁。Mastra 的 workflow snapshot、Codex 的 thread/state、dsh 的 event log 都是在解决这层;Pi 默认仍更偏交互式会话。
人类需要重新介入
长任务不是完全无人值守。审批、澄清、预算超限、目标改变和错误恢复都要求 Agent 能暂停并等待。Mastra 的 HITL pause/resume 最直接;Codex 有强审批策略;Pi 通过 steering 和扩展完成;dsh 把 interaction 也视为插件能力。
代码和工具的外部副作用
长任务可能修改文件、启动服务、写数据库、消耗 token、访问网络。恢复时必须知道哪些副作用已经发生,不能仅凭模型自述。Codex 的 audit/guardian、Pi 的 git checkpoint 扩展、dsh 的 revertible effects,以及事件日志,分别提供了不同答案。
预算和调度
长任务需要 token、时间、工具调用次数、并发数、费用和失败重试预算。Mastra 有后台任务和 workflow 生态,Codex 有 usage/rollout,Pi 可由扩展和上层 supervisor 补齐,dsh 可通过插件组合。真正生产化的系统必须把预算状态写入可恢复的 execution state。
Memory 应该分层,而不是堆成一个池
从五个系统可以抽出一套更稳定的 Memory 分层:
L0:原始 Session/Event Log
不可变或 append-only,保存用户消息、模型输出、工具调用、工具结果、审批和系统事件。它是证据层,不直接全部注入 prompt。
L1:Working Memory
当前任务的结构化状态,例如目标、约束、已确认决定、待办、已修改文件、测试状态、外部资源 ID。它应可由 Agent 工具显式更新,最好有 schema、版本和 owner。
L2:Compaction / Observation
从近期或历史轨迹生成的密集交接摘要。它服务于当前 context,不应自动升级为事实数据库。应保存来源 event range、生成模型、时间和版本,支持重建与重新生成。
L3:Semantic/Episodic Memory
跨 session 检索的事实、过去案例、用户偏好、项目知识和经验。需要 scope、时态、置信度、来源、权限、冲突和删除策略。
L4:Procedural Assets
Skills、规则、模板、代码片段、workflow 和可复用工具。它们比向量记录更接近“能直接改变未来行为”的知识,必须版本化、可审阅、可回滚。
L5:Live Execution State
正在运行的进程、内核变量、网络连接、队列、scheduler、checkpoint 和资源锁。这是 Prime Agent 所展示的“活内核”路线,也是最难审计、最不可移植的一层。不能把它与 L0-L4 混称为 memory。
推荐的注入顺序为:
system policy
→ project / user working memory
→ relevant semantic/episodic memories
→ compacted session briefing
→ recent raw messages and tool transactions
每一层都应有 token budget;召回结果应渐进披露,而不是把全部结果一次塞进上下文。
哪些机制值得学习
最值得学习的机制
- 学 Codex:真实 provider usage 驱动 compact;安全策略、网络策略和审计必须进入主架构;子任务用父子执行树隔离上下文。
- 学 Mastra:把 agent loop 设计成可 snapshot/resume 的 workflow;审批不是结束流后重新发起,而是从挂起点继续;Memory 应有 working、observational、semantic 的明确分层。
- 学 Pi:保留完整原始历史,压缩只是当前工作视图;session tree/fork/clone 是长任务的人类控制面;摘要应包含文件、决策和未完成事项,而非泛泛总结。
- 学 dsh:建立
Model-visible ⟺ logged不变式;为插件副作用登记逆操作;让 compaction、workspace、sandbox、model 和 loop 通过 capability seam 替换,而不是散落硬编码。
不应直接照搬的部分
- 不应把所有 history 都直接变成长期 Memory;Mastra observation 也必须保留 evidence。
- 不应只做摘要而不做 execution checkpoint;否则“知道发生过什么”仍不能“从中断点继续”。
- 不应为了插件化把每个内部对象都抽象掉;dsh 的组合能力很强,但产品级 runtime 仍需清晰的稳定核心。
- 不应把 daemon、heartbeat、autonomous scheduler 当作长任务的全部答案;它们解决调度,不解决安全、审计、事实一致性和恢复。
- 不应把 prompt cache 当作压缩后的附带问题;压缩策略必须记录缓存失效成本,并以批量、阈值和异步 buffer 控制频率。
一个更完整的目标架构
一个面向现有工作区、支持长任务的 harness,可以采用如下分层:
SessionEventLog(append-only canonical source)
↓
Turn / Tool Transaction / Approval Event
↓
Execution Checkpoint(loop step、预算、挂起点、资源状态)
↓
Context Manager
├─ recent raw window
├─ compaction summary
├─ working memory
└─ relevant long-term memory
↓
Model request(所有可见内容可从 log 重建)
实现优先级:
- P0:日志不变式——记录所有模型可见内容、工具事务和审批事件,并可重放一次请求。
- P0:真实 usage compact——支持阈值触发、溢出兜底、最新工具事务原子保留、摘要来源可追溯。
- P0:working memory——用 schema 管理目标、决策、待办、文件和验证状态,避免全部依赖自然语言摘要。
- P1:pause/resume checkpoint——先实现审批挂起,再扩展到外部事件、跨进程和长进程。
- P1:Session tree/fork——保留原始 history,允许从任意 checkpoint 创建分支。
- P1:Memory SPI——冻结
read / write / observe / consolidate等最小接口,允许接本地 SQLite、Mastra、mem0 或其他服务,而不把 provider 核心化。 - P2:可逆 effect——为文件修改、插件挂载、环境变量和进程等副作用逐步增加 undo/rollback 能力。
- P2:evals 与成本报表——评估摘要事实保真度、恢复成功率、召回准确率、缓存命中率和每任务成本。
建议的最小评测指标
- compact 后任务继续成功率;
- 摘要遗漏关键决策率;
- 文件状态和测试状态保真率;
- overflow recovery 成功率;
- pause/resume 后重复副作用率;
- memory 召回 precision/recall;
- prompt cache 在 compact 前后的命中率;
- 长任务每有效完成任务的 token、时间与费用;
- 从原始 log 重建 model-visible context 的一致率。
最后:Harness 管理的是连续性
五个 Harness 的竞争,不是“谁有更多工具”,而是“谁能把状态变成可靠的执行基础设施”:
- Codex 把可靠性押在 工程化、安全和 provider 服务;
- Mastra 把可靠性押在 workflow、存储和内置 Memory runtime;
- Pi 把可靠性押在 可回溯 Session 和人类导航;
- DeepSeek Harness 把可靠性押在 日志不变式、可逆副作用和插件组合语义。
对于未来的 Agent 产品,最可能成为默认配置的不是单一方案,而是五者的组合:
Codex 的安全与 usage
+ Mastra 的 durable workflow 与分层 memory
+ Pi 的 session tree 与可回溯 compact
+ dsh 的 event-sourced plugin runtime 与可逆 effects
但组合时必须守住边界:原始日志是证据,compact 是视图,checkpoint 是恢复状态,Memory 是经过治理的可复用知识,live runtime 是执行现场。
真正的机会也不在再造一个更大的 Agent loop,而在于把这五类状态之间的转换做成可观察、可恢复、可审计、可计量的协议。谁能让长任务在压缩之后仍然知道“目标是什么、已经做了什么、下一步是什么、哪些副作用已经发生、哪些记忆值得保留”,谁才真正拥有下一代 Agent Harness 的基础设施能力。
资料来源与边界
03-研究/源码拆解/Agent 源码对比:Hermes · Codex CLI · Pi · Downcity.mdx:Codex、Pi、Mastra 的源码快照对比,以及 Mastra workflow/memory 对比。03-研究/源码拆解/DeepSeek Harness (dsh) 与 Downcity Harness 对比.mdx:DeepSeek Harness 的插件树、Cordis、session log、Model-visible ⟺ logged与可逆副作用分析。03-研究/领域调研/web plugin/memory 2.mdx:Mastra Observational Memory、Session/Memory 边界、Memory 分层和其他方案横向研究。LanLance on X 读懂 Pi 的上下文压缩机制 - X.mdx:Pi compaction 的触发、保留窗口、溢出兜底、缓存代价与交接摘要设计。deepseek-harness-团队面试准备 · yopedia.mdx:Downcity Agent/Workspace/Session/Turn 的运行时组织方式,可作为 dsh 对照的工作区背景资料。03-研究/源码拆解/Agent 源码对比:Hermes · Codex CLI · Pi · Downcity.mdx:Downcity SDK 的SessionLoop、Executor、CoreEngineRunner、真实 usage compact、沙箱、插件和 City/Federation 源码拆解。
边界声明:本文不把工作区中关于未来版本、生态规模或未逐行复核的实现描述当作稳定 API;涉及具体模块名和参数时,应以相应仓库当前源码与官方文档重新核验。