← 返回 2026-03-10

面向终端构建AI编程Agent:脚手架、运行时框架、上下文工程与经验教训 Building AI Coding Agents for the Terminal: Scaffolding, Harness, Context Engineering, and Lessons Learned

Nghi D. Q. Bui 📅 2026-03-05 👍 7 2026-07-13 08:35
AI Agent 上下文工程 代码智能 系统架构 终端工具

首个开源CLI编程Agent完整技术报告:四层架构+五阶段自适应压缩+纵深防御安全

前置知识

ReAct循环

Reason+Act的agent推理范式,模型在每一轮先推理再行动,通过工具与环境交互。本文的Extended ReAct在标准ReAct基础上增加了显式的thinking(不带工具的独立推理调用)和可选的self-critique阶段,把"思考"和"执行"在API层面彻底解耦——思考阶段根本看不到工具schema,从而避免模型"看到工具就想立刻调用"的倾向。

OPENDEV的整个推理流水线(Algorithm 1)都建立在扩展ReAct之上,五阶段压缩、doom-loop检测、role:user提醒都嵌在这个循环的特定相位里。

Compound AI System

Zaharia等人提出的范式:把多个LLM、检索器、工具编排成一个结构化系统,而不是依赖单一巨型模型。OPENDEV把这一思想落到工程层面,定义了五个模型角色(Action、Thinking、Critique、Vision、Compact)并支持per-workflow的LLM绑定——切换模型只改配置不改代码。

这是OPENDEV"模型无关"的根本原因,也是它和单模型agent(如早期SWE-Agent)的核心架构区别。

上下文压缩(Context Compaction)

当LLM的上下文窗口接近耗尽时,对历史对话进行摘要、截断或重写以腾出空间。OPENDEV提出Adaptive Context Compaction(ACC)的五阶段渐进策略:70%警告→80%观察遮蔽→85%快速剪枝→90%激进遮蔽→99% LLM全量摘要,把"二值紧急压缩"变成"渐进调节"。

工具输出在典型session中占据70-80%的上下文,压缩策略直接决定一个session能跑多少轮——OPENDEV把典型session从15-20轮扩展到30-40轮,并把峰值上下文消耗降低约54%。

Language Server Protocol (LSP)

微软定义的编辑器与语言服务器之间的JSON-RPC协议,提供跨文件查找定义、重命名、引用解析等语义能力。OPENDEV集成了30+种语言的LSP服务器,通过两层缓存(原始响应+处理过的符号树)避免重复调用,并支持精确符号查找、引用追踪、workspace级重命名等。

代码编辑不是字符串替换——`text_search`找不出函数调用和同名变量的区别,只有LSP能给出"AuthController.validate在哪里被调用"这种语义查询。

Model Context Protocol (MCP)

Anthropic提出的标准协议,让LLM agent能动态发现并调用外部工具服务器。MCP理论上能让agent扩展无限能力,但如果把所有MCP工具的schema都塞进prompt,100个工具就能吃掉2万token。OPENDEV用lazy discovery解决:默认0个外部工具schema,agent需要时通过search_tools关键词检索,命中的工具schema才进入上下文。

MCP的"全部加载"模式让baseline占用高达40%上下文,Lazy方案把它压到<5%,这是OPENDEV扩展性的关键设计。

研究动机

现有的AI编程助手生态存在三个具体工程痛点。第一,IDE插件式copilot是被动响应型,需要开发者全程监督,无法处理长视野、多步骤的任务。第二,主流生产系统(Claude Code、各种闭源CLI)虽然终端化做得好,但都是闭源的,学术界无法复现其架构决策;开源CLI工具(Aider、Goose、OpenCode、Crush)又缺少技术报告,设计决策无从追溯。第三,真正开源且有技术报告的系统(SWE-Agent)是为benchmark评测设计的,不能日常交互使用——OpenHands虽然文档完善但跑在浏览器里而不是终端。Terminal-Bench显示即便是前沿模型也只能解决不到65%的CLI任务,LongCLI-Bench显示多类别编程任务的pass rate低于20%,这些数字暴露出专门工程化解决方案的必要性。

