
目录1. 如何优雅地驾驭长期运行的 AI Agent2. 上下文压缩让长期 Agent 永不“失忆“3. 工作区Workspace文件即真理目录即架构4. 双层记忆系统 让 Agent 拥有真正的“长期大脑“5. 文件系统一套代码三种部署零改动切换6. 沙箱Sandbox让 Agent 在安全笼子里自由奔跑7. 子 Agent 编排 文件驱动的多智能体协作架构8. Skill技能让 Agent 从“会说话“进化为“会做事“9. Plan Mode 让 Agent 先想清楚再动手10. Channel Agent 通信的“神经系统“设计LLM 的 token 预算是有限的。一段对话越跑越长要么主动压缩、要么撞到模型的硬上限报错。AgentScope Harness 给出了四种正交策略让你按需组合、从容应对。一、问题背景为什么需要上下文压缩在构建长期运行的 AI Agent 时上下文窗口是最根本的物理约束。一个持续对话的 Agent 会面临两类膨胀膨胀类型表现典型场景太深消息条数 / token 累计过多多轮对话、反复调用工具太宽单条工具结果体量巨大grep 返回大量匹配、execute 输出冗长日志如果不做任何处理Agent 迟早会撞上 context_length_exceeded 错误轻则中断任务重则丢失关键上下文。AgentScope Java 2.0 的 Harness 模块内置了一整套压缩链路默认关闭、按需开启通过 .compaction(…) 或 .toolResultEviction(…) 一行配置即可激活。二、架构定位压缩在整体链路中的位置理解压缩机制首先要明确它在 Harness 架构中的位置┌──────────────────────────────────────────────────────┐ │ HarnessAgent.call() │ │ │ │ ┌────────────┐ ┌──────────────────────────────┐ │ │ │ 压缩链路 │───▶│ AgentState.contextMutable() │ │ │ │ (内存操作) │ │ (对话消息列表) │ │ │ └────────────┘ └──────────────┬───────────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────────────────────┐ │ │ │ AgentStateStore (持久化) │ │ │ │ call() 结束时整体写入 │ │ │ └──────────────────────────────┘ │ └──────────────────────────────────────────────────────┘关键设计压缩在内存中更新 AgentState.contextMutable()状态存储在 call 结束时把更新后的 AgentState 整体持久化。两条路径独立但按顺序执行——状态存储拿到的永远是压缩后的版本。这意味着压缩是有损但可控的你选择压缩就接受前缀消息被摘要替代但框架保证压缩前的关键信息不会凭空消失后文详述 Memory 联动。三、四大正交策略详解Harness 提供四种策略彼此正交、可任意组合、默认全部不开。这种按需装配的设计哲学贯穿整个 Harness 架构。策略一对话摘要压缩CompactionMiddleware**解决的问题**上下文太深——消息条数或 token 累计过多。**触发时机**每次模型推理前。工作原理原始对话: [msg1, msg2, ..., msg25, msg26, msg27, msg28, msg29, msg30] ↑ 触发阈值(30条) 压缩后: [summary] [msg21, msg22, ..., msg30] ↑ ↑ LLM生成的摘要 保留最近10条原文配置示例HarnessAgent.builder().compaction(CompactionConfig.builder().triggerMessages(30)// 30 条消息触发压缩.keepMessages(10)// 压缩后保留最近 10 条原文.build()).build();**摘要结构**默认摘要 prompt 会将内容组织为四个小节SESSION INTENT本次会话的意图和目标SUMMARY已完成的工作摘要ARTIFACTS产出的关键产物文件、配置等NEXT STEPS下一步计划这种结构化摘要特别适合工程/编排类 Agent确保压缩后 Agent 仍能接住上下文继续工作。进阶配置字段说明triggerTokens按估算 token 数触发与 triggerMessages 二选一或并用keepTokens按 token 数保留尾部消息flushBeforeCompact摘要前是否先抽取事实到长期记忆默认 trueoffloadBeforeCompact摘要前是否将原始消息写入日志文件默认 truemodel为压缩摘要指定独立模型不设则用 Agent 主模型 实践建议如果主模型是昂贵的旗舰模型如 GPT-4o可以通过 .model(…) 指定一个轻量模型专门做摘要大幅降低压缩成本。策略二大工具结果卸载ToolResultEvictionMiddleware**解决的问题**上下文太宽——单条工具结果体量过大。**触发时机**工具执行后。工作原理工具返回 120K 字符的结果 │ ▼ 超过阈值默认 80K 字符 ≈ 20K tokens │ ├──▶ 全文写入工作区文件: /workspace/tool-results/xxx.txt │ └──▶ 上下文中替换为: [前 2K 字符] ... [内容已卸载到文件] ... [后 2K 字符] read_file 路径提示配置示例HarnessAgent.builder().toolResultEviction(ToolResultEvictionConfig.defaults()).build();**智能排除列表**以下工具默认不触发卸载——它们要么自带分页、要么返回值天然很小read_file / write_file / edit_filegrep_files / glob_files / list_filesmemory_* / session_search而 Shell execute默认不排除因为命令输出可能非常大如 find / 或 cat 大文件。 设计亮点Agent 想看被卸载的全文时只需自己调用 read_file 读取对应路径即可。这是一种延迟加载思想——不预先占满上下文需要时再取。策略三上下文溢出兜底**解决的问题**真的撞到了模型的 context_length_exceeded 硬上限。**触发时机**call() 抛错时。工作原理模型返回 context_length_exceeded / maximum context / token limit 错误 │ ▼ HarnessAgent.recoverFromOverflow() │ ├──▶ 强制执行 triggerMessages1 的极端压缩 │ 只保留最近 1 条消息 摘要 │ └──▶ 自动重试一次**关键前提**必须已配置 .compaction(…)否则错误原样抛回上层。// 只要 compaction 开了溢出恢复就自动开——无需额外配置HarnessAgent.builder().compaction(CompactionConfig.builder().triggerMessages(30).keepMessages(10).build()).build();这是一条最后防线——正常情况下策略一和策略二应该已经足够但如果真的溢出了框架不会静默失败而是尝试自救。策略四预压缩参数截断可选**解决的问题**工具调用参数如 write_file 的文件内容体量大但后期没人再看。**触发时机**摘要之前的轻量预处理不走 LLM。配置示例CompactionConfig.builder().triggerMessages(80).truncateArgs(CompactionConfig.TruncateArgsConfig.builder().maxArgLength(2000)// 参数超过 2000 字符就截断.truncationText(... [truncated] ...).build()).build();**为什么有效**write_file、edit_file 这类工具的入参往往包含完整的文件内容可能几万字符但写入完成后这些参数在后续对话中几乎没有参考价值。提前截断它们可以显著推迟摘要触发的时机。 性价比之王这一步几乎零成本纯字符串操作不调 LLM却能大幅降低触发摘要的频率。强烈建议与策略一搭配使用。四、压缩与 Memory 的联动信息不会凭空消失这是 Harness 压缩设计中最精妙的部分。很多人担心压缩把前缀消息摘要掉了那些信息岂不是丢了答案是不会丢因为框架在压缩前做了两件保底操作。4.1 flushBeforeCompact默认 true摘要发生前MemoryFlushMiddleware MemoryFlushManager 会先把对话前缀中的有价值事实抽取到长期记忆中压缩前的对话前缀 │ ▼ MemoryFlushMiddleware │ ├──▶ 读取 workspace/MEMORY.md已有记忆 ├──▶ 读取 memory/*.md日志层 └──▶ 增量写入新事实之后即使前缀消息被摘要替代Agent 仍可通过 memory_search / memory_get 工具回头查阅这些事实。4.2 offloadBeforeCompact默认 true摘要前把原始消息整段写到永不压缩的 *.log.jsonl 文件原始消息 ──▶ workspace/agents/agentId/sessions/sessionId.log.jsonl这份日志供 session_search 工具检索是真正的全量备份。联动流程图触发压缩 │ ├── ① flushBeforeCompact: 事实 → MEMORY.md / memory/*.md │ ├── ② offloadBeforeCompact: 原始消息 → *.log.jsonl │ ├── ③ truncateArgs: 截断大参数可选 │ └── ④ LLM 摘要: 前缀 → [summary] 结果: [summary] [recent tail] 写回 AgentState五、压缩不会触碰的内容ConversationCompactor 只处理 AgentState.contextMutable() 里的对话消息列表。以下组件完全不受压缩影响组件存储位置为什么不受影响Plan Mode 状态AgentState.getPlanModeContext() 工作区 plans/独立字段生命周期由 Plan Mode 自己管理子 Agent 后台任务/agents//tasks/.json由 TaskRepository 维护通过 system reminder 注入不进入对话流todo_write 任务清单AgentState.getTasksContext()独立字段跟着 AgentState 持久化但不参与压缩权限规则AgentState.getPermissionContext()独立字段自带持久化✅ 结论你可以放心开启 .compaction(…)不用担心丢 Plan、丢未完成的后台 Task、丢权限配置。压缩通路对它们是透明的。六、用 Agent 自己查历史会话启用会话能力时默认开三个查询工具会自动注册Agent 可以自主调用工具功能示例session_list列出某个 Agent 的历史会话session_list agentId“coder”session_history查看某次会话最近 N 条消息session_history agentId“coder” sessionId“abc” lastN20session_search在历史会话中关键词搜索session_search query“数据库迁移” agentId“coder”关键点这些工具读的是永不压缩的对话日志*.log.jsonl所以即使当前上下文已经被压缩成摘要Agent 也能查到任意历史消息的原文。这形成了一个优雅的闭环压缩丢掉细节 → Agent 需要回忆 → 调用 session_search → 找回原始信息七、最佳实践与配置建议场景一轻量对话 Agent对话轮次少// 不需要任何压缩配置默认即可HarnessAgent.builder().workspace(/path/to/ws).build();场景二工程编码 Agent长对话 大文件操作HarnessAgent.builder().compaction(CompactionConfig.builder().triggerMessages(50).keepMessages(10).truncateArgs(CompactionConfig.TruncateArgsConfig.builder().maxArgLength(2000).build()).build()).toolResultEviction(ToolResultEvictionConfig.defaults()).workspace(/path/to/ws).build();场景三成本敏感场景用便宜模型做摘要HarnessAgent.builder().compaction(CompactionConfig.builder().triggerMessages(40).keepMessages(8).model(cheapModel)// 用轻量模型做摘要主模型只做推理.build()).build();配置决策树你的 Agent 会跑多少轮 ├── 20 轮 → 不需要压缩 ├── 20~100 轮 → 开启 compaction truncateArgs └── 100 轮或不确定 → compaction truncateArgs toolResultEviction 溢出兜底自动生效八、设计哲学总结回顾整套压缩机制可以提炼出几个核心设计原则正交组合四种策略解决不同维度的问题互不干扰、自由搭配默认关闭不预设用户需要压缩避免不必要的 LLM 调用开销有损但可恢复压缩是有损的但通过 Memory 联动和日志备份确保信息可追溯零成本优先参数截断这种免费操作放在 LLM 摘要之前能省则省透明隔离压缩只碰对话消息Plan、Task、权限等状态完全不受影响。九、结语上下文压缩不是一个锦上添花的功能而是长期 Agent 走向生产的必备基础设施。AgentScope Harness 的设计给出了一个教科书级的答案用分层策略应对不同维度的膨胀用Memory 联动保证信息不丢失用正交设计保持系统的可组合性用零成本预处理降低整体开销。