AIGC标识 OpenCode × DeepSeek V4:多 Agent 上下文管理的两层优化实战

背景:Token 不便宜,但 Agent 天生能吃

在 OpenCode 多 Agent 框架下跑 DeepSeek V4,一个典型的开发会话长这样:Orchestrator 拆任务 → planner 出方案 → deep-worker 写代码 → reviewer 审结果。每一环都在往上下文里塞东西——prompt、tool call、返回结果、反复读写的文件内容。DeepSeek V4 给了 128K 窗口,但窗口大不代表你可以随便浪费。原生 compaction 是"被动兜底",等到快溢出了才动手,那时候 token 已经花出去了。

解决思路是两步走:让压缩变主动让内容在源头就变少


第一层:DCP——从被动兜底到主动裁剪

OpenCode DCP(Dynamic Context Pruning)和原生 compaction 有本质区别:原生是溢出时才出手,DCP 是持续感知、提前介入。下面这套配置是专门为 DeepSeek V4 的 128K 窗口调的。

双阈值,提前预警

"maxContextLimit": 85000,   // 85K 开始强力推压缩
"minContextLimit": 45000,   // 45K 开始温和提醒

不是等到 128K 溢出才应对。45K 时就开始提示"可以考虑压缩了",85K 时 hard push。模型在压缩后还有充足空间继续工作,而不是在溢出边缘勉强运转。

摘要缓冲——压缩后的内容不占窗口

"summaryBuffer": true

开启后,DCP 生成的压缩摘要不计入 maxContextLimit。这意味着你能一直积累对话历史(plan → impl → review → fix),却不会因此被踢出上下文窗口。对于跨多个阶段的长时间会话,这个能力很关键。

受保护工具——子 Agent 输出不丢

"protectedTools": ["task", "skill", "todowrite", "todoread"]

压缩的是"过程"(中间态的文件读取、重复的 tool 调用),不是"结果"。子 Agent 的 task 返回、skill 加载内容、todo 状态全部保留。

自动去重 + 错误清理

"deduplication": { "enabled": true },
"purgeErrors": { "enabled": true, "turns": 3 }

同一个 tool 同样参数重复调用?只保留最新一次。三轮前就失败的 tool call?清掉输入体,只留错误原因。这两项自动化策略在长会话里静默省 token,不用你手动干预。

子 Agent 不启用 DCP

"allowSubAgents": false

子 Agent 的生命周期很短,一两轮就结束了。上下文管理交给上层的 orchestrator,子 Agent 专心执行任务,不为压缩增加额外开销。

Nudge 更频繁

"nudgeFrequency": 3,              // 每 3 次 LLM 请求提醒一次
"iterationNudgeThreshold": 12,    // 第 12 条消息开始注入提醒
"nudgeForce": "strong"            // 明确要求优先考虑压缩

DCP 默认的提醒频率偏保守(5 次请求一次),对 DeepSeek V4 这种 token 敏感的配置来说偏慢了。收紧后的节奏让模型始终保持对上下文压力的感知。


第二层:源头减量——在 prompt 写出来之前就砍掉冗余

DCP 解决的是"已经产生的内容怎么压缩",但更好的策略是让内容压根就不要那么多。往下走:

砍掉 generalist Agent

generalist 角色是"不知道该分给谁的任务我来做"。实际运行中发现,light-orchestrator 完全能覆盖它的场景——单文件小改动、配置微调、简单修正。多一个 Agent 不单是多一个文件,而是全网的引用都要维护:orchestrator 的路由表、AGENTS.md 的 Flash 模型列表、opencode.json 的 agents 和 commands 各一条记录。删掉它,少了的不止 35 行文件,而是整张引用网的清理。

Agent prompt 瘦身 30-50%

10 个 Agent 的 prompt 文件逐一遍历,能砍的都砍了:冗余的修饰语和解释、重复的 Model Leverage 章节(这些信息已在一处集中说明)、子 Agent 不需要的 orchestrator 级别规则(插件行为、DCP 策略等)。最终结果:21 个文件,+184 行新增内容,-329 行冗余,净减少 145 行配置。每一行都在为每次 Agent 调用省钱。

全局规则加入缓存意识

AGENTS.md 里加了一条约束:

Prefer stable, prefix-matched prompt structures so OpenCode's cache can reuse compute across sessions. Avoid injecting dynamic content at the front of prompts.

DeepSeek 的 prompt cache 按前缀匹配。如果在 prompt 最前面塞时间戳、随机 ID,整段缓存就废了。这条规则保证所有 Agent 构造 prompt 时都会考虑缓存友好性。

插件行为集中文档化

superpowers(14 个过程型技能)和 DCP 的工作机制、边界行为、transform hook 的模块缓存特性、allowSubAgents: false 的限制,全部收敛到 AGENTS.md 尾部两个独立章节里。以前这些东西散落在各个 Agent prompt 的零散引用中,改一处要满世界同步。收敛后改一个地方,全局生效。

原生 compaction 参数收紧

// 调整后
"tail_turns": 8,                    // 从 10 下调
"preserve_recent_tokens": 12000     // 从 16000 下调

既然 DCP 已经在主动管理上下文,原生 compaction 从"主力"退到"兜底"。保留最小安全参数,不再为了"也许用得上"多留冗余。


两层机制的协作关系

DCP 和原生 compaction 不是叠床架屋,而是分工明确:

角色 工作方式 触发时机
DCP 主动感知,渐进推进 45K 提醒 → 85K 强推,持续裁
原生 compaction 被动兜底 窗口真正快满时安全接管

DCP 承担日常上下文管理,原生 compaction 只在极端情况下介入。两层之间不打架,也不互相依赖。


几个值得注意的设计细节

保护配置文件不被裁剪opencode.jsonAGENTS.md.env 等关键文件加了 protected pattern,确保配置相关的上下文始终完整。

错误不彻底消失purgeErrors 清理的是 3 轮前的旧错误,保留了错误原因;近期的失败信息依然可见,调试不会被截断。

summaryBuffer 配合压缩阈值。85K 就触发强压缩而非 128K——因为 summaryBuffer 让压缩摘要不占窗口,提前压缩不但不丢信息,反而腾出空间给新任务。

模型自主决策权manualMode: false 让 DCP 自主决定何时压缩,不需要等用户手动发 /dcp 命令。


上下文管理的本质不是你有多大的窗口,而是你能在窗口里装多少有价值的东西。DCP 负责把已有的东西压得紧凑,源头减量负责让没用的东西压根不进场。两条路方向一致,效果互相放大。

配置本身不运行,效果只有在实际会话里才能感受到。跑几个长任务,你会发现有些 token 被悄悄省掉了——而这就是这套配置的目的。


项目地址:github.com/znlgis/my-opencode-deepseek-config

posted @ 2026-07-24 14:07  我才是银古  阅读(161)  评论(0)    收藏  举报