本文的目标是OPENDEV要交付一个"首个开源、终端原生、可交互的AI编程Agent"的完整技术报告,目标是:(1)填补"闭源工业实践"和"开放学术话语"之间的gap,让学界能复现生产级设计决策;(2)提供一个四层(Entry&UI / Agent / Tool&Context / Persistence)复合AI系统架构,用per-workflow模型路由把"单模型万能"的隐含假设解耦掉;(3)以Rust实现并在工程层面解决长视野会话必然遇到的三个根本难题——上下文窗口耗尽、危险操作防护、能力扩展时prompt过载。

与已有工作不同的是,和已有工作相比,OPENDEV切入了一个被忽视的维度:"Agent工程"本身的经验学。大部分agent论文聚焦算法改进(新训练方法、新推理框架),而OPENDEV关注的全是工程问题——什么时候用role:user而不是role:system注入提醒更有效、为什么9层模糊匹配比2层匹配好得多、为什么schema gating比runtime permission check更安全、为什么70-80%压缩阈值要靠经验调优而不是理论推导。它把这些"踩坑经验"系统化成本文第3节的transversal lessons,这是现有任何一篇agent论文都没做过的整合。

核心方法

OPENDEV的核心思路是"compound system + 渐进降级 + 透明可观测"——把一个看起来"很神奇"的AI编程助手,拆解成多个独立可替换的工程模块。直觉上,可以把它想象成一个"AI手术机器人":医生(LLM)负责思考,机械臂(工具系统)负责执行,监护仪(上下文工程)负责持续追踪"病人状态",麻醉师(安全层)负责防止过度操作,病历本(持久化层)负责记录全过程。整个架构分为四层:Entry&UI层把CLI/Web UI的请求归一化;Agent层跑扩展ReAct循环,五阶段压缩、thinking+critique都嵌在里面;Tool&Context层用注册中心(registry)管理35个内置工具+按需MCP发现,上下文工程把token预算当成一级公民来管理;Persistence层用文件系统(JSON+JSONL)做会话/快照/配置存储。最关键的工程创新是context engineering——它把"上下文"从"缓冲区"重定义为"预算",通过ACC五阶段压缩、role:user just-in-time提醒、ACE playbook记忆管线,把"会话长度"和"信息损失"之间的矛盾系统性地缓解。

本文最核心的创新点,不是某一个具体算法,而是三个相互支撑的架构原则:(1)Scaffolding vs Harness分离——Agent在第一次接收prompt前就完成全部构造(system prompt编译、tool schemas、subagent注册),运行时只关心dispatch和context管理,这消除了"初始化半成品"导致的race condition;(2)Schema-level Safety而非Runtime check——安全不是"运行时拦截危险操作",而是"让agent根本看不到它不能用的工具",这从结构上消灭了"模型推理绕过权限检查"的可能性,Planner子agent的schema里根本没有write工具,所以它永远不会尝试写入;(3)Progressive degradation of context——压缩不是一个二值的紧急操作,而是从70%就开始的五阶段渐进策略,优先使用便宜的剪枝/遮蔽,把昂贵的LLM摘要保留到99%才用。这三个原则一起构成了一个"用架构解决LLM固有缺陷"的设计哲学。

方法步骤详情

