深入脚手架内部:编码智能体架构的源代码级分类法
原文:Inside the Scaffold: A Source-Code Taxonomy of Coding Agent Architectures 作者:Benjamin Rombaut (Centre for Software Excellence, Huawei Canada) 日期:2026-04-04 翻译方式:baoyu-translate skill (refined mode)
Benjamin Rombaut 华为加拿大软件卓越中心
摘要
基于 LLM 的编码智能体能够定位缺陷、生成补丁并运行测试,且对人工监督的依赖日益减少,然而包裹在语言模型外部的脚手架 (Scaffold) 代码——控制循环、工具定义、状态管理和上下文策略——仍然缺乏充分的理解。现有综述按照抽象能力类别(工具使用、规划、反思)对智能体进行分类,这种方式无法区分架构上截然不同的系统;而轨迹研究观察的是智能体做了什么,却未检视决定其行为原因的脚手架代码。本文提出了一套源代码级别的架构分类法,该分类法来源于对 13 个开源编码智能体脚手架在固定提交哈希处的分析。每个智能体在 12 个维度上进行表征,这些维度组织为三个层次:控制架构、工具与环境接口以及资源管理。分析表明,脚手架架构难以用离散类别加以划分:控制策略的分布范围从固定流水线到蒙特卡洛树搜索 (Monte Carlo Tree Search, MCTS),工具数量从 0 到 37 不等,上下文压缩涵盖七种不同的策略。五种循环原语(ReAct、生成-测试-修复、计划-执行、多次重试、树搜索)作为可组合的构建块,被智能体以不同方式分层组合;13 个智能体中有 11 个组合了多种原语,而非依赖单一控制结构。各维度在外部约束占主导的地方趋于收敛(工具能力类别、编辑格式、执行隔离),在开放性设计问题尚存的地方趋于发散(上下文压缩、状态管理、多模型路由)。所有分类法层面的论断均以文件路径和行号为依据,为研究智能体行为的研究者和设计新脚手架的实践者提供了可复用的参考。
1 引言
大语言模型已经深刻改变了软件工程实践。Aider 1、SWE-agent 2 和 OpenHands 3 等工具能够浏览陌生的代码仓库、定位缺陷、生成补丁并运行测试套件,且对人工监督的依赖日益减少。其中最强大的系统在 SWE-bench Verified 基准测试 4 上能够解决超过半数的真实 GitHub 问题,本研究分析的智能体中有七个各自积累了超过 15,000 个 GitHub star 5(Table 1),表明其已被相当规模的开发者社区所采用。随着这些智能体从研究原型走向生产工具,包裹在语言模型外部的脚手架代码——控制循环、工具定义、状态管理和上下文策略——越来越多地决定着智能体的行为方式、所犯的错误类型以及 Token 预算的分配 6。
尽管脚手架具有如此重要的实践意义,编码智能体脚手架的内部架构在研究文献中仍然缺乏充分的理解。现有的 LLM 智能体综述在概念层面运作,按照抽象能力(工具使用、记忆、规划、反思)而非区分不同生产系统的具体实现策略来组织系统 7 8。一个使用蒙特卡洛树搜索来探索候选补丁的编码智能体与一个使用简单 while 循环配合测试驱动重试的编码智能体,在这些分类法下都属于”使用工具、具备规划、可反思”的智能体,然而它们的脚手架架构在影响成本、可靠性和失败模式的根本层面上存在差异。关于编码智能体的实证研究已开始通过轨迹分析来表征其运行时行为 9 10,揭示出成功的智能体比失败的智能体更快地定位缺陷、更早地进行测试、产生更短的动作序列。然而,这些研究将智能体视为黑箱:它们观察智能体做了什么,但并未检视决定其行为原因的脚手架代码。已有研究者呼吁建立架构感知的评估指标,将内部组件与可观察的结果关联起来 11,针对单个系统的详细架构描述也已存在 6,但据目前的文献检索所知,尚无研究在源代码层面系统性地比较过生产级编码智能体的脚手架架构。
这一空白的重要性体现在三个方面。第一,缺乏脚手架设计的共享词汇表,研究智能体行为的学者无法将观察到的差异归因于具体的架构选择;脚手架设计与模型能力之间的混淆因素未被认识到。此前的轨迹研究为不同的智能体使用了不同的 LLM 9,导致无法判断行为差异究竟源于脚手架还是模型。第二,构建新编码智能体的实践者缺乏设计空间的系统性地图。架构决策——是使用持久化事件存储还是扁平消息列表,是为 LLM 提供十个专用工具还是一条 shell 命令,是通过摘要还是截断来压缩上下文——目前只能依赖阅读单个代码库或博客文章来做出,没有可供比较的参考资源(Section 2)。第三,快速的发展意味着设计空间的扩展速度超过了其被文档化的速度:本研究分析的 13 个智能体的发布时间跨越 2023 年 6 月至 2025 年 3 月,代表了不同的架构策略(固定流水线、顺序 ReAct 循环、分阶段工作流、深度优先树搜索以及完整的 MCTS),但此前没有任何研究对它们之间的关系进行过梳理。
本文提出了一套针对 13 个开源编码智能体脚手架的源代码级架构分类法。每个智能体的实现在固定的提交哈希处,沿 12 个维度进行分析,这些维度组织为三个层次:控制架构(智能体如何决定下一步做什么)、工具与环境接口(智能体如何与代码和执行环境交互)以及资源管理(智能体如何管理上下文、状态和模型)(Section 3.2)。分析遵循定性案例研究方法论,每一项分类法论断均以克隆仓库中的文件路径和行号为依据。
该分类法揭示了若干挑战编码智能体设计常见假设的发现。智能体并非落入离散的架构类别中,而是占据连续频谱上的不同位置:控制策略的分布范围从没有反馈循环的固定流水线(Agentless 12)到具有奖励反向传播的完整蒙特卡洛树搜索(Moatless Tools 13),其中 13 个智能体中有 7 个使用顺序 ReAct 循环作为其主要控制结构。循环原语(ReAct、生成-测试-修复、计划-执行、多次重试)作为可组合的构建块,被智能体以不同方式分层组合,而非作为互斥的类型。工具集的规模从零个 LLM 可调用工具(Aider,由用户驱动所有导航)到 37 个动作类(Moatless Tools)不等,但底层的能力类别趋于收敛:读取、搜索、编辑和执行代码的功能出现在每一个赋予 LLM 自主权的智能体中。上下文压缩、状态管理和多模型路由各自呈现出类似的频谱,设计选择在一端侧重简洁性,在另一端侧重鲁棒性或搜索广度。五个跨维度主题——包括采样与迭代之间的权衡、子智能体委托作为一等工具的涌现以及 IDE 耦合的架构影响——跨越多个维度,捕捉了无法归结为单一轴线的模式。
本文的贡献如下:
- 一套编码智能体脚手架架构的分类法,源自对 13 个开源智能体的源代码分析,组织为三个层次和 12 个维度。据目前的文献检索所知,这是首个在实现层面对编码智能体进行比较的架构研究。
- 一项实证发现:脚手架架构更适合被表征为沿连续频谱排列的循环原语组合,而非离散架构类型的实例。
- 一份锚定到具体提交的架构观察详细证据库,为研究智能体行为的研究者和设计新脚手架的实践者提供了可复用的参考。
本文其余部分的结构如下。Section 2 综述了智能体架构、轨迹分析和编码智能体评估方面的相关工作。Section 3 描述了智能体选择标准、分析维度和编码流程。Section 4 从三个层次呈现分类法,包含证据表和跨维度主题。Section 5 解读研究发现并引申出对智能体设计和评估的启示。Section 6 讨论效度威胁。Section 7 以总结和未来工作方向作结。
2 相关工作
本研究位于多条研究脉络的交汇处。以下各小节依次讨论每条脉络:LLM 智能体的概念性分类法(Section 2.1)、编码智能体行为的实证研究(Section 2.2)、单个系统的架构描述(Section 2.3)以及基准测试驱动的评估(Section 2.4)。每条脉络从不同的视角审视编码智能体,但没有任何一条在源代码层面对其脚手架架构进行了比较性考察。
2.1 LLM 智能体架构综述
一批日益增长的综述工作按照抽象能力来组织基于 LLM 的智能体。7 提出了一个五组件参考模型(推理、规划、工具使用、记忆、反思),并对单智能体和多智能体设计中的交互模式进行了分类。8 提出了一种基于能力的分类法(使用工具、记忆增强、规划、多智能体、具身),立足于经典智能体理论,认为可靠性是一种架构属性而非仅仅是模型质量的函数。这一论断与本研究的前提相呼应;本文所提供的源代码分析为 Nowaczyk 等人概念性论证所隐含但未提供的内容补充了实现层面的证据,将架构与可靠性之间的关系扎根于具体的脚手架设计选择而非抽象的能力类别中。更广泛的 LLM 软件工程应用综述将编码智能体作为诸多类别之一加以涵盖 14。这些分类法提供了有用的概念词汇,但它们所运作的抽象层次无法区分不同的生产级编码智能体。本研究语料库中的每一个智能体在这些方案下都符合”使用工具、记忆增强、具备规划”的分类,然而它们的脚手架架构在影响成本、可靠性和失败模式的层面上存在差异。一个使用蒙特卡洛树搜索来探索候选补丁的编码智能体与一个使用简单 while 循环配合测试驱动重试的编码智能体,在基于能力的分类下无法区分,尽管二者在控制流、状态管理和资源消耗方面存在根本性差异。一条相关的研究线索考察 LLM 如何在模型层面学习使用工具(工具调用训练、函数调用微调)15 16;这与本研究所探讨的问题互补,因为本研究考察的是脚手架代码如何暴露和编排工具,而非模型如何学习调用工具。
许多概念类别所依赖的提示范式已被独立形式化。17 提出了 ReAct 范式,其中 LLM 在思考-动作-观察循环中交替生成推理轨迹和任务特定的动作;本研究中 13 个智能体中有 7 个使用顺序 ReAct 循环作为主要控制结构(Table 2),还有若干智能体在更大工作流的各阶段中嵌入了类 ReAct 的迭代。18 形式化了 Reflexion,一种言语强化学习框架,其中智能体对失败的尝试进行反思并将反思结果存储在情景记忆缓冲区中以供后续重试;这一模式是本语料库中观察到的生成-测试-修复循环原语的基础(Section 4.1.1)。然而,ReAct 和 Reflexion 描述的都是算法范式,而非脚手架架构。从”交替思考与动作”到一个包含工具注册、上下文压缩、多模型路由和持久化状态的生产实现之间的鸿沟,正是本研究所记录的内容。
2.2 编码智能体轨迹与行为研究
一条互补的研究线索通过分析编码智能体在运行时的执行轨迹来研究其行为。10 收集了五个智能体在 SWE-bench Verified 上运行的完整执行轨迹,将其归一化为统一的动作模式,并提取出”决策路径”分类法:反复出现的行为模式,如探索优先、补丁优先和测试驱动策略。他们发现缺陷定位是主要瓶颈,早期测试生成与成功率存在强相关性。9 分析了 OpenHands、SWE-agent 和 Prometheus 19 的轨迹日志,报告了失败轨迹比成功轨迹长 12–82%,且代码仓库导航在智能体活动中的占比超过补丁编写。20 研究了三个智能体(RepairAgent 21、AutoCodeRover、OpenHands)的思考-动作-结果轨迹,发现即便罕见的思考-动作错位(占步骤的 0.5–4.8%)也与失败强相关,且失败轨迹表现出重复的、非适应性的动作循环。
这些研究建立了重要的实证规律,但存在两个局限性,本研究对此进行了回应。第一,这些研究将智能体视为黑箱:它们观察智能体做了什么,但无法解释为什么。诸如”轨迹较短的智能体更频繁地成功”这样的发现无法区分以下情形:一个脚手架强制提前终止,一个实现了高效的搜索启发式方法,还是一个仅仅设置了较低的迭代预算。第二,此前的轨迹研究为不同的智能体使用了不同的 LLM 9 20,将脚手架效应与模型效应混淆在一起;例如,Majgaonkar 等人将基于 Claude 3.5 Sonnet 的 OpenHands 轨迹与基于 DeepSeek-V3 的 Prometheus 轨迹进行比较,导致无法判断行为差异究竟源于脚手架还是模型。本文提出的架构分类法提供了缺失的解释层:通过检视产生那些轨迹的脚手架源代码,可以将行为差异归因于具体的设计选择,而非不透明的系统级差异。
22 从行为分析转向资源导向的分析,测量了五个脚手架在三个 LLM 上的 Token 消耗、成本和计算时间。他们发现的”Token 雪球效应”(由于朴素的对话历史累积,输入 Token 随 API 调用线性增长)和”昂贵的失败”(失败尝试消耗的资源高达成功尝试的 4 ×)是实证现象,本研究可以从架构层面加以解释:Token 雪球效应对应上下文压缩维度(Section 4.3.2),昂贵的失败则与错误恢复和终止策略相关。然而,SWE-Effi 并未检视产生这些成本模式的脚手架代码;其唯一的架构区分是”智能体式”与”程序式”。
2.3 单个系统描述
若干编码智能体已有详细的架构描述,这些描述综合表明脚手架设计选择显著影响智能体行为。一些论文聚焦于工具与环境接口如何塑造智能体能力:2 为 SWE-agent 引入了智能体-计算机接口(ACI)概念,表明设计定制的 shell 命令来组织代码仓库交互本身就是一项影响下游性能的架构决策;1 描述了 Aider 中通过 PageRank 进行的代码仓库映射以及针对特定模型的编辑格式选择;6 描述了一种四层终端智能体架构,包含双智能体设计、多模型路由、延迟工具发现和自适应上下文压缩,并得出结论”工具可靠性比模型能力更重要”。
其他系统论文揭示了智能体自主性的频谱。在一端,12 认为对于许多任务而言,智能体式的脚手架并非必要,证明了由定位、修复和重排序阶段组成的固定流水线可以在 SWE-bench 上与智能体方法持平甚至超越后者;这为本分类法中的流水线到智能体频谱提供了动机。在另一端,23 在 DARS-Agent 中提出了带有基于 LLM 的分支选择的树结构搜索,24 在 MASAI 中将智能体分解为针对不同子任务的专用子智能体。在这两个极端之间,25 描述了 AutoCodeRover 中基于抽象语法树 (AST) 的上下文检索配合基于频谱的故障定位 (SBFL),3 描述了 OpenHands 底层的事件溯源架构和智能体委托机制。这些论文各自为单个系统提供了架构深度,但设计空间整体仍未被梳理:实践者若不独立阅读十余个代码库,便无法比较控制循环策略、工具接口设计或上下文管理方法。本研究将这种针对单个系统的深度分析扩展到 13 个智能体,实现了单独描述所无法提供的比较分析。
一条相关但正交的研究线索考察开发者如何配置编码智能体。26 分析了 2,926 个 GitHub 仓库以表征五种商业编码工具的配置制品(指令文件、提示模板、Skills 定义、结构化配置),发现配置实践仍然碎片化,Skills 和子智能体配置等高级功能鲜有使用。该工作与本研究互补:配置制品控制智能体接收到的指令,而脚手架架构决定智能体如何处理这些指令。一个指定”提交前务必运行测试”的 CLAUDE.md 文件是面向开发者的配置;实现该指令的脚手架生成-测试-修复循环则是架构特征。本研究分析的是后者。
2.4 编码智能体评估与基准测试
SWE-bench 4 已成为编码智能体事实上的评估标准,推动了快速进展并驱动了本研究语料库中许多智能体的设计。然而,其局限性已被越来越多地记录在案:过于详细的问题描述抬高了解决率 27,单一语言偏差限制了泛化能力 4 28,脚手架与模型效应的混淆使得将性能归因于架构选择变得困难 22。较新的基准测试部分解决了这些问题:SWE-bench Pro 29 引入了更难的多文件任务并具有抗污染能力,SWE-Compass 28 将评估扩展到八种编程语言和多种任务类型。30 在最小脚手架下检验了智能体生成的测试是否能提升解决率,发现增加或移除测试的提示干预最多改变 2.6 个百分点的结果;这表明脚手架层面的测试编排(lint-测试循环、测试门控重试、MCTS 奖励信号)——而非模型原生的测试编写行为——可能才是架构层面的相关变量。
本研究刻意不进行智能体性能的基准测试,因为基准测试分数混淆了脚手架架构与模型能力、提示工程以及偶然的配置选择(迭代次数限制、成本上限、默认模型选择);隔离脚手架的贡献需要的是本文所呈现的这种架构分析,而非额外的基准测试运行。然而,该分类法确实为未来的受控实验提供了条件,通过识别需要保持恒定的具体变量:例如,比较拥有相同工具集但使用不同循环策略的智能体,或相同循环但不同压缩策略的智能体,同时保持模型一致(Section 5.5)。
11 明确呼吁建立架构感知的评估指标,将智能体内部组件(规划器、记忆、工具路由器)与可观察结果关联起来,并提出了一个组件到指标的映射框架。然而,他们的提议是概念性的:尚未在真实系统上进行验证,且依赖于在本研究之前大多数编码智能体所不具备的架构文档。本分类法提供了此类评估框架所需要的架构词汇。
3 研究方法
本研究对开源编码智能体脚手架进行源代码级别的架构分析,从观察到的实现模式而非文档声明或概念模型中推导出分类类别。
3.1 智能体选取
候选智能体通过三个渠道识别:截至 2026 年初在 SWE-bench 排行榜文献中被评估和报告的智能体、在开发者工具中具有显著采用率的智能体(以 GitHub star 数作为社区使用的代理指标 5)以及在近期 LLM 软件工程综述中被引用的智能体 14。检索在任何单一渠道内都并非穷尽性的;候选池反映的是研究者通过这些来源所接触到的智能体,而非满足某一固定阈值的所有智能体的完整枚举。一个包含 22 个候选的初始池依据三项纳入标准进行筛选(完整的候选列表及每个排除理由见 Appendix A):
- 编码专用。智能体必须是为软件工程任务(代码编辑、缺陷修复、代码仓库导航)而设计的,而非通用任务自动化工具。这排除了通用框架(Open Interpreter 31、Deep Agents 32)和多智能体编排平台(MetaGPT 33、CrewAI 34),后者的分析单元是智能体间的协调而非单个智能体的架构。
- 开源且实现可读。智能体的脚手架代码(控制循环、工具定义、状态管理)必须以可读源代码的形式存在于公开仓库中,并固定到特定的提交。这排除了 Claude Code 35(以编译后的二进制文件分发,无公开源代码仓库)和 MASAI 24 1。脚手架代码不可检视的专有智能体(GitHub Copilot Workspace、Cursor 的 AI 后端、Windsurf)也据此被排除。
- 架构上有区分度。近似重复的智能体被移除以避免冗余分析(例如,共享同一核心代码库或仅在前端集成上有差异的智能体)。
保留用于分析的 13 个智能体列于 Table 1。它们跨越两个自然的来源类别:为交互式开发者使用而构建的 CLI 智能体和主要为自动化问题解决而构建的 SWE-bench 智能体。另有一个智能体 mini-swe-agent 36 作为刻意设定的最小基线纳入:它由 SWE-agent 2 团队发布,作为展示最简可能完整脚手架的参考实现。该选取并非穷尽性的,但旨在覆盖截至 2026 年初开源编码智能体生态系统中所呈现的架构策略范围。
Table 1:所分析的智能体,按 GitHub star 数排序作为社区采用的代理指标 5。“类别”区分了交互式 CLI 工具和为自动化 SWE-bench 评估而设计的智能体。所有智能体均在固定的提交哈希处进行分析(见 Appendix B)。
| 智能体 | 类别 | 语言 | Star 数 | 来源 |
|---|---|---|---|---|
| OpenCode 37 | CLI | TypeScript | 135k | SST |
| Gemini CLI 38 | CLI | TypeScript | 100k | |
| Codex CLI 39 | CLI | Rust / TS | 72k | OpenAI |
| OpenHands 3 | SWE-bench | Python | 70k | All Hands AI |
| Cline 40 | CLI | TypeScript | 60k | Independent |
| Aider 1 | CLI | Python | 43k | Independent |
| SWE-agent 2 | SWE-bench | Python | 19k | Princeton / CMU |
| mini-swe-agent 36 | 基线 | Python | 4k | Princeton / CMU |
| AutoCodeRover 25 | SWE-bench | Python | 3k | NUS / SonarSource |
| Agentless 12 | SWE-bench | Python | 2k | UIUC |
| Prometheus 19 | SWE-bench | Python | 1k | EuniAI |
| Moatless Tools 13 | SWE-bench | Python | 600 | Independent |
| DARS-Agent 23 | SWE-bench | Python | 70 | Independent |
3.2 分析维度
分析框架包含九个维度(在结果中产生 12 个分类法维度,如下所述)。这些维度并非先验固定的,而是在对两个架构差异显著的智能体——Aider(一个较简单的交互式 CLI 脚手架)和 OpenHands(一个复杂的事件驱动容器化脚手架)——进行试点分析的过程中,通过迭代的开放编码 41 逐步形成的。选择这两个智能体是为了在试点阶段最大化架构多样性;具体的选择理由和改进细节见 Section 3.4。
初始试点从概念性智能体架构文献 7 中提取了六个候选维度:控制循环、工具接口、状态管理、上下文检索、执行隔离和多模型路由。在试点过程中,由于源代码揭示了初始维度集未能捕捉的架构变异,新增了三个维度:工具发现策略(源于 Aider 和 OpenHands 注册工具方式的差异)、上下文压缩(源于 Aider 的显式摘要逻辑与 OpenHands 缺乏此逻辑之间的对比)以及持久化记忆(源于 Aider 的约定文件)。稳定化过程包括将修订后的九维度框架再次应用于两个试点智能体,以确认每个维度在两个智能体间均能产生有区分力的发现,且没有源代码观察结果落在框架之外而未被开放式部分捕获。在此过程中没有移除任何维度。若干最终维度与此前编码智能体的单系统分析 6 和概念性智能体架构综述 7 中独立识别的架构关注点相一致,为其相关性提供了外部支持。每个维度捕捉脚手架中一个独立的架构决策点。
- 控制循环类型。智能体主执行循环的结构:它如何编排 LLM 调用、工具分发和观察处理。一个子属性——循环驱动者——记录循环是由用户发起还是由 LLM 驱动,这一区分是在试点过程中添加的,因为观察到它决定了若干下游架构决策(Section 4.1.2)。
- 工具集与工具接口设计。模型可用的完整工具集,包括工具如何被定义并传达给 LLM(例如,通过函数调用的 JSON schema、内联系统提示描述或自定义文本格式)。该维度还记录智能体在提出文件修改时使用的编辑与补丁格式。
- 工具发现策略。完整的工具集是在启动时注册(静态)还是根据任务状态在运行时有条件地加载、动态注册或组装(动态)。
- 状态管理策略。智能体如何在循环迭代间累积和表示历史:数据结构(扁平消息列表、类型化事件日志、树)、状态是只追加的还是可变的,以及除原始消息之外还存储了什么。
- 上下文检索范式。智能体在任务执行之前或期间识别相关源代码的机制:LLM 导向的工具调用(grep、find、AST 查询)、预计算的代码仓库索引、基于嵌入的语义搜索,或者包含在初始提示中的静态代码仓库映射。
- 执行隔离模型。智能体在何处运行 shell 命令和代码:在宿主文件系统上、在 Docker 容器中、在沙箱化的子进程中,还是在远程云环境中。这记录了智能体与宿主系统之间的信任边界。
- 上下文压缩方法。当对话历史接近模型上下文窗口上限时所采用的策略:硬截断、滑动窗口、LLM 生成的摘要、选择性丢弃工具结果,或者没有任何机制。
- 多模型路由。是由单个模型处理所有智能体步骤,还是将不同模型分配给不同角色(例如,大模型用于规划,小模型用于定位),以及路由决策如何做出。
- 持久化记忆。是否有任何信息在会话间留存:项目约定、之前的任务结果、用户偏好或代码仓库事实,以及所使用的存储机制。
分析模板还包括一个开放式的第十部分,用于记录不符合九个维度中任何一个的观察。这遵循了定性编码的标准做法,其中在预定义类别之外预期会出现涌现类别 42:强制将每个发现归入预定义类别可能会抑制新模式的发现。在实践中,该部分捕获了 47 项跨维度发现(在逐个智能体的分析文档中逐一列举),这些发现为 Section 4 中呈现的分类法结构提供了信息。
九个分析维度在结果中映射为 12 个分类法维度。在分析过程中,两个子属性证明具有足够的区分力而值得独立处理:循环驱动者(控制循环类型的子属性)和编辑与补丁格式(工具集设计的子属性)各自产生了独立的频谱和证据表,在 Section 4 中作为独立维度呈现。第三个维度——控制流实现(实现控制循环的代码层面机制:while 循环、递归、编译图或基于异常的信号传递)——在分析过程中涌现,作为与循环拓扑正交的一个变异轴,同样独立呈现。从分析框架到分类法结构的这种扩展是定性编码的正常结果:框架指导数据收集,但最终的类别反映数据所揭示的内容 42。
3.3 工具计数方法
工具计数采用两种互补方法进行报告,以避免将接口粒度与功能覆盖混为一谈。
注册计数按照 LLM 所见的方式统计工具:每个单独注册的可调用单元(函数调用 schema 条目、系统提示中定义的命令或等效物)计为一次。该度量受脚手架开发者如何划分功能的影响。
能力类别计数按照工具的功能进行分组:读取、搜索、编辑、执行、验证和代码仓库状态。这些类别通过试点分析归纳得出:在编目前两个智能体的所有工具之后,将反复出现的功能角色归入若干类别,然后在其余十一个智能体上进行验证。该度量可在不同智能体间进行比较,不受粒度选择的影响。一个拥有单一 bash 工具的智能体与一个拥有独立的 run_command、run_tests 和 run_linter 工具的智能体都覆盖了执行类别。两种计数均在结果中报告;能力类别计数用于跨智能体比较。
3.4 分析流程
每个智能体使用一个结构化模板进行分析,该模板源自 Section 3.2 中建立的九个维度,并在全部 13 个智能体中一致应用。该模板区分三个描述层次,遵循实证论断应可追溯到原始数据源而非从二手文档推断的原则 43:
- 观察:代码做了什么,以数据流和控制流的方式描述,附有具体的文件和行号引用。
- 分类:观察到的行为如何映射到分类法维度,附有明确的映射理由。
- 证据:锚定到所分析特定提交哈希的文件路径和行号。
对于每个智能体,该模板生成一份结构化文档,涵盖全部九个维度加上开放式部分,并以主控制循环的完整调用链追踪作为入口点。该模板在与维度开发相同的两个智能体(Section 3.2)上进行了试点:Aider 和 OpenHands。此次试点与维度稳定化的目的不同;它测试的是三层观察格式是否能产生一致且足够详细的分析文档。试点还暴露了对双重工具计数方法(Section 3.3)的需求——在观察到原始工具计数在接口粒度不同的智能体间不具可比性之后。全部 13 个智能体的完整分析文档均遵循该模板;各分析文档的相关章节在结果中被引用,作为特定论断的主要证据。
所有分析均固定到特定的 git 提交哈希,列于 Appendix B,因为若干被研究的智能体(Cline、Aider、OpenHands、Gemini CLI)在分析期间处于活跃开发状态,未固定的分析将产生不可复现的结果。当源代码存在歧义时,分析明确记录不确定性而非赋予一个高置信度的分类。对于某些智能体确实不适用的维度(例如,没有跨会话存储的智能体的持久化记忆)记录为”不存在”而非省略。所有分析由作者独立完成,并大量使用了基于 LLM 的编码助手进行代码导航、调用链追踪和陌生代码库的初步总结。所有 LLM 生成的观察结果在纳入分析文档之前均已与源代码进行了核实;分析文档本身记录了文件路径和行号以便于独立验证。单作者设计是对构造效度的一个威胁;缓解措施在 Section 6 中讨论。
3.5 范围与局限性
本研究纯粹是分类性的。未进行性能基准测试,也未就脚手架设计与任务成功率之间的相关性提出任何主张。排除性能分析的决定反映了可用数据的两个局限性:第一,跨智能体的 SWE-bench 结果无法直接比较,因为不同的智能体使用了不同的底层模型,而模型能力是比脚手架设计更大的混淆因素;第二,SWE-bench 问题描述中已有文献记录的解决方案泄露 27 使得原始通过率无论如何都不是可靠的信号。语料库仅限于具有可读源代码的开源智能体;由此产生的威胁在 Section 6 中讨论。
4 结果
对 13 个开源编码智能体脚手架的分析揭示了一套由三个层次组织的分类法:控制架构(智能体如何决定下一步做什么)、工具与环境接口(智能体如何与代码和执行环境交互)、以及资源管理(智能体如何管理上下文、状态和模型)。在每个层次内,架构选择沿连续梯度分布,而非落入离散类别。本节将每个维度呈现为一系列观察到的策略范围,将智能体放置在相应位置上并附以源代码证据,同时识别跨维度的共性模式。Figure 1 提供了完整分类法结构的概览。