完整的工作流程分两大阶段。第一阶段是Scaffolding(预运行装配):AgentFactory.create_agents()严格按三阶段顺序装配——Phase 1扫描三个目录(builtin/user/project)发现Skill并注册use_skill工具;Phase 2创建SubAgentManager,register_defaults()编译8种内置子agent(Code Explorer、Planner、Web Clone、Security Reviewer等),每个子agent在构造时就通过allowed_tools参数过滤tool schema,所以"能力边界"在编译时就锁死;Phase 3才创建MainAgent(无工具过滤,全权限),此时Phase 2注册的spawn_subagent工具才能进入它的schema。装配完成后所有manager(ConfigManager、SessionManager、ModeManager、ApprovalManager)通过依赖注入(AgentDependencies Pydantic模型)传给agent.run_sync()。第二阶段是Harness Runtime(运行时框架):每一轮迭代跑Algorithm 1的六相位——Phase 0首先检测token利用率p,如果p>0.99触发完整LLM摘要,>0.85做fast pruning,>0.80做observation masking,>0.70只记录警告;Phase 1如果开启了thinking模式,调一个无工具的thinking LLM生成推理trace(HIGH档额外触发critique模型自评并refine);Phase 2调action LLM接收完整prompt(system prompt+playbook bullets+tool schemas+对话历史+thinking trace)返回响应;Phase 3分支:无tool calls则可能注入错误恢复nudge或todo完成检查,有tool calls则先做doom-loop检测(MD5指纹+20长滑动窗口,3次重复触发SYSTEM WARNING,再次重复升级到approval pause),然后并行或串行调度工具;最后汇总执行结果,Reflector每5条消息触发一次playbook反思,Curator决定add/update/tag/remove bullets,更新持久化的playbook JSON。整套流程最巧妙的是"中断可注入"——UI通过有界Queue(maxsize=10)注入消息,在每个iteration边界被drain,所以用户在agent执行中段发送的指令不会丢失。

技术新颖性

和已有agent框架相比,OPENDEV的技术新颖性主要体现在四个层面。第一个层面是"架构层面的新颖性":它把compound AI system范式落地为per-workflow LLM binding,这是SWE-Agent(单模型)、OpenHands(浏览器单前端)、Aider(无subagent架构)都没系统化做过的设计;同时它把"scaffolding"和"harness"显式分phase,通过eager construction在Agent构造时就把所有prompt/schema/manager锁死,消除了lazy init常见的race condition,这是工程上的"小创新"但对生产稳定性影响巨大。第二个层面是"上下文工程层面的新颖性":Adaptive Context Compaction把传统agent的单次紧急压缩(95-99%阈值)替换为五阶段渐进(70/80/85/90/99%),同时把observation的生命周期建模为active→faded→archived三态,这是对context rot现象[46]的系统性工程回应;Lazy MCP discovery解决了MCP协议在大规模外部工具下的context bloat问题(40%→<5%),这一技巧未来很可能成为所有MCP-based agent的标准设计。第三个层面是"安全层面的新颖性":纵深防御的五层架构中,"schema gating(让agent根本看不到禁用工具)"取代了"runtime permission check(允许但拦截)",这是从"guard rail"到"missing road"的范式转换——OpenHands和Claude Code都还在用runtime check,OPENDEV通过allowed_tools参数在schema构建时就把Planner子agent的write能力剥掉,从根本上消除了"模型推理绕过权限"的可能性。第四个层面是"工具设计层面的新颖性":9-pass模糊匹配把edit_file的最大单点故障(content not found)从40%以上错误率降到接近零;agent-aware truncation hints根据调用方能力(是否能spawn_subagent)给出针对性恢复建议;这些细节让系统对LLM的"近似正确输出"具备原生容忍能力。综合起来,OPENDEV的新颖性不在某一个具体算法突破,而在于"系统地把LLM固有缺陷(long context、instruction drift、approximate output、dangerous action)用架构约束系统化解决"。

Overview of OPENDEV. Work is organized into concurrent sessions, each composed of multiple specialized sub-agents; each agent executes typed workflows (Execution, Thinking, Compaction) that independently bind to a user-configured LLM.
Figure 1: Overview of OPENDEV. Work is organized into concurrent sessions, each composed of multiple specialized sub-agents; each agent executes typed workflows (Execution, Thinking, Compaction) that independently bind to a user-configured LLM.
System architecture of OPENDEV, organized into four layers: Entry & UI, Agent, Tool & Context, and Persistence.
Figure 2: System architecture of OPENDEV, organized into four layers: Entry & UI, Agent, Tool & Context, and Persistence.
Defense-in-depth safety architecture. Five independent layers intercept dangerous actions at progressively lower levels of abstraction.
Figure 3: Defense-in-depth safety architecture. Five independent layers intercept dangerous actions at progressively lower levels of abstraction.
Detailed view of the ReAct loop at the center of Figure 4. Each user query passes through an initialization stage that creates an IterationContext, then enters an iteration loop consisting of four phases: context management, thinking, action, and decision.
Figure 8: Detailed view of the ReAct loop at the center of Figure 4. Each user query passes through an initialization stage that creates an IterationContext, then enters an iteration loop consisting of four phases: context management, thinking, action, and decision.
Detailed view of the compaction subsystem from Figure 9. Five stages activate at progressive pressure thresholds (70%, 80%, 85%, 90%, 99%).
Figure 13: Detailed view of the compaction subsystem from Figure 9. Five stages activate at progressive pressure thresholds (70%, 80%, 85%, 90%, 99%).
Detailed view of the memory subsystem from Figure 9. Stage 1: BulletSelector scores playbook bullets; Stage 2: Reflector every 5 messages; Stage 3: Curator plans mutations; Stage 4: mutations applied to playbook.
Figure 14: Detailed view of the memory subsystem from Figure 9. Stage 1: BulletSelector scores playbook bullets; Stage 2: Reflector every 5 messages; Stage 3: Curator plans mutations; Stage 4: mutations applied to playbook.
Expanded view of the Tool layer from Figure 2. ToolSchemaBuilder assembles JSON schemas from three sources; ToolRegistry dispatches tool calls to category-based handlers.
Figure 16: Expanded view of the Tool layer from Figure 2. ToolSchemaBuilder assembles JSON schemas from three sources; ToolRegistry dispatches tool calls to category-based handlers.

实验结果

本文不是一篇benchmark-driven论文,而是一篇系统报告,所以"结果"主要是工程化指标而非排行榜分数。核心可量化的发现包括:(1)Adaptive Context Compaction(ACC)把典型session的峰值上下文消耗降低约54%,在常规30轮session中常常完全避免触发LLM摘要;(2)上下文压缩前典型session能跑15-20轮就触发overflow,加上8,000字符(~2,000 token)输出offload阈值后扩展到30-40轮;(3)单次长跑测试输出30,000 tokens经per-tool summarizer压缩后只剩不到100 tokens,某些文件读取从2,000-3,000 tokens压成"✓Read file (142 lines, 4,831 chars)"的元数据;(4)Anthropic的prompt caching在OPENDEV的stable/dynamic分割下,把cached portion的input cost降低约88%(stable部分通常占prompt总量的80-90%);(5)Lazy MCP discovery把baseline上下文占用从40%压到<5%,只有真正被搜索/调用的工具schema才会进入prompt;(6)Doom-loop检测能在3次重复调用内捕获stuck loop,而原有的"连续N次read"counter需要更多轮次且不能区分"相同工具不同参数"vs"完全相同调用";(7)9-pass模糊匹配链把edit_file的"content not found"错误率从最大单点故障源降为边缘问题,exact match短路保证零额外开销。这些数字共同说明了一个核心结论:"渐进式、分阶段、感知上下文的策略"在工程效率上明显优于"一刀切式的紧急阈值"。同时作者坦承:本文没有在SWE-bench、Terminal-Bench、LongCLI-Bench上做定量评测,这是第5节明确列出的首要未来工作。