Figure 1:分类法概览:12 个维度组织为三个架构层次。每个维度是一个连续频谱,其端点来自 13 个智能体语料库的观察结果。智能体沿这些频谱分布,而非落入离散类别(Section 5.1)。
4.1 第一层:控制架构
控制层决定了智能体如何编排其行动。三个维度捕捉了关键差异:(1) 控制循环的拓扑结构,(2) 驱动循环的主体,(3) 控制循环在代码中的实现方式。
4.1.1 控制循环策略
控制循环的范围从无反馈的固定流水线到具有反向传播的树结构搜索(Table 2),且这些循环类型并非互斥;智能体经常将一种循环类型嵌套在另一种内部。这种可组合性意味着表中低估了实际的控制复杂度:被归类为”分阶段循环”的智能体可能在每个阶段内包含一个完整的 ReAct 循环。例如,AutoCodeRover 在其流水线的每个阶段内运行多轮 LLM 交互(agent_search.py:88—163):一个生成器函数将工具选择结果 yield 给调用方,调用方执行这些操作并将结果返回,这使得它在不同抽象层次上既是分阶段智能体又是迭代式智能体。Moatless Tools 在可组合性方面更进一步,将内部智能体与外部控制流完全解耦:其 ActionAgent(一个单步执行器:一次 LLM 调用生成动作,然后执行)既可以由 AgenticLoop(反复调用它以产生 ReAct 行为)驱动,也可以由 SearchTree 驱动进行基于蒙特卡洛树搜索 (Monte Carlo Tree Search, MCTS) 的探索,且无需修改智能体代码本身。这种分离意味着顺序探索与树搜索探索之间的选择是一个配置决策,而非架构决策。
Table 2:控制循环策略。智能体按探索策略的灵活性从低到高排列。
| 位置 | 智能体 | 机制 |
|---|---|---|
| 固定流水线 | Agentless | 由 10 个独立脚本组成的流水线,通过磁盘上的 JSONL 文件连接。阶段之间无反馈循环。 |
| 用户驱动循环 | Aider | 外部循环由用户发起(每个编辑周期需要用户输入)。内部的生成-测试-修复循环在最多 max_reflections 次迭代内自主运行。 |
| 顺序 ReAct 循环 | SWE-agent, OpenHands, Codex CLI, Gemini CLI, mini-swe-agent, Cline, OpenCode | 标准的思考-工具-观察循环。LLM 选择下一个动作;循环在完成信号或预算耗尽时终止。 |
| 分阶段循环 | AutoCodeRover, Prometheus | 44 |
| 深度优先树搜索 | DARS-Agent | ReAct 步骤构成搜索树中的节点。在分支点,环境被重置并从根节点重放;一个 LLM 评论者在采样的备选方案中进行选择。 |
| 完整 MCTS | Moatless Tools | 选择-扩展-模拟-反向传播,具有奖励值(-100 到 +100)和访问计数。可插拔的选择器接口;一个判别器从已完成的轨迹中选择最优者。 |
树搜索策略。
三个智能体跨越了从扁平采样到启发式搜索的梯度,展示了探索可能解空间的方法如何逐步精细化。
在最简单的一端,Agentless 使用独立采样:在定位到相关代码后,它提示 LLM 独立生成候选补丁(默认配置生成 20 个;原始论文使用 4 个定位样本 × 每个 10 个补丁,共计 ≈$ 40 个)。每次生成看到相同的上下文,但可能产生不同的修复方案。然后通过对这些候选方案进行多数投票来选择最终补丁。不存在树结构,候选方案之间也没有交互;每个补丁都是独立生成的。
DARS-Agent 在其主执行循环中引入了树结构搜索。与 Agentless 将定位和修复分为不同阶段不同,DARS-Agent 没有阶段分离:搜索命令与编辑和执行命令在整个过程中并行可用。该智能体构建一棵搜索树,其中每个节点代表一个动作(如编辑文件、创建文件或提交补丁)。在每个分支点,智能体生成多个备选动作,然后使用一个 LLM 评论者在其中进行选择:评论者接收这些备选方案作为提示,并以 <best_action_index> 标签响应以指示其选择。然而,与经典树搜索不同,DARS-Agent 没有数值奖励信号,也没有将结果反向传播到较早节点;评论者做出贪心的局部决策,不考虑较早的选择如何影响了后续结果。
Moatless Tools 实现了完整的蒙特卡洛树搜索 (MCTS) 45,这与 AlphaGo 46 等博弈系统使用的算法相同。搜索树中的每个节点接收数值奖励值(范围从 -100 到 +100),算法维护访问计数以平衡对未尝试路径的探索与对有前景路径的利用。在扩展节点后,奖励沿树反向传播以更新祖先节点,使搜索能够从后续结果中学习,并将精力重新导向更有前景的分支(search_tree.py:326—345)。
从扁平采样到完整 MCTS 的演进揭示了一个设计权衡:更丰富的搜索策略需要一种跨分支管理执行状态的机制。Moatless Tools 通过影子模式执行来解决这一问题,即在内存中跟踪文件修改而非写入磁盘;这使得搜索可以在任意点分支,而无需昂贵的文件系统操作。DARS-Agent 采用了另一种方法:在每个分支点,它将 Docker 环境重置为干净状态,并从树的根节点重放所有动作以到达目标分支,这种方法是正确的但在较深的搜索深度下代价高昂。
其余 CLI 智能体(Cline、Codex CLI、Gemini CLI、OpenCode)均实现了标准的顺序 ReAct 循环,不含分阶段结构或树搜索,与 Table 2 中的其他 ReAct 智能体处于同一中间区段。Aider 是一个特例:虽然它出现在该区段中,但其外部循环是用户驱动而非自主式的(Section 4.1.2),LLM 生成文本格式的编辑而非选择工具。然而,Aider 的内部循环(base_coder.py:932)是自主的:在 LLM 生成编辑后,脚手架运行代码检查和测试,如果任一失败,则将错误输出重新提示给 LLM,最多进行 max_reflections 次迭代。这个生成-测试-修复循环是 Aider 中唯一不需要用户输入即可进行多轮 LLM 交互的部分。
4.1.2 循环驱动者
与循环拓扑正交的问题是什么驱动循环(Table 3),这一维度可以说是最根本的架构区分。Aider 位于一个极端:LLM 从不运行 grep,从不打开未被提供的文件,也从不决定”我应该看看模块 Y”。所有导航责任都落在用户身上,PageRank 加权的仓库地图提供被动上下文。在另一个极端,13 个智能体中有 9 个赋予 LLM 对工具选择的完全自主权,Prometheus 占据一个混合位置——LLM 在每个图节点内驱动工具选择,但由脚手架控制的边管理节点间的转换。在这两个极端之间,Agentless 和 AutoCodeRover 占据中间位置,脚手架控制阶段顺序,但 LLM 在每个阶段内做出决策。
Table 3:循环驱动者策略。谁决定下一步做什么?
| 驱动者 | 智能体 |
|---|---|
| 用户驱动 | Aider:LLM 拥有 0 个可调用工具。用户选择文件(/add)、运行搜索并提供上下文。LLM 以文本格式生成编辑,由脚手架解析(base_coder.py:2296—2304)。 |
| 脚手架驱动 | Agentless, AutoCodeRover:脚手架控制顺序并在固定点调用 LLM。在 Agentless 中,每次 LLM 调用都是单轮的,没有对话状态。在 AutoCodeRover 中,脚手架管理跨越最多四个阶段的阶段转换:可选的复现器生成、可选的基于频谱的故障定位 (SBFL) 故障定位、搜索和补丁生成。 |
| LLM 驱动 | SWE-agent, OpenHands, Codex CLI, Gemini CLI, Cline, mini-swe-agent, Moatless Tools, DARS-Agent, OpenCode:LLM 选择工具并控制探索。Prometheus 是一个混合体:在每个图节点内,LLM 通过 ReAct 驱动工具选择,但节点间的转换由脚手架控制(基于状态字段的条件边,如 state[“reproduced_bug”])。 |
循环驱动者的影响超越了控制流。用户驱动的智能体回避了先前轨迹分析中识别出的缺陷定位瓶颈:如果用户选择文件,定位不正确是用户错误,而非智能体失败。LLM 驱动的智能体必须将定位作为任务的一部分来解决,这使得检索策略(Section 4.2.4)成为关键的设计选择。
4.1.3 控制流实现
上述语义层面的循环类型通过四种不同的代码级机制来实现(Table 4):(1) 命令式 while 循环,脚手架在 while True 循环中调用 LLM 并在终止信号时跳出(13 个智能体中有 8 个);(2) 递归,每个工具使用轮次触发一次递归函数调用(Cline);(3) 图即控制流,由编译后的状态机定义转换和循环(Prometheus);(4) 基于异常的信号传递,特殊的异常类型在循环体和外部处理器之间传递控制消息(mini-swe-agent)。
Table 4:控制流实现变体。本表按代码级机制对智能体进行分类,这与 Table 2 中的语义循环策略是正交的:按循环策略被归类为”用户驱动”的智能体(如 Aider)在实现层面仍可能使用命令式 while 循环。
| 实现方式 | 智能体 |
|---|---|
| 命令式 while 循环 | SWE-agent, OpenHands, Codex CLI, Gemini CLI, mini-swe-agent, Aider, OpenCode |
| 固定流水线(无循环) | Agentless:顺序脚本;每次 LLM 调用都是单轮的,没有智能体循环。Anthropic 路径包含一个有界 for 循环(最多 10 次迭代,model.py:148—284),但主体架构没有循环。 |
| 递归 | Cline:recursivelyMakeClineRequests(task/index.ts:2268)。调用栈随对话长度线性增长。 |
| 图即控制流 | Prometheus:LangGraph 编译的状态机,具有显式边(issue_graph.py:22—134)。图中的循环创建迭代;递归限制(IssueBugSubgraph 为 30,BugReproductionSubgraph 为 150;动态公式在多候选运行中可扩展至数百步)作为终止保证。 |
| 基于异常的信号传递 | mini-swe-agent:InterruptAgentFlow 层级结构(Submitted、LimitsExceeded、FormatError)将消息作为载荷传递。run() 方法捕获这些异常,将消息注入历史记录,然后继续或跳出(default.py:88—96)。 |
基于图的方法与其他方法有本质区别:控制流可被框架检查、序列化和创建检查点。Prometheus 的子图定义了自己的状态类型,每个子图被包装在一个 SubgraphNode 类中,该类在父图状态和子图状态之间进行转换。例如,父 IssueState 持有 issue_title、issue_body 和 issue_comments;IssueBugSubgraphNode 包装器将这些作为关键字参数传递给 IssueBugSubgraph.invoke()。至少存在四层嵌套:IssueGraph → IssueBugSubgraph → IssueVerifiedBugSubgraph → ContextRetrievalSubgraph。
Cline 的递归实现是语料库中唯一将递归用于主智能体循环的实例。虽然在语义上与迭代等价,但这意味着 JavaScript 调用栈随每次工具使用轮次增长。在实践中,Node.js 的默认栈限制(通常为数千帧)在正常会话中不太可能被触及,但该设计有架构层面的影响:每个递归帧保留局部状态,与迭代方法相比,控制流更难序列化或创建检查点。七个智能体(SWE-agent、OpenHands、Codex CLI、Gemini CLI、mini-swe-agent、Aider、OpenCode)使用命令式 while 循环。Agentless 完全没有智能体循环(其流水线是固定的脚本序列),尽管其 Anthropic 代码路径包含一个小型迭代循环。Codex CLI 的 while 循环明显比其他智能体复杂:它使用了双层事件驱动架构和异步通道,但逻辑模式仍然是标准的 ReAct 循环。在这个群组中,OpenCode 在架构上独具特色,它在 while 循环之上叠加了一个全局的发布-订阅事件总线(packages/opencode/src/bus/)。各组件通过类型化事件而非直接函数调用进行通信。语料库中没有其他 CLI 智能体使用事件总线进行组件间通信;OpenHands 使用事件溯源进行状态管理(Section 4.3.1),但其事件流服务于与 OpenCode 的发布/订阅总线不同的目的(持久化和重放 vs. 解耦的运行时通信)。
4.2 第二层:工具与环境接口
接口层捕捉了智能体如何与代码和执行环境交互。五个维度刻画了该设计空间:(1) 工具集设计,(2) 编辑与补丁格式,(3) 工具发现策略,(4) 上下文检索范式,(5) 执行隔离。
4.2.1 工具集设计
工具数量从 0(Aider)到 37 个动作类(Moatless Tools)不等,但原始计数掩盖了能力类别上的趋同(Table 5)。尽管数量差异悬殊,相同的四个核心能力类别(读取、搜索、编辑、执行)出现在所有 LLM 驱动的智能体中(按 Section 4.1.2 的分类)。第五个类别——验证(专门的测试运行或代码检查工具)——仅出现在 Moatless Tools 中;其他智能体将验证归入其执行能力之下。两个使用 LLM 可调用工具的脚手架驱动智能体(AutoCodeRover、Agentless)有意将工具集限制为这些类别的子集,反映了其分阶段架构。工具较少的智能体通过组合实现覆盖:mini-swe-agent 的单一 bash 工具通过委派给 shell 命令覆盖了全部四个类别。工具较多的智能体则将这些类别分解为更细粒度的操作(仅搜索类别,Moatless Tools 就拥有 FindClass、FindFunction、FindCodeSnippet、SemanticSearch、GrepTool 和 GlobTool 等独立动作)。OpenHands 因包含一个基于 BrowserGym 的无头浏览器 47 作为一等工具而突出,是语料库中唯一一个内置网页浏览工具用于导航和交互网页的智能体。它还提供了一个 think 工具用于记录推理而无副作用,以及一个 request_condensation 工具允许 LLM 请求上下文压缩(Section 4.3.2)。OpenCode 拥有相当的工具数量(18 个内置),并包含其他智能体中未见的独特工具:实验性的 LSP 集成用于符号导航、一个 skill 元工具从文件系统加载用户定义的领域特定指令和工作流、以及一个 batch 工具用于分组多个操作。Codex CLI(≈$ 20+ 个工具)值得注意的是包含了元工具,允许 LLM 在运行时发现更多工具:tool_search 查询已注册的应用工具,tool_suggest 为当前任务推荐工具。它还暴露了一个 request_permissions 工具,允许 LLM 在会话中途请求提升的沙箱访问权限,使智能体自身的权限成为可协商的资源而非固定约束。
Table 5:工具集规模与能力覆盖。工具计数反映 LLM 可调用工具;面向用户的命令(如 Aider 的 ≈$ 38 个斜杠命令)不包含在内。
| 智能体 | 工具数 | 读取 | 搜索 | 编辑 | 执行 | 验证 | 备注 |
|---|---|---|---|---|---|---|---|
| Aider | 0 | ✓ ∗ | ∗ 文本解析编辑,13 种格式 | ||||
| Agentless | 0–1 | ✓ ∗ | ∗ Anthropic 路径中 1 个模拟工具 | ||||
| AutoCodeRover | 8 | ✓ | ✓ | 全部为搜索/读取;无编辑工具 | |||
| OpenHands | 9+ | ✓ | ✓ | ✓ | +MCP;搜索通过 bash 实现 | ||
| Moatless Tools | 15–37 | ✓ | ✓ | ✓ | ✓ | ✓ | 37 个类;每个会话约 ≈$ 15 个 |
| SWE-agent | 3–35 | ✓ | ✓ | ✓ | ✓ | 默认 3 个;15 个工具包中共 35 个 | |
| DARS-Agent | ≈$ 15 | ✓ | ✓ | ✓ | ✓ | 继承自 SWE-agent 分支 | |
| Codex CLI | ≈$ 20+ | ✓ | ✓ | ✓ | ✓ | +MCP;+子智能体生成 | |
| Gemini CLI | 17+ | ✓ | ✓ | ✓ | ✓ | +MCP;+工具发现子进程 | |
| Prometheus | 17 | ✓ | ✓ | ✓ | ✓ | 每个图节点绑定 1–12 个 | |
| OpenCode | 18+ | ✓ | ✓ | ✓ | ✓ | +MCP;+插件;+自定义工具 | |
| Cline | 27+ | ✓ | ✓ | ✓ | ✓ | +MCP;最大的扁平内置工具集 | |
| mini-swe-agent | 1 | ✓ | 所有能力通过 bash 实现 |
按节点工具作用域。
Prometheus 是唯一在不同决策点绑定不同工具子集的智能体。其 EditNode 拥有 5 个工具(文件操作),而 BugReproducingWriteNode 仅拥有 read_file,BugFixVerifyNode 仅拥有 run_command。这种结构性护栏在每一步约束了动作空间。AutoCodeRover 通过阶段分离实现了类似效果:补丁智能体不被提供搜索工具,而是被提示直接从搜索阶段收集的上下文生成补丁。这是一种工作流级别的约束,而非可配置的绑定。
AutoCodeRover 定位阶段的搜索专用工具。
AutoCodeRover 的搜索智能体拥有 8 个 LLM 可调用工具,全部为只读搜索操作;搜索 LLM 无法编辑文件、运行命令或修改状态。这是使用 LLM 可调用工具的所有智能体阶段中最受约束的工具集。AutoCodeRover 确实生成补丁,但这发生在一个单独的补丁智能体阶段,该阶段提示 LLM 直接在其输出中生成补丁,而不调用任何工具。其理念是定位和修复是具有不同工具需求的不同任务:搜索阶段需要结构化的代码导航,而补丁阶段仅需要搜索阶段收集的上下文和 LLM 的代码生成能力。
AutoCodeRover 中用于工具调用的代理智能体。
AutoCodeRover 使用一个辅助 LLM 调用(agent_proxy.py:81—82)将搜索智能体的自然语言工具选择转换为结构化 JSON。搜索智能体”自言自语地思考”要调用哪些工具;代理智能体最多重试 5 次来提取结构化的调用。这为每轮搜索增加一次 LLM 调用(在可能的 15 轮中,最多增加 15 次额外的 LLM 调用),但避免了要求搜索智能体直接生成结构化输出。语料库中没有其他智能体使用辅助 LLM 调用来解析工具调用;所有其他智能体依赖函数调用 API、正则表达式解析或 XML 提取。
4.2.2 编辑与补丁格式
智能体如何将 LLM 输出转换为代码变更揭示了一种向共享接口趋同的趋势(Table 6)。str_replace_editor 工具——接受 old_str 和 new_str 参数进行精确字符串替换——出现在 13 个智能体中的 5 个中(OpenHands、SWE-agent、Codex CLI 自由模式下的 apply_patch、Agentless 作为三种修复输出格式之一、以及 Moatless Tools 的 StringReplace)。这种趋同值得注意,因为这些智能体是独立开发的;共享的接口反映了一个共同发现——对于 LLM 生成的补丁,精确字符串匹配比基于行号或基于统一 diff 的编辑更可靠 2。
Table 6:编辑/补丁格式变体。
| 格式 | 智能体 |
|---|---|
| 字符串替换(函数调用) | OpenHands 和 SWE-agent(str_replace_editor),Codex CLI(apply_patch),OpenCode(edit) |
| 写入工具(函数调用) | Gemini CLI, Cline |
| 文本解析编辑块 | Aider(13 种格式),DARS-Agent |
| 模拟工具使用 | Agentless(Anthropic 路径) |
| Pydantic 模式动作 | Moatless Tools, Prometheus |
在解析方面,SWE-agent 支持 10 种不同的输出解析器(FunctionCallingParser、ThoughtActionParser、XMLThoughtActionParser 等),使相同的工具集能够跨具有不同输出约定的模型工作。结合 Aider 的 13 种模型特定编辑格式,这代表了语料库中观察到的输出接口方面最高程度的模型无关性;然而,两种方法针对不同的层次(SWE-agent 适配工具解析,而 Aider 适配编辑格式本身)。
Aider 以 13 种注册编辑格式成为异类,每种格式作为独立的 coder 子类实现。格式根据模型能力进行选择:某些模型更擅长处理统一 diff,其他模型则更适合 SEARCH/REPLACE 块。将编辑格式视为一等的、模型特定的架构组件,这在语料库中是独特的,尽管 OpenCode 实现了同一思路的简化版本:其工具注册表根据模型能力在 edit(字符串替换)和 apply_patch(统一 diff)之间选择,提供两种格式而非十三种。
Agentless 在其 Anthropic 路径中的”模拟工具使用”在架构上是独特的。当使用 Anthropic 的 API 时,LLM 调用 str_replace_editor 工具,但每次调用都收到相同的硬编码响应:“File is successfully edited”,无论输入是什么。LLM 在编辑后从不看到实际的文件状态;工具调用被提取并在事后应用。这将工具调用 API 用作结构化输出提取技术,而非用于实际执行。
其余智能体使用同一方法的变体。AutoCodeRover 使用自定义的类 XML 标签
4.2.3 工具发现策略
工具发现的范围从完全静态(工具在初始化时固定)到真正动态(工具在会话期间添加)(Table 7)。近半数智能体(13 个中有 6 个)使用完全静态的工具注册:所有工具在初始化时定义,在整个会话期间保持不变。这是基准测试智能体(Agentless、AutoCodeRover、mini-swe-agent、DARS-Agent、Moatless Tools)和 Aider(LLM 没有可调用工具)的默认方法。SWE-agent 和 OpenHands 处于中间地带:其工具集是配置条件化的(不同的工具包根据配置加载),但一旦加载,在给定尝试中工具集是固定的。(在 SWE-agent 的重试循环中,如果 agent_configs 指定了不同的配置,不同的尝试可以加载不同的工具包。)
Table 7:工具发现策略。
| 策略 | 智能体 |
|---|---|
| 静态(全部在初始化时确定) | Aider, Agentless, AutoCodeRover, mini-swe-agent, DARS-Agent, Moatless Tools |
| 按阶段作用域(每个节点静态) | Prometheus, AutoCodeRover |
| 配置条件化 | SWE-agent, OpenHands |
| 每轮动态重建 | Codex CLI(每次采样请求调用 built_tools(),codex.rs:6156—6164) |
| 动态(MCP + 子进程) | Gemini CLI(工具发现子进程,tool-registry.ts:312—439),Cline(MCP 服务器在运行时连接/断开),OpenCode(静态核心工具 + 来自配置目录的动态自定义工具、插件系统和 MCP 集成) |
在动态的一端,Codex CLI 的每轮工具重建是独特的:大多数智能体构建工具集一次(或每个阶段一次),而 Codex CLI 在每次 LLM 采样请求时调用 built_tools(),纳入任何 MCP 服务器变更、新启用的连接器或会话期间添加的动态工具。工具集原则上在每次 LLM 调用时都可能不同。Gemini CLI 的 toolDiscoveryCommand 功能采用了不同的方法:一个外部子进程以 JSON 形式输出 FunctionDeclaration[],允许在不修改智能体代码的情况下使用任意工具源。Cline 和 OpenCode 类似地通过 MCP 服务器连接和插件系统支持运行时工具变更。Prometheus 和 AutoCodeRover 介于静态和动态之间:其工具集在每个阶段或图节点内是固定的,但不同阶段暴露不同的工具子集(如 Section 4.2.1 所述)。
4.2.4 上下文检索范式
上下文检索(智能体如何找到相关代码)显示出显著的架构差异,七种不同的策略类型从简单的关键词搜索到知识图谱遍历(Table 8)。13 个智能体分为两种检索范式,反映了关于代码理解应驻留在何处的根本不同假设。
Table 8:上下文检索策略。智能体可能使用多种策略。
| 策略 | 智能体 | 机制 |
|---|---|---|
| 关键词/正则搜索 | SWE-agent, OpenHands, Codex CLI, Gemini CLI, Cline, mini-swe-agent, DARS-Agent, OpenCode | LLM 调用 grep、find、ripgrep 作为工具。 |
| 仓库地图(静态分析) | Aider | PageRank 加权的 tree-sitter 标签索引。构建 NetworkX 依赖图;对话中提及的标识符获得 10 倍权重提升;加入聊天的文件获得 50 倍提升(repomap.py:365—574)。 |
| 抽象语法树 (AST) 感知搜索 | AutoCodeRover, Moatless Tools, DARS-Agent, Prometheus | search_class、search_method:在预构建的 AST 索引上进行结构感知查询。AutoCodeRover 的 AST 工具仅支持 Python;Prometheus 基于 tree-sitter 的工具覆盖 20 种语言。 |
| 知识图谱遍历 | Prometheus | 从覆盖 20 种语言的 tree-sitter AST 构建的 Neo4j 图。11 个工具(10 个图遍历加 read_file)查询 FileNode、ASTNode、TextNode 实体(graph_traversal.py:93—586)。 |
| 基于嵌入的语义搜索 | Moatless Tools | 48 |
| 层次化定位 | Agentless | 文件 → 类/函数 → 跨流水线阶段的行级缩窄。每一层仅看到前一层识别的内容(FL.py:313—681)。 |
| 经典故障定位 | AutoCodeRover | 使用 Ochiai 评分的 SBFL(analysis/sbfl.py)。语料库中独此一例。 |
第一种范式被八个智能体采用(SWE-agent、OpenHands、Codex CLI、Gemini CLI、Cline、mini-swe-agent、DARS-Agent、OpenCode),将 LLM 视为导航者:智能体提供通用 shell 工具(grep、find、ripgrep),依赖 LLM 制定查询、解释结果并决定下一步查看位置。脚手架本身不提供代码理解能力;它只是执行 LLM 请求的命令并返回输出。
第二种范式投资于脚手架侧的代码理解,在任务之前或期间构建代码库的结构化表示。Aider 从解析后的源代码构建依赖图,使用 PageRank 对文件相关性进行排名(下文讨论)。Agentless 在连续的 LLM 调用中从文件缩窄到类再到行,每次调用仅看到前一阶段识别的内容。AutoCodeRover 和 Moatless Tools 将源代码解析为抽象语法树 (AST),支持结构感知查询(如”查找所有名为 process 的方法”),而非文本模式匹配。Prometheus 走得最远,从覆盖 20 种语言的 AST 构建 Neo4j 49 图数据库,并提供 11 个工具(10 个图遍历加 read_file)用于查询代码实体间的关系。
范式选择与循环驱动者(Section 4.1.2)相关:脚手架驱动的智能体倾向于投资检索基础设施,而 LLM 驱动的智能体倾向于信任 LLM 使用通用工具进行导航。这种相关性并不令人意外:如果脚手架控制顺序,它就有机会(也有必要)对仓库进行预处理;如果 LLM 控制探索,它可以按需发出搜索命令。
Aider 的 PageRank 仓库地图。
Aider 的检索机制将 Google 的 PageRank 算法 50 应用于源代码结构。tree-sitter 51 解析每个文件以提取符号定义和跨文件引用,形成有向依赖图(repomap.py:365—574)。PageRank 分数按结构中心性对文件进行排名,并具有上下文感知的权重提升:对话中提及的标识符获得 10 倍权重,加入聊天的文件获得 50 倍权重,二分搜索按排名顺序填充 Token 预算。语料库中没有其他智能体使用图论相关性排名。该方法以启动成本(解析整个仓库)换取上下文质量:Aider 不依赖 LLM 导航代码库,而是从仓库的实际依赖结构预计算相关性。
AutoCodeRover 的 SBFL。
AutoCodeRover 是唯一结合了经典故障定位 52 的智能体。当存在失败测试时,它运行基于频谱的故障定位 (SBFL),使用 Ochiai 可疑度评分 53:被失败测试频繁执行而被通过测试很少执行的方法排名最高(analysis/sbfl.py)。可疑度最高的 5 个方法作为建议性输入呈现给 LLM,补充其基于搜索的探索。这在两个原本互不关联的社区(自动故障定位与基于 LLM 的修复)之间架起了桥梁 54;语料库中没有其他智能体使用基于测试执行的定位。
4.2.5 执行隔离
执行隔离的范围从无沙箱到推测性的内存中执行(Table 9)。对于树搜索智能体,执行隔离与搜索成本直接相关。DARS-Agent 的环境重置执行完整的 Docker 重置,并从根节点到分支点重放所有动作。在深度 N 处,这需要重新执行 N 条命令。DARS 通过将分支限制为特定动作类型(edit、create、append、submit)来降低这一成本,具体通过 action_expansion_limit 实现(default_dars.yaml:179—184)。Moatless Tools 完全避免了重放:其影子模式在 FileContext 对象中跟踪文件修改而不写入磁盘,每个节点克隆其父节点的文件上下文。这使得在任意步骤分支而无环境成本成为可能。
Table 9:执行隔离策略。
| 隔离级别 | 智能体 |
|---|---|
| 无(本地 shell) | Gemini CLI, Aider, OpenCode |
| 无状态子 shell | mini-swe-agent(subprocess.run(),local.py:28—39) |
| 平台级沙箱 | Codex CLI(Linux 上使用 Bubblewrap+Landlock,macOS 上使用 Seatbelt) |
| Docker 容器 | SWE-agent, OpenHands, DARS-Agent, AutoCodeRover, Prometheus |
| 影子 Git 检查点 | Cline(隔离的 Git 仓库在每次工具执行后跟踪状态,CheckpointTracker.ts) |
| 影子模式(内存中) | Moatless Tools(shadow_mode 标志,agent.py:57) |
| 不适用 | Agentless:LLM 从不执行任意命令;Docker 仅用于通过 SWE-bench harness 执行测试 |
Cline 的影子 Git。
Cline 的 CheckpointTracker 为每个工作区创建一个隔离的 Git 仓库,在每次工具执行后记录文件系统状态。这实现了基于 diff 的回滚,而不触及用户的真实 Git 历史,也不需要 Docker。它通过临时禁用嵌套 Git 仓库来处理嵌套情况,并对敏感目录进行验证。这是在无隔离和容器化之间的一种中间方案,特定于 Cline 所运行的 IDE 上下文。
安全策略的分化。
未使用容器隔离的智能体采取了截然不同的安全策略,这表明在交互式智能体的隔离标准方面,生态系统尚未形成共识。
Gemini CLI 采用基于规则的策略引擎,为每个工具分配审批要求。在执行工具调用之前,引擎会检查该工具是否需要用户确认、是否自动允许、还是完全禁止。这些规则是可配置的,允许用户根据自身工作流调整安全边界。
Codex CLI 结合了两种机制。在操作系统层面,它使用平台特定的沙箱技术(Linux 上的 Bubblewrap 55 和 Landlock 56,macOS 上的 Seatbelt)来限制文件系统和网络访问。在此之上,一个 Guardian 安全子智能体——一个独立的 LLM (gpt-5.4) 2——通过 0-100 分的结构化评分来评估每个工具调用的风险,阻止得分超过 80 分阈值的调用 (guardian.rs)。这是语料库中唯一一个使用 LLM 来评估另一个 LLM 行为安全性的智能体。
Aider 采取了最简单的方式:依赖用户在场监督。由于用户手动选择要编辑的文件,并在所有提议的更改应用之前进行审查,因此人类充当了安全边界。
Cline 提供了语料库中最细粒度的审批系统:按工具和按范围的审批设置,配合一个 CommandPermissionController 来阻止危险的 shell 操作符。设置范围从完全自主模式(“YOLO”)到按命令模式审批,为用户提供了对信任边界的精细控制。OpenCode 使用了类似于 Gemini CLI 的基于策略的权限系统:工具可以通过各自工具实现中的权限回调请求运行时用户审批,提供三个选项(允许一次、始终允许、拒绝),但不提供操作系统级别的沙箱。mini-swe-agent 使用无状态子 shell,在不使用容器化的情况下提供进程级隔离。
五个基于 Docker 的智能体(SWE-agent、OpenHands、DARS-Agent、AutoCodeRover、Prometheus)依赖容器边界作为其主要安全机制:所有命令在容器内执行,宿主文件系统永远不会被直接暴露。OpenHands 的 Docker 实现在架构上具有独特性:一个 FastAPI 动作服务器运行在容器内部,宿主端的智能体控制器通过 HTTP 与之通信。这在智能体和执行环境之间创建了一个干净的 API 边界,不同于其他直接在容器中执行命令的 Docker 智能体。Agentless 处于独特的位置:由于 LLM 从不执行任意命令(它只生成文本,由脚手架进行解析),其隔离需求与智能体方法有根本性的不同。Docker 仅用于通过 SWE-bench harness 执行测试,而非用于智能体安全。
从人工监督到基于 LLM 的安全评估,这一分布反映了一个开放的设计问题:随着智能体获得更多的自主权(Section 4.1.2),安全机制必须相应地扩展,但目前尚未出现标准的方法。
4.3 第三层: 资源管理
资源管理层关注智能体如何处理有限上下文窗口、API 成本和会话边界等约束。四个维度刻画了其中的变异:(1) 状态管理,(2) 上下文压缩,(3) 多模型路由,(4) 持久化记忆。
4.3.1 状态管理
智能体表示和维护对话状态的方式,从简单的破坏性覆写到完整的事件溯源 57,跨度极大(Table 10)。在一个极端,Aider 的双列表设计(cur_messages 和 done_messages)简单但具有破坏性:摘要化会替换 done_messages 的内容。在另一个极端,OpenHands 的事件溯源架构存储不可变事件,并通过 View 类计算视图;压缩操作插入标记而非删除事件,从而保留完整的审计轨迹。在这两个极端之间,OpenCode 基于 SQLite 的层级结构使用仅追加的消息和 12 种类型化的部件变体,是语料库中继 OpenHands 之后最细粒度的状态表示,也是唯一一个由关系数据库而非内存结构支撑的状态表示。Agentless 位于频谱的另一端:它完全没有对话状态,因为每次 LLM 调用都是单轮的。流水线各阶段之间的状态以不可变的 JSONL 文件表示,存储在磁盘上,每行对应一个问题实例的一个 JSON 对象。这种基于文件的状态总线使流水线可以被轻松恢复(—skip_existing 检查输出中的实例是否存在)和并行化,但这也意味着不存在需要管理的对话历史,因为根本没有对话。Codex CLI 在扁平列表类智能体中脱颖而出,它添加了双重持久化:一个仅追加的 JSONL 回放文件用于人类可读的重放,另有一个 SQLite 数据库用于可查询的状态和会话恢复。它也是唯一一个支持撤销(Op::Undo)和线程回滚(Op::ThreadRollback)的扁平列表类智能体。Cline 维护两个并行的消息列表,一个用于 LLM API,另一个用于 UI,通过互斥锁保护的并发访问进行同步;这种双列表架构反映了其 IDE 集成的特点,即 UI 需要比 API 更丰富的表示。
Table 10: 状态管理策略。
| 策略 | 智能体 |
|---|---|
| 破坏性 | Aider: 摘要化覆写 done_messages (base_coder.py:1024—1034) |
| 扁平列表,保留原始数据 | SWE-agent、Codex CLI、Gemini CLI: 保留原始历史;为 LLM 创建过滤视图。mini-swe-agent: 保留原始历史且不进行过滤(消息按原样发送给 LLM) |
| 类型化事件日志 | OpenCode: 基于 SQLite 的消息/部件层级结构,包含 12 种部件类型(Drizzle ORM)。仅追加的消息,部件状态可变 (message-v2.ts) |
| 图作用域 | Prometheus: 每个图节点拥有独立的消息列表 (edit_messages、analyzer_messages、context_provider_messages),在重试边界处重置 |
| 树结构 (MCTS) | Moatless Tools: 树中的节点,每个节点包含文件上下文快照、访问计数和奖励值 |
| 树结构(贪心) | DARS-Agent: 树中的节点,每个节点包含扩展候选和评判者响应 (dars_agent.py:294—297)。无 MCTS 统计信息;分支使用贪心 LLM 评判者选择,状态通过 Docker 重置和动作重放来恢复,而非文件上下文快照。 |
| 事件溯源 | OpenHands: 不可变的 EventStream;视图通过压缩标记计算 (memory/view.py:13—96) |
Prometheus 的图作用域状态在结构上具有独特性。它并非维护一个持续增长的单一对话,而是图中每个 LLM 节点维护各自的消息列表。当图循环回来进行重试时,ResetMessagesNode 清除特定的消息列表,无需任何 Token 计数逻辑即可防止无界累积。
树结构状态存储了扁平列表无法表示的逐节点元数据,但两个树搜索智能体对其的使用方式不同。Moatless Tools 维护 MCTS 统计信息(访问计数和奖励值),并在每个分支点克隆文件上下文快照。DARS-Agent 存储扩展候选和评判者响应,但没有 MCTS 统计信息:它使用贪心 LLM 评判者选择,并通过重置 Docker 环境并从根节点重放动作来恢复分支状态,而非维护逐节点的文件快照。
4.3.2 上下文压缩
所有智能体都面临有限上下文窗口的约束,压缩策略从不进行任何管理到 LLM 主动发起压缩不等(Table 11)。
Table 11: 上下文压缩策略。
| 策略 | 智能体 | 机制 |
|---|---|---|
| 无(溢出时崩溃) | mini-swe-agent | 无界增长;智能体在 ContextWindowExceededError 时崩溃。 |
| 基于规则的截断 | SWE-agent、DARS-Agent | SWE-agent: 7 个可组合的处理器;保留前 N 个和后 N 个观测,省略其余部分。用于提示缓存保留的 polling 参数。DARS-Agent: 在其分支中添加了 Last5Observations。 |
| 结构化隔离 | Prometheus、AutoCodeRover | Prometheus: 逐节点的消息作用域 + 在重试边界处重置。AutoCodeRover: 轮次限制 (15) + 结果截断。 |
| 基于 Token 的选择性包含 | Moatless Tools | 在 Token 预算内进行贪心的近期优先选择;逐观测摘要作为回退。 |
| LLM 摘要化(脚手架触发) | Aider、OpenHands、Gemini CLI、Codex CLI、OpenCode | 在 Token 阈值处自动触发。Aider: 递归层级式摘要化。Codex CLI: 轮次前和轮次中两种模式。OpenCode: 两阶段(先修剪旧输出,再进行 LLM 摘要化)。 |
| LLM 摘要化 + 验证 | Gemini CLI | 先摘要化,然后进行”Probe”验证轮次以检查信息是否丢失。 |
| LLM 主动发起的压缩 | Cline | condense 工具: LLM 决定何时进行压缩。同时也支持在 Token 阈值处脚手架触发的压缩。 |
语料库揭示了两种截然不同的理念。“预防型”智能体从结构上约束上下文增长:Prometheus 将消息限定在图节点作用域内,并在重试边界处重置;AutoCodeRover 将搜索轮次上限设为 15,每次查询最多展示 3 个完整结果;Moatless Tools 通过树结构限制轨迹深度。“治疗型”智能体则让上下文自由增长,在需要时进行压缩:Aider、OpenHands、Gemini CLI 和 Codex CLI 都在 Token 阈值处触发基于 LLM 的摘要化。预防方法避免了摘要化的成本和信息丢失,但要求脚手架预先估计上下文增长模式。Agentless 则完全绕开了压缩问题:由于每次 LLM 调用都是无对话历史的单轮调用,“压缩”简化为将代码装入单个提示。当提示超过 128K Token 限制时,Agentless 从排序列表末尾逐步丢弃文件,并通过 libcst 将函数体压缩为签名。这种预计算方法通过从不累积对话状态,消除了运行时压缩的需要。在”治疗型”智能体中,OpenCode 的两阶段策略最为精准:它首先修剪冗长的旧工具输出,保持消息结构但将最近 40,000 Token 之前的输出替换为截断标记。只有在此之后,它才通过一个可使用更廉价模型的专用压缩智能体触发基于 LLM 的摘要化。与纯截断相比,这种方法保留了更多的对话上下文;与全面摘要化相比,则更具针对性。Codex CLI 区分了轮次前压缩和轮次中压缩:轮次前压缩在每个用户轮次之前运行,清除引用上下文,以便下一轮次能干净地重新注入初始上下文;轮次中压缩在工具执行期间达到 Token 限制时运行,将初始上下文注入到最后一条用户消息之上,以匹配模型对上下文出现位置的训练预期。这种对压缩时机与对话结构关系的感知在语料库中是独一无二的。
SWE-agent 的 polling 参数。
SWE-agent 的 LastNObservations 处理器包含一个 polling 参数,揭示了压缩与 API 成本之间的一个微妙交互。许多 LLM 提供商提供提示缓存,即共享相同消息前缀的连续调用可以跳过重复处理。如果不使用 polling,每个新观测都会改变包含哪些消息,从而使缓存失效。使用 polling 后,截断变化仅以每步 1/polling 的速率发生,使前缀在连续调用之间保持稳定。这种成本优化处于两个本来相互独立的关注点的交汇处,在此前对 SWE-agent 的分析中未被记录。
Gemini CLI 的验证探测。
Gemini CLI 是唯一一个验证自身上下文压缩结果的智能体。在 LLM 摘要化之后,它运行一个”Probe”轮次,让模型检查关键信息是否丢失。这种自我纠正机制以每次压缩事件额外消耗一次 LLM 调用为代价,解决了 LLM 摘要化的一个已知失效模式(技术细节的有损压缩)。
Cline 的 LLM 主动发起的压缩。
Cline 的 condense 工具赋予了 LLM 对自身上下文管理的能动性。如果 LLM 判断上下文已变得难以处理,它可以主动请求摘要化。语料库中没有其他智能体将压缩决策委托给 LLM。OpenHands 提供了一个概念上类似的 CondensationRequestAction,但压缩也可以在历史记录超过压缩器阈值时自动触发。OpenHands 的压缩器架构是语料库中最具可扩展性的:九个可插拔的实现通过注册表模式组合成流水线。由于压缩操作在视图层面进行(插入 CondensationAction 标记而非删除事件),原始事件流永远不会被修改,即使在积极压缩之后也能实现会话重放。
4.3.3 多模型路由
多模型路由(为不同子任务使用不同的 LLM)从单模型的简洁性到多策略分类器链不等(Table 12)。两个智能体自始至终使用单一模型:mini-swe-agent 和 Agentless。OpenHands 提供了可扩展的路由基础设施,但默认采用单模型运行;其唯一已实现的路由器仅根据图像是否存在和 Token 限制做出有限的决策。其余 10 个智能体路由到多个模型,但出于不同的原因。
Table 12: 多模型路由策略。
| 策略 | 智能体 | 机制 |
|---|---|---|
| 单模型 | mini-swe-agent、Agentless(按路径) | 全程使用一个模型。 |
| 路由器抽象(默认单模型) | OpenHands | RouterLLM 基类,配合 MultimodalRouter: 根据图像是否存在和 Token 限制进行路由 (llm/router/rule_based/impl.py:16—81)。默认: 通过 noop_router 使用单模型。 |
| 基于角色 | Aider、OpenCode | 为不同子任务配置主模型/弱模型/编辑器模型。Aider: 弱模型用于摘要化和提交消息 (models.py:607—608);编辑器模型用于架构师模式 (architect_coder.py:22—25)。OpenCode: 为构建、计划、探索和压缩智能体配置逐智能体的模型覆盖 (agent/agent.ts:78—233)。 |
| 基于计划/执行模式 | Cline | 每种模式使用独立的模型 (api/index.ts:76—149)。LLM 通过工具调用切换模式。 |
| 逐次尝试轮换 | SWE-agent、AutoCodeRover | 在重试时使用不同的模型。SWE-agent: 在 agent_configs 中轮询 (agents.py:303—319)。AutoCodeRover: 在 model_names 中轮询 (inference.py:98—114)。 |
| 安全导向 (Guardian) | Codex CLI | 独立模型 (gpt-5.4) 评估工具调用的风险 (guardian.rs)。 |
| 基于任务的双模型 | Prometheus | 高级模型用于推理(分析、编辑、补丁选择);基础模型用于机械性任务(检索、验证)(llm_service.py:23—38)。按图节点硬编码。 |
| Actor-Critic | Moatless Tools | 价值函数(可能使用不同模型)为节点评分 (value_function/base.py)。 |
| 分类器链 | Gemini CLI | 7 层优先级路由: 回退 → 覆盖 → 审批模式 → Gemma 分类器 → LLM 分类器 → 数值分类器 → 默认 (modelRouterService.ts:39—67)。可选的本地 Gemma 模型用于客户端路由。 |
成本优化是主要驱动力。
在使用多模型的智能体中,主要动机是成本:将机械性任务路由到更廉价的模型,同时将昂贵的模型留给推理任务。Aider 的”弱模型”处理摘要化和提交消息;在架构师模式下,第三个”编辑器模型”接收计划并生成编辑。OpenCode 通过逐子智能体的模型覆盖扩展了这种基于角色的方法。
Prometheus 以更细的粒度应用了同样的原则。其 LangGraph 状态机中的每个节点都被硬编码为使用”高级”或”基础”模型。推理密集型节点(分析、编辑和补丁选择——最后一项进行 10 次多数投票 LLM 调用)使用高级模型,而机械性节点(知识图谱遍历、测试执行)使用基础模型。由于路由是按节点而非按角色进行的,成本节约随图中机械性步骤占比的增加而扩大。
Gemini CLI 的分类器链。
Gemini CLI 的 7 层路由策略是观察到的最复杂的路由机制。每一层实现不同的策略,第一个产生决策的层胜出,因此简单的情况以低成本解决,而模糊的情况则传递给更复杂的分类器。最具特色的层是可选的 GemmaClassifierStrategy,它在本地运行一个轻量级的 Gemma 模型 58 进行客户端路由决策,避免了仅为选择模型而发出 API 调用。没有其他智能体执行客户端模型选择。
树搜索中的 Actor-Critic。
Moatless Tools 的价值函数 (value_function/base.py) 为搜索树节点分配数值奖励。当配置为使用与动作智能体不同的模型时,结果是一种 Actor-Critic 架构:一个模型生成动作,另一个模型评估动作。没有其他智能体使用不同的模型分别进行生成和评估;DARS-Agent 的 LLM 评判者扮演类似角色,但生成和评估使用同一模型,这意味着评判者共享了生成者的偏见。
其他路由策略。
两个智能体使用逐次尝试的模型轮换:SWE-agent 和 AutoCodeRover 都在重试时轮换不同的模型配置,押注在一次尝试中失败的模型,在由不同模型从零开始尝试同一任务时可能会成功。Cline 按模式而非按角色进行路由:其计划和执行模式各使用一个独立配置的模型,LLM 通过工具调用在模式之间切换。Codex CLI 是语料库中使用模型数量最多的智能体:用于代码生成的主模型,用于工具调用安全评估的 Guardian 模型 (gpt-5.4),以及其记忆提取流水线的两个专用模型(gpt-5.1-codex-mini 用于逐回放提取,gpt-5.3-codex 用于整合;Section 4.3.4)。Guardian 是语料库中唯一一个出于安全而非成本或能力原因进行多模型路由的实例。
4.3.4 持久化记忆
持久化记忆(跨会话留存的知识)从完全不存在到多层提取流水线不等(Table 13)。基准测试评估类智能体和交互式使用类智能体之间存在明显的分界。五个没有持久化记忆的智能体(SWE-agent、OpenHands、AutoCodeRover、mini-swe-agent、DARS-Agent)将每个任务视为独立的,没有跨任务学习。对于纯基准测试智能体(SWE-agent、AutoCodeRover、mini-swe-agent、DARS-Agent),这是预期之中的;而对于同时广泛用于交互式开发的 OpenHands(53k star,语料库中第二高),缺乏持久化记忆值得关注,尽管其 microagent 系统加载的静态项目指令部分填补了这一角色。Agentless 也缺乏跨任务学习,但通过缓存输出和嵌入索引支持流水线可恢复性,介于上述两组之间。五个具有持久化记忆的 CLI 智能体(Aider、Cline、Gemini CLI、Codex CLI、OpenCode)面向交互式开发,在这种场景中记住项目规范和过往决策具有直接价值。Prometheus 是一个异类:尽管它是一个 SWE-bench 智能体(Table 1),却实现了更具交互式工具特征的多层持久化(Neo4j、PostgreSQL、Athena),这暗示着超越基准测试评估的架构抱负。在这些智能体中,“记忆”的含义差异显著:Cline 和 Gemini CLI 持久化学习到的规则,Codex CLI 从过往会话中提取和整合记忆,而 OpenCode 则在 SQLite 中持久化完整的会话状态,包括所有消息、工具输出、Token 使用量和成本,使得中断的会话可以在完整上下文下恢复。
Table 13: 持久化记忆策略。
| 策略 | 智能体 | 机制 |
|---|---|---|
| 无 | SWE-agent、OpenHands、AutoCodeRover、mini-swe-agent、DARS-Agent | 无跨会话持久化。每次运行从零开始。轨迹文件是输出制品,不被未来的运行消费。 |
| 流水线可恢复性 | Agentless | 无跨任务学习,但 JSONL 输出支持流水线可恢复性 (—skip_existing),嵌入索引通过 —persist_dir 持久化,预计算的仓库结构通过 PROJECT_FILE_LOC 缓存。这些被同一流水线的未来运行消费,而非跨任务知识。 |
| 配置文件加载 | Aider (.aider.conf.yml) | 静态的、用户编写的配置。标签缓存 (repomap.py:43, 217—265) 将 AST 分析跨会话持久化,作为性能优化。 |
| LLM 可写的规则/记忆 | Cline (.clinerules/)、Gemini CLI (GEMINI.md) | LLM 主动编写持久化指令。Cline: new_rule 工具 (tools.ts:31)。Gemini CLI: save_memory 工具将内容追加到 GEMINI.md 的”Gemini Added Memories”部分 (memoryTool.ts)。 |
| 完整会话持久化 | OpenCode | 基于 SQLite 的会话历史,支持恢复能力。所有消息、工具输出、Token 使用量和成本均被持久化 (session/session.sql.ts:14—76)。 |
| 后台提取流水线 | Codex CLI | 两阶段: 第一阶段从近期回放中提取记忆(并行,gpt-5.1-codex-mini);第二阶段通过子智能体整合 (gpt-5.3-codex)。按使用频率排序,过时记忆被修剪 (memories/README.md)。 |
| 多层持久化 | Prometheus | Athena(语义记忆服务,HTTP API)+ Neo4j(知识图谱,20 种语言的 AST)+ PostgreSQL(LangGraph 检查点)。记忆优先检索,知识图谱作为回退 (context_retrieval_subgraph.py:159—163)。 |
静态项目指令。
“无”类别中的若干智能体确实会加载跨会话持久化的静态、用户编写的项目指令。OpenHands 通过其 microagent 系统从工作区读取 .openhands_instructions 和 .cursorrules,类似于 Aider 的 .aider.conf.yml。这些未被归类为持久化记忆,因为智能体从不写入或更新它们;它们是静态配置而非学习到的知识。
LLM 作为记忆的作者。
Cline 和 Gemini CLI 共享一种模式,即 LLM 编写自己的持久化指令。Cline 的 new_rule 工具创建 .clinerules 文件;Gemini CLI 的 save_memory 工具向 GEMINI.md 追加内容,后者还支持 @path/to/file 引用以跨多个文件组合指令。这些记忆持久化在项目仓库中,并在未来会话的系统提示中被加载。Codex CLI 采取了不同的方法:一个后台流水线提取和整合记忆,而无需 LLM 明确决定要记住什么。
跨工具兼容性。
Cline 不仅读取自己的 .clinerules/,还读取 .cursorrules、.windsurfrules 和 AGENTS.md。这种务实的互操作性反映了一个正在形成的生态系统,在该生态系统中开发者使用多个 AI 编码工具并共享项目级指令 26。
4.4 跨维度主题
若干发现横跨多个分类法维度,无法简化为单一轴线。这些跨维度主题源自分析模板的开放编码部分(Section 3.2),代表了在不同维度上以不同方式呈现的架构模式或权衡取舍。之所以单独呈现,是因为将它们强行纳入维度框架会遮蔽其多维本质。
4.4.1 采样与迭代
当 LLM 生成的补丁失败时,有两种根本不同的重试方式:生成另一个独立的尝试(采样),或利用失败的反馈来改进失败的尝试(迭代)。这一区分横跨控制循环分类法,因为它描述的是智能体如何处理解决方案尝试的总体,而非任何单次尝试的结构。
Agentless 是采样的最纯粹示例:它独立生成多个补丁,并通过多数投票进行选择(Section 4.1.1)。每个补丁都从相同的上下文生成;没有任何补丁因知道另一个失败而受益。
九个 LLM 驱动的智能体中有六个(OpenHands、Codex CLI、Gemini CLI、Cline、mini-swe-agent、OpenCode)采取了相反的方式:纯迭代。单次尝试通过反馈循环不断精化,每一步都能看到前一步的结果。如果测试失败,智能体会看到错误消息并进行调整。这种深度优先策略押注于反馈比独立性更有价值,且单条有引导的轨迹比多条无引导的轨迹更可能收敛到正确的解决方案。
多数投票也出现在 Prometheus 中,但处于不同的层面。Prometheus 并非独立生成补丁,而是在同一提示上调用高级模型 10 次,以在已生成的候选补丁中进行选择,当票数领先超过剩余票数时提前终止。在这里,投票运作在决策层(选择提交哪个补丁),而非生成层(创建补丁)。
SWE-agent 的 RetryAgent 介于采样和迭代之间。它生成多个完整的尝试——每个都是一条拥有自身反馈循环的完整深度优先轨迹——并通过一个审阅模型选出最佳者。每次尝试可以使用不同的模型配置。其结果将每次尝试内的迭代(反馈驱动的精化)与跨尝试的采样(事后评估的独立轨迹)结合在一起。
4.4.2 子智能体委托
五个智能体支持子智能体生成,即主智能体创建一个辅助智能体实例来处理子任务。这一能力之所以重要,是因为它支持并行性(同时处理多个文件)和专业化(委托给具有不同工具权限或系统提示的智能体)。然而,这五个智能体通过根本不同的机制实现委托,揭示了关于谁应控制委托决策的不同假设。
Codex CLI 通过将委托作为一套工具暴露给 LLM,赋予其完全的委托控制权:spawn_agent、send_input、resume_agent、wait 和 close_agent。LLM 决定何时生成子智能体、分配什么任务以及何时收集结果。深度受 agent_max_depth 限制,协作工具在最大深度时被禁用,以防止无界递归。
OpenCode 采取基于角色的方法:其 task 工具生成具有不同专长的子智能体(build、plan、explore、general),每个都有脚手架强制的工具权限。plan 智能体对大多数路径禁用文件编辑工具(edit、write),但保留 bash 访问;explore 智能体启用面向读取的工具加 bash,同时默认拒绝面向写入的工具。LLM 选择调用哪个专家,但可用的专长及其能力由脚手架定义。这是一种结构性约束,不同于 Cline 的计划/执行模式切换——后者由 LLM 自身通过工具调用决定何时转换模式。
OpenHands 将委托集成到其事件溯源架构中。父 AgentController 通过 AgentDelegateAction 创建子控制器,并将事件转发给委托者。由于委托通过与所有其他动作相同的事件流进行,它自动被捕获在智能体的历史中,并受到与其他动作相同的压缩和重放机制的约束。
Cline 通过 new_task 和 use_subagents 提供了更简单的基于工具的委托。Gemini CLI 通过其 LocalAgentExecutor 支持子智能体,后者运行一个独立的 ReAct 循环,拥有自己的轮次限制和截止时间计时器;其独特之处在于包含一个恢复阶段,当截止时间到达时给予子智能体最后一轮以产生输出。Prometheus 的图结构通过子图嵌套隐式地进行委托,而非显式的生成。
4.4.3 在线选择与离线选择
树搜索智能体面临两个不同的选择问题:在搜索过程中下一步探索哪个分支(在线引导),以及在搜索完成后返回哪个已完成的解决方案(离线选择)。这两个问题可以由相同的机制解决,也可以由不同的机制解决,各有不同的权衡。
DARS-Agent 将两者清晰地分离。在搜索过程中,LLM 评判者在每个分支点的候选动作之间进行选择;这是塑造搜索树哪些部分被探索的在线引导。搜索完成后,一个单独训练的审阅者评估已完成的补丁;这是选择最终输出的离线选择。这种分离意味着每个组件可以独立优化:在线评判者需要快速(它在每个分支点运行),而离线审阅者可以更加深入(它只在最后运行一次)。
Moatless Tools 也将两个组件分离。价值函数在在线 MCTS 模拟期间分配数值奖励;一个独立的判别器离线评估并选择最佳已完成轨迹。与 DARS-Agent 独立训练的审阅者不同,两个组件可以配置为使用同一模型,使判别器能够应用与搜索引导一致的评估标准。
两者在如何提取最终答案上的对比进一步延伸。DARS-Agent 的最左路径提取总是取 children[0],完全依赖在线评判者已将搜索引导向好的解决方案。Moatless Tools 的判别器则主动重新评估所有已完成的轨迹,有可能选择一个在搜索过程中并非被访问最多的轨迹。
4.4.4 生态系统成熟度
DARS-Agent 与 SWE-agent 之间的关系说明了当前生态系统的成熟度状况。当 DARS-Agent 需要在 SWE-agent 的 ReAct 循环之上添加树搜索能力时,它复制并修改了整个代码库而非扩展它:agents.py 是原始 SWE-agent Agent 类的 700 行副本,dars_agent.py 是一个 1382 行的并行重新实现,加入了树搜索逻辑。这种基于分叉的复用意味着任一项目中的缺陷修复和改进都不会传播到另一个项目。
mini-swe-agent 采取了相反的方法,复用 SWE-agent 的执行环境(包括其 SWE-ReX Docker 和 Modal 后端),同时在其之上定义自己的抽象。它将 agent、model 和 environment 指定为 Python Protocols——一种结构化类型 59,即任何拥有正确方法的对象自动符合该接口。这使得在不修改 mini-swe-agent 代码的情况下替换为其他实现成为可能。
对同一上游项目同时存在基于分叉和基于依赖的复用,表明生态系统尚未围绕干净的扩展点稳定下来。Moatless Tools 的双流架构(Section 4.1.1)提供了这种稳定化的一种预示:逐步逻辑与编排策略之间的干净分离,使得在顺序模式和树搜索模式之间切换成为一个配置选择。
4.4.5 IDE 作为架构
Cline 是语料库中唯一一个作为 IDE 扩展而非独立 CLI 或服务器运行的智能体 40。这一架构选择使其能够获取 CLI 智能体无法获得的一类上下文:IDE 自身对项目的理解。
例如,@problems 提及调用 VS Code 的诊断 API,使智能体能够访问与开发者在编辑器”Problems”面板中看到的相同的类型错误、lint 警告和构建失败。@terminal 提及访问集成终端输出,命令在可见的终端面板中通过 VS Code 终端 API 执行,因此用户可以实时观察命令运行。FileContextTracker 监控模型在各轮次中已查看、读取或修改的文件,检测外部修改以防止差异编辑时的上下文过时。
其权衡是平台锁定。这些能力依赖于 VS Code 的扩展 API,Cline 的核心功能(诊断集成、文件监控、检查点 Git 集成)无法在 VS Code 之外运行。代码库显示出持续解耦的迹象(一个独立的终端管理器、一个 CLI 模式),但最丰富的上下文来源仍然依赖于 VS Code。
5 讨论
Section 4 所呈现的结果描述了三个架构层上的 12 个维度,每个维度展示了 13 个开源编码智能体中观察到的一系列策略。本节沿三条线索解读这些发现,分别对应 Section 1 中陈述的贡献:设计空间的频谱性、组合性特征对研究者分类智能体的方式意味着什么(Sections 5.1-5.2),分类法为研究智能体行为的研究者和构建新脚手架的实践者提供了什么(Sections 5.3-5.4),以及证据基础揭示了关于生态系统成熟度和评估方法论的什么信息(Sections 5.5-5.6)。
5.1 频谱而非类别
在全部 12 个维度中,最持续性的发现是:脚手架架构抵抗离散分类。此前关于 LLM 智能体的分类法按照抽象能力将系统组织为不同类别:工具使用型、记忆增强型、规划型、反思型 7 8。本文语料库中的每个智能体都符合上述所有类别,然而它们的实现方式存在这些标签无法表达的差异。源代码分析表明,这种差异更适合用连续频谱来描述:控制循环的范围从固定流水线到完整的 MCTS (Section 4.1.1),工具数量从 0 到 37 (Section 4.2.1),上下文压缩从完全没有到 LLM 主动发起的压缩 (Section 4.3.2),状态管理从破坏性覆写到事件溯源 (Section 4.3.1)。在每个频谱内,智能体占据着不同的位置,这些位置反映的是真实的架构权衡,而非随意的实现选择。
这种频谱特征有其结构性解释:Section 4.1.1 中识别出的循环原语 (ReAct、生成-测试-修复、计划-执行、多次重试、树搜索) 作为可组合的构建块,被智能体自由地分层和嵌套。由于这些原语可以自由组合,可能的架构空间是组合式的而非类别式的。给一个叠加了多种原语的系统贴上单一标签 (“ReAct 智能体”、“流水线智能体”),会掩盖真正区分它们的设计决策。
对研究者而言,这一发现表明,独立评估各个脚手架维度可能比对整个智能体进行分类更有信息量。一项比较 “ReAct 智能体” 和 “流水线智能体” 的研究,实际上将循环拓扑、循环驱动者、工具集设计和上下文管理混为一个二元变量。沿本文识别的维度进行分解,可以更精确地将行为差异归因于具体的架构选择。对实践者而言,循环原语的可组合性表明,设计决策可能比表面看起来更加正交:Moatless Tools 证明了树搜索可以叠加在现有的逐步智能体之上,而无需重写智能体逻辑 (Section 4.1.1),不过所有维度组合是否都同样可行,仍然是一个有待实证验证的问题。
5.2 趋同与分化
在 12 个维度中,有些维度在智能体之间表现出强烈的趋同,另一些则呈现广泛的分化,这一模式本身具有信息价值。趋同的维度往往反映了脚手架设计者所面临的外部约束:工具能力类别趋同于读取、搜索、编辑和执行代码 (Section 4.2.1),因为无论架构理念如何,这些都是软件工程任务所必需的操作。编辑格式正在向字符串替换趋同 (Section 4.2.2),因为与基于行号或统一 diff 格式相比,LLM 使用精确字符串匹配能产生更可靠的编辑——无论这是独立发现还是对成功设计的模仿。执行隔离在基准测试智能体中趋同于 Docker 容器 (Section 4.2.5),因为在无人值守的评估中,没有沙箱的自主代码执行是不可接受的。这些趋同反映了已解决的问题或硬性约束:设计空间已被充分探索,实践者已经收敛到可行的解决方案上。
分化的维度则呈现不同的面貌。上下文压缩 (Section 4.3.2) 在 13 个智能体中表现出七种不同的策略,从完全不管理到 LLM 主动发起的带有验证探针的压缩。状态管理 (Section 4.3.1) 的范围从破坏性覆写到事件溯源,其间包含树结构、图作用域和数据库支持的变体。多模型路由 (Section 4.3.3) 跨越了从单模型的简洁性到七层分类器链的范围。这些维度之所以分化,是因为它们所针对的是尚无主导解决方案的开放设计问题。例如,上下文压缩需要在信息保留与 Token 成本之间取得平衡,而最优权衡取决于任务长度、模型能力和成本容忍度,没有任何单一策略能够解决。状态管理涉及简洁性、可审计性与分支探索支持之间的类似权衡。这些维度上的分化并非噪声,而是反映了对最佳方法的真正不确定性。
这一模式具有实际意义。趋同的维度是标准化的候选对象:一个涵盖四个能力类别的共享工具协议 (正如 MCP 开始尝试的那样) 将减少重复工作,同时不会限制架构创新。相反,分化的维度正是最需要研究投入的领域。上下文压缩策略的多样性尤其表明,现有方法没有任何一种能够完全解决 22 所识别的 “Token 雪球效应” 问题——即工具输出带来的上下文增长同时降低性能和增加成本。已观察到的策略范围 (通过结构限定进行预防、通过摘要进行治疗,以及混合方法) 代表了一个活跃的设计前沿。
5.3 脚手架-模型接口
分类法揭示了一个此前研究尚未系统考察的现象:脚手架设计以多种方式中介了模型能力。同一底层语言模型的行为表现会因以下因素而不同:被呈现的工具数量 (Aider 中为 0,SWE-agent 中为 35,Section 4.2.1)、上下文的管理方式 (mini-swe-agent 中的完整未过滤历史,与 OpenHands 中带有压缩的事件溯源视图,Section 4.3.2)、外围的循环结构 (Agentless 中的单次流水线与 SWE-agent 中的反馈驱动迭代,Section 4.1.1),以及循环的驱动者 (Aider 中由用户驱动、AutoCodeRover 中由脚手架驱动、OpenHands 中由 LLM 驱动,Section 4.1.2)。每一个脚手架层面的决策都塑造了模型所看到的内容、它能采取的动作,以及其错误如何传播或被纠正。
这一观察对编码智能体的实证研究有直接影响。使用不同模型来比较智能体的轨迹分析 9 无法分离所观察到的行为差异究竟源于脚手架还是模型。本分类法提供了精确描述两个智能体之间脚手架维度差异的词汇表,从而使设计受控比较成为可能。例如,一项研究可以比较工具集相同但循环策略不同的智能体 (Section 4.1.1),或循环相同但压缩策略不同的智能体 (Section 4.3.2),同时保持模型不变。11 呼吁建立架构感知的评估指标,将内部组件与可观测结果关联起来;本文识别的 12 个维度恰好提供了此类指标需要控制的架构变量。
脚手架-模型接口还解释了为什么循环驱动者维度 (Section 4.1.2) 可以说是最根本的架构区分。正如 Section 4.1.2 所记录的,用户驱动的智能体完全绕过了定位瓶颈,而 LLM 驱动的智能体则必须解决它,这使得检索策略成为一个关键的协同设计选择。同一模型在用户精心策划的上下文中表现良好,但在被迫自主导航代码仓库时可能会力不从心。这种交互说明了为什么脚手架维度不能孤立评估——它们构成一个相互依赖的设计空间。
5.4 对智能体设计的启示
从分类法中可以归纳出若干实用的设计经验,不过应将其理解为在 13 个智能体中观察到的模式,而非规定性的建议。
循环组合作为设计策略。
13 个智能体中有 11 个叠加了多种循环原语,而非依赖单一控制结构 (Section 4.1.1)。纯粹的单循环智能体十分罕见:Agentless (仅流水线) 和 mini-swe-agent (仅 ReAct) 是最接近的例子,而且两者都是刻意追求极简主义。这一模式表明,ReAct 循环虽然是基础性的,但通常仅凭自身是不够的;在其之上叠加重试、测试-修复或规划原语,可以解决单一反馈循环无法处理的失败模式 18。
工具数量与能力-混淆权衡。
工具数量的范围从 0 到 37,但底层的能力类别趋同于四类 (读取、搜索、编辑、执行)。尽管在工具层面存在分化,但在能力层面的趋同表明,这四个类别定义了自主编码智能体的最小可行工具集。在此基线之上,面临的权衡是表达力与 LLM 混淆之间的权衡:更专门化的工具降低了 LLM 每个工具的推理负担,但增加了其必须导航的动作空间 2。Prometheus 的逐节点工具限定 (Section 4.2.1) 和 AutoCodeRover 的阶段分离提供了管理这种权衡的两种策略——在每个决策点约束可见的工具,而不是在每一步都呈现完整的工具集。
上下文压缩作为架构需求。
每个赋予 LLM 持续自主权的智能体都必须处理上下文增长问题。Section 4.3.2 记录了两种理念:预防 (通过结构限定上下文) 和治疗 (按需压缩)。预防避免了信息丢失,但需要预判增长模式;治疗更加灵活,但存在有损压缩的风险。唯一没有压缩策略的智能体 (mini-swe-agent) 在上下文窗口被超出时会崩溃,这证实了对于在非平凡任务长度下运行的智能体,压缩不是可选项。
子智能体委派作为新兴能力。
13 个智能体中有 5 个通过五种不同机制支持显式子智能体生成 (Section 4.4.2);第六个 Prometheus 通过子图嵌套而非显式生成实现了隐式委派。这种多样性以及主导模式的缺失表明,委派是一个活跃的设计前沿。委派决策由谁控制的差异,映射了循环驱动者频谱 (Section 4.1.2),表明自主性与控制之间的权衡在智能体架构的每个层级都会反复出现。
5.5 对智能体评估的启示
如 Section 3.5 所述,智能体之间的 SWE-bench 比较将脚手架设计、模型选择和配置混淆在单一指标中。分类法使这种混淆变得具体化。正如 Section 4.3.3 所记录的,智能体使用不同的模型和不同数量的模型;Codex CLI 路由到四个不同的模型,而 mini-swe-agent 只使用一个。SWE-agent 和 AutoCodeRover (Section 4.3.3) 中的逐次尝试模型轮换意味着,单次基准测试运行可能涉及多个模型,进一步增加了归因的复杂性。控制这些差异需要本分类法所提供的那种架构分解,而现有评估并未进行这种分解。
采样与迭代的区分 (Section 4.4.1) 提出了一个特别尖锐的评估挑战。Agentless 的独立采样策略和 SWE-agent 的迭代重试策略代表了解决同一问题的根本不同方法,但基准测试分数将单次尝试质量与多次尝试策略混为一谈。一个产生平庸单个补丁但采样 40 个并选择最佳者的智能体,可能会超过一个通过迭代精炼产生高质量单个补丁的智能体。将这两种能力在评估中分离,需要同时报告单次尝试和多次尝试的指标——分类法使这种区分变得清晰,但当前的基准测试并未强制执行。
架构感知的评估无需全新的基准测试。本文识别的 12 个维度提供了可在现有评估框架内应用的具体控制变量。例如,固定工具集 (Section 4.2.1) 而变化控制循环 (Section 4.1.1),可以分离循环策略对任务成功的影响。固定模型而变化脚手架,可以将脚手架效应从模型效应中分离出来。分类法提供了变量;评估方法论则是实验设计的问题。
5.6 生态系统成熟度与标准化
语料库中复用和模块化的状态反映出一个快速创新但尚未围绕共享抽象稳定下来的生态系统。正如 Section 4.4.4 所记录的,针对同一上游项目,基于 fork 的复用和基于依赖的复用并存,这表明清晰的扩展点尚未形成。
工具能力类别的趋同与工具接口的分化并存 (Section 4.2.1),暗示了一个具体的标准化机会。所有 LLM 驱动的智能体都需要用于读取、搜索、编辑和执行代码的工具,但每个智能体定义了自己的工具模式、参数名称和输出格式。一个共享的工具接口协议可以降低新工具的集成成本,同时不限制脚手架如何编排这些工具。MCP (Model Context Protocol) 60 已被语料库中的五个智能体支持 (OpenHands、Codex CLI、Gemini CLI、Cline、OpenCode),代表了这种标准化的早期尝试,尽管它运行在传输层而非为特定工具类别定义语义契约。
Moatless Tools 的双流架构 (Section 4.1.1) 提供了一个更聚焦的模型,展示了模块化脚手架设计的可能形态。它在逐步执行器 (ActionAgent) 和编排策略 (AgenticLoop 或 SearchTree) 之间的清晰分离意味着,添加新的探索策略只需实现新的编排器,而无需修改智能体逻辑。这种关注点分离在语料库中较为罕见;大多数智能体将其逐步逻辑与编排策略紧密耦合,使得在没有大量重构的情况下难以实验替代控制结构。随着生态系统的成熟,这种模块化分离可能比工具协议标准化更有价值,因为它针对的是设计差异最大的架构层级 (Section 5.2)。
Cline 的 IDE 集成 (Section 4.4.5) 展示了生态系统演进的另一个侧面:平台耦合与能力丰富度之间的权衡。Cline 访问的 IDE 原生上下文 (诊断信息、文件变更追踪、终端集成) 对 CLI 智能体不可用,但代价是对 VS Code 平台的锁定。对整个生态系统而言,这种张力可能通过协议层抽象 (通过标准化 API 提供 IDE 品质的上下文) 而非平台趋同来解决,但目前尚不存在这样的抽象。
6 效度威胁
本节按照实证软件工程研究的标准框架 43 组织效度威胁:构造效度 (研究是否测量了其声称测量的内容)、内部效度 (研究发现是否源自数据)、外部效度 (研究发现是否可推广到本研究之外) 和可靠性 (研究是否可以被复现)。
6.1 构造效度
主要的构造效度威胁是单作者偏差。全部 13 个智能体的分析均由单一作者完成 (辅以 LLM 协助的代码导航,如 Section 3.4 所述),这意味着维度分类、证据选择和跨智能体比较反映的是一个人对源代码的解读。两项缓解措施部分解决了这一威胁。第一,Section 4 中的每一项分类主张都建立在固定提交哈希处的具体文件路径和行号之上 (Appendix B),使每项主张都可以独立地对照源代码进行验证。一次事后验证检查了从克隆仓库中提取的 296 项主张,确认了 267 项,修正了 19 项 (主要是由于分析日期和验证日期之间代码演进导致的行号偏移),接受了 10 项作为轻微简化 (例如,用比代码实际实现更少的步骤描述一个多步过程,或将跨越两个函数的行为归因于单个函数)。验证由进行原始分析的同一研究者完成;虽然自我验证弱于独立审核,但固定提交的证据链使独立验证变得简便。第二,分析模板将观察 (代码做了什么)、分类 (如何映射到维度) 和证据 (文件路径和行号) 分离,遵循了案例研究报告指南 43。这种分离使读者可以独立于观察来评估分类。尽管如此,本研究仍将受益于第二位分析者的独立复现,尤其是在需要判断取舍的维度上 (例如,Prometheus 的图作用域状态管理是否构成一种结构性压缩的形式,还是一种独立的架构模式)。
第二个构造效度威胁涉及维度框架本身。虽然九个分析维度是在对两个架构对比鲜明的智能体进行试点分析 (Section 3.2) 时通过开放编码 41 迭代得出的,但试点智能体 (Aider 和 OpenHands) 可能未能呈现所有相关维度。分析模板的开放式第十节旨在捕获预定义维度之外的观察,它产生了 47 项跨维度发现,为最终分类法提供了信息 (Section 4.4)。然而,两个试点智能体都不具备且后续智能体也未使其显著的维度仍可能被遗漏。例如,分类法不包含提示工程策略维度 (系统提示如何构建和变化)。虽然提示模板在源代码中可见,但该维度因范围原因被排除:分析 13 个智能体的提示结构、长度、少样本示例和角色指令本身就构成一项独立研究,而且在没有运行时实验的情况下,无法评估提示差异 (相对于脚手架差异) 的架构影响。这一排除是有意为之,但意味着脚手架设计的一个重要方面未被捕获。
6.2 内部效度
内部效度关注的是,观察到的模式是否真正反映了架构关系而非混淆因素。两个威胁与此相关。
第一,分类法描述的是固定提交处的源代码,但若干智能体在分析期间正处于活跃开发状态 (Section 3.4)。架构特性可能在被分析的提交与当前版本之间被添加、移除或大幅重构。固定到特定提交确保了所报告发现的可重现性,但意味着分类法是一个快照,而非实时描述。提交哈希列于 Appendix B 中,以便读者评估每个智能体自分析以来发生了多大变化。
第二,某些维度之间的独立性可能不如分类法所暗示的那样强。Section 5.3 指出,循环驱动者与检索策略存在相关性:脚手架驱动的智能体倾向于投资检索基础设施,而 LLM 驱动的智能体则依赖通用工具。其他维度之间可能存在类似的相关性 (例如,工具发现策略与工具数量之间,或状态管理与上下文压缩之间)。分类法将各维度呈现为独立的轴,但实际上它们构成一个相互依赖的设计空间,在一个维度上的选择会约束其他维度的选项。Section 4.4 的跨维度主题捕获了其中一些相互依赖性,但对维度交互的完整分析超出了本研究的范围。
6.3 外部效度
三个威胁限制了研究发现的可推广性。
第一,语料库仅限于具有可读源代码的开源智能体 (Section 3.1)。专有编码智能体 (GitHub Copilot Workspace、Cursor 的 AI 后端、Windsurf) 以及源代码经过编译或混淆的智能体 (Claude Code) 被排除在外,因为其脚手架代码不可公开检视。这引入了幸存者偏差:开源智能体可能在业务约束、专有模型访问或不同的优化目标 (用户体验与基准测试分数) 驱动的设计选择上,与专有智能体存在系统性差异。因此,分类法应被理解为描述开源设计空间,而非编码智能体的完整设计空间。
第二,13 个智能体的语料库虽然涵盖了一系列架构策略,但并非穷尽性的。分析期后发布的智能体或不符合纳入标准的智能体可能展现出分类法中未涵盖的架构模式。本研究追求的是分析性可推广性 61 (维度和频谱应当可用于表征新智能体),而非统计性可推广性 (智能体在维度位置上的分布并未声称代表任何总体)。随着生态系统的演进,新的维度和现有维度上的新位置都可能出现。
第三,语料库以针对 Python 语言代码仓库的智能体为主,这主要是因为 SWE-bench (主导性的评估基准测试) 仅使用 Python 项目。为多语言或非 Python 生态系统设计的智能体可能面临不同的架构约束 (例如,不同的 AST 解析需求、不同的构建和测试工具链,或不同的依赖解析模式),这可能产生此处未观察到的架构差异 4 28。Prometheus 的 20 种语言 tree-sitter 支持和 SWE-agent 的语言无关的基于 shell 的方法表明,一些智能体已经在应对这一局限,但本分析并未系统评估架构选择如何随目标语言而变化。
6.4 可靠性
主要的可靠性威胁是可重现性。完整的分析模板 (Section 3.4) 和固定的提交哈希 (Appendix B) 使第二位分析者能够得出大体相似的观察结果,尽管分类判断 (将智能体置于连续频谱上的何处) 可能存在差异。完整的分析文档支持独立审查。
次要关切是,静态源代码分析会遗漏运行时行为。某些架构特性 (实践中的 MCP 工具发现、Moatless Tools 的可插拔选择器等可配置特性是否在典型部署中被使用) 可能只在运行时才可见。分类法描述的是架构能力,而非观察到的运行时行为。
语料库也高度集中于 Python 实现的智能体 (13 个中有 10 个);三个 TypeScript 智能体 (Cline、Gemini CLI、OpenCode) 可能使用了以 Python 为导向的分析框架不太敏感的语言习惯用法 (事件驱动架构、模块系统)。分析模板被设计为语言无关的,但分析者在注意力上的细微偏差无法排除。
最后,贯穿全文使用的 CLI/SWE-bench 类别划分 (Table 1) 是一种简化。有些智能体跨越类别:OpenHands 被归类为 SWE-bench,但也被广泛用作交互式开发工具,若干 SWE-bench 智能体也可以交互式运行。这一划分是描述性的 (用于对设计选择提供背景说明) 而非分析性的 (不作为分类法的一个维度),但读者不应将其解读为一个刚性边界。
7 结论
本文提出了一套针对 13 个开源编码智能体脚手架的源代码级架构分类法,组织为三个层次 (控制架构、工具与环境接口、资源管理) 和 12 个维度。每一项分类主张都建立在固定提交处克隆仓库的文件路径和行号之上,提供了一个可独立验证的证据基础,并可随生态系统的演进而扩展。
分析得出三项发现。第一,脚手架架构更适合被表征为沿连续频谱的位置,而非离散类型的实例。控制策略的范围从固定流水线到完整的蒙特卡洛树搜索 (Monte Carlo Tree Search);工具数量从 0 到 37;上下文压缩跨越七种不同策略;状态管理从破坏性覆写到事件溯源。此前基于能力的分类法将智能体归类为 “工具使用型” 或 “规划型”,无法区分在这些维度上存在根本差异的系统。第二,控制架构底层的循环原语 (ReAct、生成-测试-修复、计划-执行、多次重试、树搜索) 作为可组合的构建块发挥作用:13 个智能体中有 11 个叠加了多种原语,而非依赖单一控制结构。这种可组合性意味着设计空间是组合式的而非类别式的,给一个系统贴上单一架构标签会掩盖区分它们的设计决策。第三,各维度本身呈现出一种模式:在外部约束的选择上趋同 (工具能力类别、编辑格式、执行隔离),在开放设计问题上分化 (上下文压缩、状态管理、多模型路由),这指示了设计空间的哪些部分已经稳定,哪些部分最需要研究投入。
基于该分类法,可以展开以下几个方向的未来工作。最直接的扩展是受控实验:12 个维度识别了可以在保持其他变量不变的情况下单独隔离的具体架构变量。例如,比较工具集相同但循环策略不同的智能体,或循环相同但压缩策略不同的智能体,同时保持模型不变,这将使性能差异能够因果归因于脚手架设计,而非当前基准测试比较无法解开的模型或配置混淆因素 (Section 5.5)。分类法提供了变量;设计实验是下一步。
第二个方向是纵向分析。分类法描述的是 13 个智能体在固定提交处的快照。在后续提交处重复分析,将揭示脚手架架构如何演进:趋同的维度是否继续趋同,分化的维度是否趋于稳定,以及随着生态系统成熟是否出现新的维度。固定提交的方法论使这种纵向比较变得简便。
第三,将语料库扩展到专有智能体 (当架构细节通过文档或逆向工程变得可用时) 以及针对 Python 以外语言的智能体,可以检验所观察频谱的可推广性 (Section 6)。维度框架被设计为语言和平台无关的,但此处观察到的具体位置是否可推广到不同生态系统,仍然是一个开放问题。
最后,分类法使此前工作所呼吁 11 但因缺乏架构文档而无法实现的架构感知评估指标成为可能。将具体的维度位置 (循环策略、压缩方法、工具集设计) 与可观测结果 (任务成功率、Token 成本、轨迹长度) 关联起来,将推动该领域从系统级排行榜迈向对编码智能体有效性的组件级理解。
致谢
本文中的研究发现和观点仅代表作者本人,不一定代表华为的立场。此外,研究结果不以任何方式反映华为软件产品的质量。
References
Appendix A 候选智能体语料库
Table 14 列出了本研究考虑的全部 22 个候选智能体,以及每个被排除智能体未满足的纳入标准。三项纳入标准在 Section 3.1 中定义。
Table 14: 完整候选池。智能体按处置结果分组:13 个纳入的智能体在前 (排列顺序同 Table 1),其后是按排除标准分组的 9 个被排除智能体。
| 智能体 | 处置 | 排除理由 |
| Gemini CLI | 纳入 | — |
| OpenHands | 纳入 | — |
| Aider | 纳入 | — |
| Cline | 纳入 | — |
| SWE-agent | 纳入 | — |
| Codex CLI | 纳入 | — |
| OpenCode | 纳入 | — |
| Agentless | 纳入 | — |
| AutoCodeRover | 纳入 | — |
| Moatless Tools | 纳入 | — |
| Prometheus | 纳入 | — |
| DARS-Agent | 纳入 | — |
| mini-swe-agent | 纳入 | — |
| 排除: 非编码专用 (标准 1) | ||
| Open Interpreter | 排除 | 通用代码执行框架。无代码库导航、补丁应用或 git 集成。 |
| Deep Agents | 排除 | 通用 LangGraph 智能体 Harness。无 git 集成、无 diff/补丁应用、无测试运行器、无 AST 工具。 |
| MetaGPT | 排除 | 多智能体编排框架;分析单元是智能体协调,而非单个脚手架架构。 |
| CrewAI | 排除 | 通用多智能体编排平台;与 MetaGPT 排除理由相同。 |
| 排除: 无可读源代码 (标准 2) | ||
| Claude Code | 排除 | 以编译后的 npm 二进制文件分发;无公开源代码仓库。 |
| MASAI | 排除 | 仓库仅包含链接到论文的 README;未发布实现代码。 |
| Copilot Workspace | 排除 | 专有产品;脚手架代码不可公开检视。 |
| Cursor | 排除 | 商业 AI 代码编辑器;脚手架代码不可公开检视。 |
| Windsurf | 排除 | 商业 AI 代码编辑器;脚手架代码不可公开检视。 |
Table 15 列出了每个被分析智能体的仓库 URL 和固定的提交哈希。Section 4 中引用的所有文件路径和行号均指向这些特定提交。读者可以克隆每个仓库并切换到所列提交,以复现或验证本文中的任何论断。
Table 15: 全部 13 个被分析智能体的固定提交哈希。提交按与 Table 1 相同的顺序排列。
| 智能体 | 提交哈希 | 仓库 URL |
|---|---|---|
| Gemini CLI | dd8d4c98b3 | https://github.com/google-gemini/gemini-cli |
| OpenHands | 922e3a2431 | https://github.com/OpenHands/OpenHands |
| Aider | 861a1e4d15 | https://github.com/Aider-AI/aider |
| Cline | 71e312e92a | https://github.com/cline/cline |
| SWE-agent | e72a7e4660 | https://github.com/SWE-agent/SWE-agent |
| Codex CLI | 9dba7337f2 | https://github.com/openai/codex |
| OpenCode | f54abe58cf | https://github.com/anomalyco/opencode |
| Agentless | 5ce5888b9f | https://github.com/OpenAutoCoder/Agentless |
| AutoCodeRover | 585d3e639a | https://github.com/AutoCodeRoverSG/auto-code-rover |
| Moatless Tools | 011ead57a5 | https://github.com/aorwall/moatless-tools |
| Prometheus | b1c722be02 | https://github.com/EuniAI/Prometheus |
| DARS-Agent | eab35168a9 | https://github.com/vaibhavagg303/DARS-Agent |
| mini-swe-agent | 6f1b196616 | https://github.com/SWE-agent/mini-swe-agent |
Footnotes
-
Aider: AI pair programming in your terminal. Note: https://aider.chat/ Cited by: §1, §2.3, Table 1. ↩ ↩2 ↩3
-
SWE-agent: agent-computer interfaces enable automated software engineering. In Advances in Neural Information Processing Systems (NeurIPS), Cited by: §1, §2.3, §3.1, Table 1, §4.2.2, §5.4. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
OpenHands: an open platform for AI software developers as generalist agents. In International Conference on Learning Representations (ICLR), Note: arXiv preprint arXiv:2407.16741 Cited by: §1, §2.3, Table 1. ↩ ↩2 ↩3
-
SWE-bench: can language models resolve real-world GitHub issues?. In International Conference on Learning Representations (ICLR), Cited by: §1, §2.4, §6.3. ↩ ↩2 ↩3 ↩4
-
What’s in a GitHub star? understanding repository starring practices in a social coding platform. Journal of Systems and Software 146, pp. 112–129. Cited by: §1, §3.1, Table 1. ↩ ↩2 ↩3
-
Building AI coding agents for the terminal: scaffolding, harness, context engineering, and lessons learned. arXiv preprint arXiv:2603.05344. Cited by: §1, §1, §2.3, §3.2. ↩ ↩2 ↩3 ↩4
-
The landscape of emerging AI agent architectures for reasoning, planning, and tool calling: a survey. arXiv preprint arXiv:2404.11584. Cited by: §1, §2.1, §3.2, §5.1. ↩ ↩2 ↩3 ↩4 ↩5
-
Architectures for building agentic AI. arXiv preprint arXiv:2512.09458. Cited by: §1, §2.1, §5.1. ↩ ↩2 ↩3
-
Understanding code agent behaviour: an empirical study of success and failure trajectories. In Proceedings of the 48th IEEE/ACM International Conference on Software Engineering (ICSE), Note: arXiv preprint arXiv:2511.00197 Cited by: §1, §1, §2.2, §2.2, §5.3. ↩ ↩2 ↩3 ↩4 ↩5
-
Understanding software engineering agents through the lens of traceability: an empirical study. arXiv preprint arXiv:2506.08311. Cited by: §1, §2.2. ↩ ↩2
-
Toward architecture-aware evaluation metrics for LLM agents. In Proceedings of the 5th IEEE/ACM International Conference on AI Engineering – Software Engineering for AI (CAIN), Note: arXiv preprint arXiv:2601.19583 Cited by: §1, §2.4, §5.3, §7. ↩ ↩2 ↩3 ↩4
-
Demystifying LLM-based software engineering agents. Proceedings of the ACM on Software Engineering 2, pp. 801–824. Note: FSE 2025. ACM SIGSOFT Distinguished Paper Award Cited by: §1, §2.3, Table 1. ↩ ↩2 ↩3
-
Moatless Tools. Note: https://github.com/aorwall/moatless-tools Cited by: §1, Table 1. ↩ ↩2
-
A survey on large language models for software engineering. Science China Information Sciences 69, pp. 141102. External Links: Document Cited by: §2.1, §3.1. ↩ ↩2
-
Toolformer: language models can teach themselves to use tools. In Advances in Neural Information Processing Systems (NeurIPS), Cited by: §2.1. ↩
-
Gorilla: large language model connected with massive APIs. In Advances in Neural Information Processing Systems (NeurIPS), Cited by: §2.1. ↩
-
ReAct: synergizing reasoning and acting in language models. In International Conference on Learning Representations (ICLR), Cited by: §2.1. ↩
-
Reflexion: language agents with verbal reinforcement learning. In Advances in Neural Information Processing Systems (NeurIPS), Cited by: §2.1, §5.4. ↩ ↩2
-
Prometheus: towards long-horizon codebase navigation for repository-level problem solving. arXiv preprint arXiv:2507.19942. Cited by: §2.2, Table 1. ↩ ↩2
-
Understanding software engineering agents: a study of thought-action-result trajectories. In Proceedings of the 40th IEEE/ACM International Conference on Automated Software Engineering (ASE), Note: arXiv preprint arXiv:2506.18824 Cited by: §2.2, §2.2. ↩ ↩2
-
RepairAgent: an autonomous, LLM-based agent for program repair. In Proceedings of the 47th IEEE/ACM International Conference on Software Engineering (ICSE), pp. 2188–2200. Cited by: §2.2. ↩
-
SWE-Effi: re-evaluating software AI agent system effectiveness under resource constraints. arXiv preprint arXiv:2509.09853. Cited by: §2.2, §2.4, §5.2. ↩ ↩2 ↩3
-
DARS: dynamic action re-sampling to enhance coding agent performance by adaptive tree traversal. In Proceedings of the 63rd Annual Meeting of the Association for Computational Linguistics (ACL), Cited by: §2.3, Table 1. ↩ ↩2
-
MASAI: modular architecture for software-engineering AI agents. arXiv preprint arXiv:2406.11638. Cited by: §2.3, item 2. ↩ ↩2
-
AutoCodeRover: autonomous program improvement. In Proceedings of the 33rd ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA), Cited by: §2.3, Table 1. ↩ ↩2
-
Configuring agentic AI coding tools: an exploratory study. arXiv preprint arXiv:2602.14690. Cited by: §2.3, §4.3.4. ↩ ↩2
-
Saving SWE-Bench: a benchmark mutation approach for realistic agent evaluation. In Proceedings of the 5th IEEE/ACM International Conference on AI Engineering – Software Engineering for AI (CAIN), Note: arXiv preprint arXiv:2510.08996 Cited by: §2.4, §3.5. ↩ ↩2
-
SWE-Compass: towards unified evaluation of agentic coding abilities for large language models. arXiv preprint arXiv:2511.05459. Cited by: §2.4, §6.3. ↩ ↩2 ↩3
-
SWE-Bench Pro: can AI agents solve long-horizon software engineering tasks?. arXiv preprint arXiv:2509.16941. Cited by: §2.4. ↩
-
Rethinking the value of agent-generated tests for LLM-based software engineering agents. arXiv preprint arXiv:2602.07900. Cited by: §2.4. ↩
-
Open Interpreter. Note: https://github.com/OpenInterpreter/open-interpreter Cited by: item 1. ↩
-
Deep Agents. Note: https://github.com/langchain-ai/deepagents Cited by: item 1. ↩
-
MetaGPT: meta programming for a multi-agent collaborative framework. In International Conference on Learning Representations (ICLR), Cited by: item 1. ↩
-
CrewAI. Note: https://github.com/crewAIInc/crewAI Cited by: item 1. ↩
-
Claude Code. Note: https://github.com/anthropics/claude-code The open-source repository contains plugins, examples, and documentation, but the core agent source is distributed as compiled TypeScript bundles in the npm package. Cited by: item 2. ↩
-
mini-swe-agent. Note: https://github.com/SWE-agent/mini-swe-agent Cited by: §3.1, Table 1. ↩ ↩2
-
OpenCode. Note: https://github.com/anomalyco/opencode Cited by: Table 1. ↩
-
Gemini CLI. Note: https://github.com/google-gemini/gemini-cli Cited by: Table 1. ↩
-
Codex CLI. Note: https://github.com/openai/codex Cited by: Table 1. ↩
-
Cline. Note: https://github.com/cline/cline Cited by: Table 1, §4.4.5. ↩ ↩2
-
Basics of qualitative research: techniques and procedures for developing grounded theory. 2nd edition, SAGE Publications. Cited by: §3.2, §6.1. ↩ ↩2
-
The coding manual for qualitative researchers. 4th edition, SAGE Publications. Cited by: §3.2, §3.2. ↩ ↩2
-
Guidelines for conducting and reporting case study research in software engineering. Empirical Software Engineering 14 (2), pp. 131–164. Cited by: §3.4, §6.1, §6. ↩ ↩2 ↩3
-
LangGraph. Note: https://github.com/langchain-ai/langgraph Cited by: Table 2. ↩
-
A survey of Monte Carlo tree search methods. IEEE Transactions on Computational Intelligence and AI in Games 4 (1), pp. 1–43. Cited by: §4.1.1. ↩
-
Mastering the game of Go with deep neural networks and tree search. Nature 529 (7587), pp. 484–489. Cited by: §4.1.1. ↩
-
The BrowserGym ecosystem for web agent research. arXiv preprint arXiv:2412.05467. Cited by: §4.2.1. ↩
-
Billion-scale similarity search with GPUs. IEEE Transactions on Big Data 7 (3), pp. 535–547. Cited by: Table 8. ↩
-
Neo4j graph database. Note: https://neo4j.com/ Cited by: §4.2.4. ↩
-
The anatomy of a large-scale hypertextual web search engine. Computer Networks and ISDN Systems 30 (1–7), pp. 107–117. Cited by: §4.2.4. ↩
-
Tree-sitter: an incremental parsing system for programming tools. Note: https://tree-sitter.github.io/tree-sitter/ Cited by: §4.2.4. ↩
-
A survey on software fault localization. IEEE Transactions on Software Engineering 42 (8), pp. 707–740. Cited by: §4.2.4. ↩
-
On the accuracy of spectrum-based fault localization. In Testing: Academic and Industrial Conference Practice and Research Techniques (TAIC PART), pp. 89–98. Cited by: §4.2.4. ↩
-
A survey of learning-based automated program repair. ACM Transactions on Software Engineering and Methodology 33 (2), pp. 1–69. Cited by: §4.2.4. ↩
-
Bubblewrap: unprivileged sandboxing tool. Note: https://github.com/containers/bubblewrap Cited by: §4.2.5. ↩
-
Landlock LSM: toward unprivileged sandboxing. In Linux Security Summit, Note: https://landlock.io/ Cited by: §4.2.5. ↩
-
Gemma: open models based on Gemini research and technology. arXiv preprint arXiv:2403.08295. Cited by: §4.3.3. ↩
-
PEP 544 – protocols: structural subtyping (static duck typing). Note: https://peps.python.org/pep-0544/ Cited by: §4.4.4. ↩
-
Model Context Protocol. Note: https://modelcontextprotocol.io/ Open specification for connecting AI assistants to external tools and data sources Cited by: §5.6. ↩
-
Case study research and applications: design and methods. 6th edition, SAGE Publications. Cited by: §6.3. ↩