Complete catalog of all 35 built-in tools in OPENDEV, organized by handler category (File Ops, Process, Web, Symbols, Task Mgmt, User Input, Planning, Completion, Discovery).
Table 1: Complete catalog of all 35 built-in tools in OPENDEV, organized by handler category (File Ops, Process, Web, Symbols, Task Mgmt, User Input, Planning, Completion, Discovery).
查看结构化数据
任务指标本文基线提升
典型session上下文消耗峰值 相对降幅 降低约54%(采用ACC五阶段压缩) 二值紧急压缩(95-99%阈值触发LLM摘要) 约54%降幅,且常避免紧急压缩
Prompt caching的stable portion成本节省 Input cost reduction 约88%降低cached部分输入成本 无cache时每轮重复计费的稳定prompt 约88%
MCP外部工具的baseline上下文占用 占context budget比例 <5%(lazy discovery) 高达40%(所有MCP schema全部加载) 从40%降至<5%
单次长跑测试输出的上下文占用 tokens/tool call <100 tokens(per-tool summarizer) 30,000 tokens(无压缩) >99%压缩比
典型session长度(触发context overflow前) 对话轮次 30-40轮(summarizer + offloading) 15-20轮(无任何压缩) 约2x延长
Doom-loop捕获速度 重复次数阈值 3次(MD5 fingerprint) 更多次(连续read计数器,无法区分参数) 更早捕获+更精确(区分tool+args对)

局限与改进

作者在第5节明确承认的最大局限是"缺乏系统化定量评测"——论文没有在SWE-bench、Terminal-Bench、LongCLI-Bench这些标准基准上跑出公开数字,所有指标都是作者在迭代开发过程中对内部session的工程观察。这意味着"54%上下文降幅""88%缓存节省"等数据虽然方向可信,但不能直接和Claude Code、Aider等竞品横向对比。其次,作者指出的特定边界条件包括:OFF-MODE下thinking被完全跳过,这对纯执行类任务(如大量文件读写)是合理的浪费;doom-loop检测只在action-phase生效,thinking-phase自身产生的无限推理无法被它捕获;9-pass模糊匹配虽然短链路short-circuit,但当LLM给出的old_content和实际文件差异极大(例如agent自己重构后用记忆写edit指令),仍然可能落入"fallback to error"。另外,本系统的per-workflow LLM routing虽然灵活,但其"哪个工作流该用哪个模型"的决策完全依赖用户配置,系统本身没有自动化模型选择能力——理论上讲,这是个隐形的调优负担,新手用户可能用错模型组合。我自己观察到的额外问题:role:user reminder的"更高salience"结论是基于作者自身测试,可能因模型而异(不同模型对system vs user message的处理方式不同);Stale-read的50ms tolerance在git checkout+立即edit的工作流下可能误触发(因为checkout更新mtime),可能需要改成"基于read_tool自己的timestamp而非文件系统mtime"。

独立分析的弱点

独立分析后我认为本文有四个具体弱点,每个都有可操作的改进方向。第一,**缺乏标准benchmark定量证据**——所有指标都是内部工程观察,缺乏与SWE-Agent、OpenHands、Aider等同行系统的A/B对比;改进方向是跑Terminal-Bench和LongCLI-Bench(已经在第5节被列为首要未来工作),特别关注"prompt caching + adaptive compaction组合"是否在长视野任务上显著优于vanilla ReAct。第二,**模型路由的决策负担全部甩给用户**——五个模型角色(Action/Thinking/Critique/Vision/Compact)都需要用户手动配置,这对小白用户门槛极高,且配置错误会导致系统行为不可预期;改进方向是引入"模型能力画像+任务复杂度估计器",自动建议配置(例如"你这个任务的thinking建议用opus,compact用haiku"),这其实就是Ye et al.的MCE工作的简化版。第三,**ACE playbook目前是扁平的自然语言bullet列表**,语义检索依赖cosine相似度,无法捕捉bullet之间的依赖/冲突/层次关系;改进方向是采用structured memory(代码依赖图、call graph、project ontology)替代部分纯文本bullet,这正是作者在第5节提出的"Structured code representations for memory"方向。第四,**安全层的approval persistence是双刃剑**——持久化在~/.opendev/permissions.json的规则很方便,但项目级与用户级规则的merge逻辑仅是"project优先级更高",这可能让恶意项目文件覆盖用户的安全边界;改进方向是引入rule的"上下文敏感性"——比如.gitignore级别的override需要显式confirm,或者某些dangerous rules(rm -rf)永远不能被任何配置文件降低安全级别,虽然现在priority=100的danger rule不会被override,但其他类型的规则还是可以被攻击。

未来方向

作者在第5节明确列出了七个未来方向:(1)在SWE-bench、Terminal-Bench、LongCLI-Bench上做系统评测(Terminal-Bench显示前沿模型<65%,LongCLI-Bench<20%,说明行业有巨大改进空间);(2)**自适应资源分配**——把当前固定的70%压缩阈值、3次nudge budget、4档thinking level,改成基于任务复杂度、当前context pressure、错误历史动态调整,这正是"用learning替代hand-engineering"的典型方向;(3)**ACE playbook的跨项目迁移**——目前playbook按项目分,未来要做hierarchical bullet organization(通用编程启发式 vs 项目特定约定)以及active learning(对不确定bullet选择性询问用户反馈);(4)**结构化代码表征**替代扁平bullet(code dependency graphs、call graphs、project-level ontologies);(5)**多agent协调超越层次委派**——目前subagent只通过completion marker通信,未来要支持peer-to-peer、共享blackboard、冲突解决协议,以实现"并行code review + 并行implementation"这类复杂workflow;(6)**学习式system reminder优化**——目前24个reminder模板是手工设计的,未来用RL基于attention-decay指标自动发现effective reminder模式;(7)**Hybrid CLI+IDE integration**——把CLI agent逻辑通过同一UICallback抽象扩展到IDE插件,复用agent logic但提供visual affordances(inline diff、symbol navigation、test result overlay)。我个人延伸的额外方向:**形式化验证safety layer的独立性**——目前五层安全是"独立设计",但缺乏formal proof,可以用model checking证明任意单层失效时剩余层仍能阻止典型攻击;**prompt injection attack的防御**——论文没有讨论MCP工具返回的内容里嵌入恶意prompt的风险,这种"tool-side prompt injection"是agent安全的新前沿。

复现评估

复现评估非常友好。代码完全开源在https://github.com/opendev-to/opendev,作者是Nghi D. Q. Bui(单人项目),代码用Rust实现,意味着编译产物轻量、运行效率高、跨平台部署容易。复现难度主要不在代码层面而在**配置层面**——要完整复现OPENDEV的context engineering行为,需要配置至少3-5个不同LLM的角色(Action+Thinking+Compact至少三个),推荐组合是Anthropic Claude Opus(thinking) + Sonnet(action) + Haiku(compact),这意味着用户需要Anthropic API key以及相应的token预算。算力门槛几乎为零——OPENDEV是client-side,不自己训练模型,所有"AI能力"通过API调用获得,普通开发笔记本即可运行。数据方面,系统启动会从远程catalog API拉取模型能力元数据(可通过OPENDEV_DISABLE_REMOTE_MODELS环境变量离线),并通过OPENDEV_MODELS_DEV_PATH指向本地catalog,air-gapped环境也能跑。最大的复现障碍其实是**评估困难**——因为没有benchmark评测,无法用单一数字判断"我的复现版本是否和论文描述一致",需要逐项跑"30轮session能否达到54%上下文降幅"等内部指标,这要求复现者理解并实现所有ACC的触发逻辑。整体复现难度:**代码层容易(开源+Rust生态成熟),配置层中等(多模型角色设置),评估层困难(缺乏benchmark锚点)**。