原文地址:Components of A Coding Agent,by Sebastian Raschka, on 2026-04-04
Coding Agent的组成:Coding Agent如何借助工具、记忆与 repo 上下文,让 LLM 在实际应用中发挥更优效果
在本文中,我将全面讲解 coding agents 与 agent harnesses 的设计体系:它们的定义、运行机制,以及各个模块在实践中的协作逻辑。读过我《Build a Large Language Model (From Scratch)》和《Build a Large Reasoning Model (From Scratch)》的读者经常问及代理相关的问题,因此我打算写一篇可供查阅的系统参考文章。
更宽泛地说,代理已经成为 LLM 领域的核心议题之一:近期 LLM 系统的实用化突破,往往不只是模型本身的迭代,更多在于应用方式的升级。在绝大多数真实业务场景中,外围系统(工具调用、上下文管理、记忆机制等)的价值,和模型本身同等重要。这也解释了为什么 Claude Code、Codex 这类产品,比起在普通聊天界面中使用同款模型,实际体验会明显更强。
本文会拆解 coding agent 的六大核心构建模块。
Claude Code、Codex CLI 与其他Coding Agent
你或许已经熟悉 Claude Code 或者 Codex CLI。简单来说,它们本质上是具备代理能力的编码工具:在 LLM 之外包裹了一层应用层,也就是所谓的 agentic harness(代理式框架),从而让编码任务更高效、体验更顺滑。

图 1:Claude Code CLI、Codex CLI,以及我开发的 mini-coding-agent(https://github.com/rasbt/mini-coding-agent)
coding agents 是面向软件开发场景定制的系统,其核心竞争力不止来自模型选型,更来自外围系统的能力,包括 repo 上下文感知、工具设计、prompt 缓存稳定性、记忆机制,以及长会话连续性。
这个区分非常关键:当我们谈论 LLM 的编码能力时,人们常常把模型本身、推理行为和代理产品混为一谈。在深入讲解 coding agent 的技术细节之前,我先简单梳理 LLM、推理模型(reasoning model)和代理(agent)这几个概念的差异。
LLM、推理模型与代理的关系
LLM 是核心的下一词元预测模型。推理模型本质上仍属于 LLM,但它通常经过专项训练或 prompt 优化,会在生成过程中投入更多算力做中间推导、自我校验,或是对候选答案进行检索。
代理(Agent) 则是叠加在模型之上的一层系统,可以理解为围绕模型的控制循环。给定目标后,代理层(或框架)会自主决定下一步检查什么、调用哪些工具、如何更新状态,以及何时终止任务。
我们可以用一个粗略的类比来理解三者关系:LLM 是发动机,推理模型是升级后的高性能发动机(动力更强,但运行成本也更高),而 agent harness 则是让发动机真正发挥作用的整车系统。这个类比并不完全严谨 —— 常规 LLM 和推理 LLM 本身也可以独立使用(在聊天界面或 Python 会话中),但希望能帮你理解核心逻辑。

图 2:常规 LLM、推理 LLM(或推理模型),以及包裹在 agent harness 中的 LLM 三者的关系
换句话说,代理是在特定环境中反复调用模型的闭环系统。
简言之,我们可以这样总结几个概念:
-
LLM:原始模型本体
-
Reasoning model(推理模型):经过优化的 LLM,擅长输出中间推理链路,并且具备更强的自我校验能力
-
Agent(代理):结合模型、工具、记忆和环境反馈来完成任务的循环系统
-
Agent harness(代理框架):代理外围的软件支架,负责管理上下文、工具调用、prompt、状态和控制流
-
Coding harness(编码框架):agent harness 的一个特例,是面向软件工程任务的专项框架,负责管理代码上下文、工具、执行过程和迭代反馈
如上文所述,在代理和编码工具领域,agent harness 和(agentic)coding harness 是两个常用术语。coding harness 是围绕模型的软件支架,帮助模型高效地编写和修改代码;而 agent harness 范围更广,不局限于编码场景(比如 OpenClaw 就属于这类)。Codex 和 Claude Code 都可以归为 coding harness。
当然,能力更强的 LLM 能为推理模型(需要额外训练)提供更好的基础,而 harness 则能进一步释放推理模型的潜力。
诚然,LLM 和推理模型本身也能独立完成编码任务(不需要 harness),但编码工作不只是下一词元生成。很大一部分工作在于 repo 导航、代码搜索、函数查找、diff 应用、测试执行、错误排查,以及把所有相关信息维持在上下文中。(程序员都知道这是很费脑力的工作,这也是为什么我们编码时不喜欢被打断的原因 :))

图 3:一个 coding harness 包含三层:模型家族、代理循环和运行时支撑。模型提供 “引擎”,代理循环驱动迭代式问题求解,运行时支撑提供底层设施。在循环内部,“observe(观察)” 从环境收集信息,“inspect(检视)” 分析信息,“choose(决策)” 选择下一步行动,“act(执行)” 落地操作。
这里的核心结论是:优秀的 coding harness 能让推理模型和非推理模型的表现,都远胜于在普通聊天框中的表现,核心原因就是它能高效地管理上下文等关键要素。
编码框架(Coding Harness)
上一节提到,我们所说的 harness,通常指模型外围的软件层,负责组装 prompt、开放工具能力、追踪文件状态、应用代码修改、运行命令、管理权限、缓存稳定前缀、存储记忆等等。
如今,相比直接给模型发 prompt 或是使用网页聊天界面(更接近 “上传文件聊天” 的模式),这一层软件在很大程度上决定了用户体验。
在我看来,如今主流 LLM 的基础版本能力都很接近(比如 GPT-5.4、Opus 4.6、GLM-5 这些模型的原生版本),harness 往往成为区分不同 LLM 实际表现的关键因素。
这是我的推测:如果把最新、能力最强的开源 LLM(比如 GLM-5)放进一套成熟的 harness 中,它的表现很可能和 Codex 中的 GPT-5.4、Claude Code 中的 Claude Opus 4.6 不相上下。当然,针对 harness 的专项后训练通常会带来额外提升。比如 OpenAI 过去就一直维护单独的 GPT-5.3 和 GPT-5.3-Codex 版本。
下一节,我将结合自己的 Mini Coding Agent(https://github.com/rasbt/mini-coding-agent),更具体地讲解 coding harness 的核心组件。

图 4:下文将讨论的 coding agent /coding harness 的主要框架特性
顺便一提,为了简化表述,本文中 “coding agent” 和 “coding harness” 两个术语会交替使用。(严格来说,agent 是模型驱动的决策循环,而 harness 是外围的软件支架,提供上下文、工具和执行支撑。)

图 5:极简但完整可运行、从零实现的 Mini Coding Agent(https://github.com/rasbt/mini-coding-agent)(纯 Python 实现)
以下就是 coding agent 的六大核心组件。你可以查看我那个极简但完整可运行的从零实现项目源码(https://github.com/rasbt/mini-coding-agent/blob/main/mini_coding_agent.py,纯 Python 实现)来获取更具体的代码示例。代码中通过注释标注了下面要讲的六大组件:
############################## #### Six Agent Components #### ############################## # 1) Live Repo Context -> WorkspaceContext # 2) Prompt Shape And Cache Reuse -> build_prefix, memory_text, prompt # 3) Structured Tools, Validation, And Permissions -> build_tools, run_tool, validate_tool, approve, parse, path, tool_* # 4) Context Reduction And Output Management -> clip, history_text # 5) Transcripts, Memory, And Resumption -> SessionStore, record, note_tool, ask, reset # 6) Delegation And Bounded Subagents -> tool_delegate
1. 实时代码仓库上下文(Live Repo Context)
这可能是最显而易见的组件,但也是最重要的组件之一。
当用户说 “修复测试用例” 或者 “实现某某功能” 时,模型需要知道自己是否在一个 Git repo 中、当前在哪个分支、哪些项目文档可能包含说明信息等等。
因为这些细节往往会决定或影响正确的操作是什么。比如,“修复测试用例” 本身不是一个完整的指令。如果代理能看到 AGENTS.md 或者项目 README,就能知道该运行哪个测试命令;如果它知道 repo 的根目录和结构,就能去正确的位置查找,而不是靠猜测。
此外,git 分支、状态和提交记录也能提供更多上下文,帮助判断当前正在进行哪些改动、应该聚焦在哪里。

图 6:agent harness 首先会生成一份精简的工作区摘要,和用户请求结合在一起,为模型提供额外的项目上下文。
核心要点是:coding agent 在开始工作前,会预先收集信息(作为工作区摘要的 “稳定事实”),这样它不会每次响应 prompt 都从零开始、毫无上下文。
2. Prompt 结构与缓存复用
当代理获取了 repo 视图后,下一个问题就是如何把这些信息喂给模型。上一张图展示了简化的形式(“组合 prompt:前缀 + 请求”),但实际上,如果每次用户查询都重新拼接、重新处理工作区摘要,会相当浪费算力。
也就是说,编码会话是重复性的:代理规则通常保持不变,工具描述通常也不变,甚至连工作区摘要大部分时候也基本一致。真正变化的通常是最新的用户请求、近期的对话记录,可能还有短期记忆。
“智能” 的运行时不会每一轮都把所有内容重建成一个庞大的、无差别的 prompt,如下图所示。

图 7:agent harness 构建一个稳定的 prompt 前缀,加入变化的会话状态,再把组合后的 prompt 喂给模型。
这一部分和第 1 点的主要区别是:第 1 点侧重收集 repo 事实,而这里关注的是如何高效地打包和缓存这些事实,供多次模型调用使用。
“稳定 prompt 前缀” 的意思是,其中包含的信息不会频繁变动,通常包括通用指令、工具描述和工作区摘要。如果没有重要变化,我们没必要每次交互都从头重建它,浪费算力。
其他组件则更新得更频繁(通常每轮都更新),包括短期记忆、近期对话记录和最新的用户请求。
简而言之,“稳定 prompt 前缀” 的缓存逻辑就是:智能运行时会尽量复用这部分内容。
3. 工具访问与调用
到了工具访问与调用这一步,体验就开始不像聊天,而更像真正的代理了。
普通的模型可以用自然语言建议命令,但处在 coding harness 中的 LLM,应该做更精准、更有用的事 —— 真正执行命令并获取结果(而不是我们手动敲命令再把结果粘贴回聊天框)。
但框架通常不会让模型随意自创语法,而是提供一份预定义的、有名称的工具列表,包含明确的输入和边界。(当然,类似 Python subprocess.call 这样的能力也可以包含在内,这样代理也能执行各种 shell 命令。)
工具调用的流程如下图所示。

图 8:模型输出结构化动作,harness 校验动作,按需请求用户批准,执行操作,再把受限的结果反馈回循环中。
为了说明这一点,下面是我的 Mini Coding Agent 中用户看到的工具调用示例。(它不像 Claude Code 或 Codex 那么美观,因为它非常极简,只用纯 Python 实现,没有外部依赖。)

图 9:Mini Coding Agent 中工具调用审批请求的示例
在这里,模型必须选择 harness 能识别的动作,比如列出文件、读取文件、搜索、运行 shell 命令、写入文件等等。同时,它提供的参数格式必须能被 harness 校验通过。
因此当模型请求执行某个操作时,运行时可以介入并做程序化检查,比如:
-
“这是已知的工具吗?”
-
“参数合法吗?”
-
“这个操作需要用户批准吗?”
-
“请求的路径是否在工作区范围内?”
只有这些检查都通过后,才会真正执行操作。
虽然运行 coding agents 本身存在一定风险,但 harness 的校验机制也提升了可靠性,因为模型不会执行完全任意的命令。
此外,除了拒绝格式错误的操作和设置审批门控,还可以通过校验文件路径,把文件访问限制在 repo 内部。
从某种意义上说,harness 限制了模型的自由度,但同时也提升了实用性。
4. 最小化上下文膨胀
上下文膨胀(context bloat)不是 coding agents 独有的问题,而是所有 LLM 都面临的共性问题。诚然,如今 LLM 支持的上下文长度越来越长(我最近也写过一篇文章,讲解让长上下文在算力上更可行的注意力变体:https://magazine.sebastianraschka.com/p/visual-attention-variants),但长上下文依然成本高昂,而且如果包含大量无关信息,还会引入额外噪声。
coding agents 在多轮对话中比普通 LLM 更容易出现上下文膨胀,因为会反复读取文件、产生冗长的工具输出、日志等等。
如果运行时把所有内容都完整保留,很快就会耗尽可用的上下文 token。因此,优秀的 coding harness 通常在处理上下文膨胀方面做得很精细,不止是像普通聊天界面那样简单截断或概括信息。
从概念上讲,coding agents 中的上下文压缩机制大致如下图所示。具体来说,我们把视角放大到上一节图 8 中的 clip(截断)环节。

图 10:长输出会被截断,重复的旧文件读取会被去重,对话记录在放回 prompt 前会被压缩。
一个极简的 harness 至少会采用两种压缩策略来应对这个问题。
第一种是截断(clipping):缩短长文档片段、大型工具输出、记忆笔记和对话条目。换句话说,防止单条文本因为本身冗长就占用过多的 prompt 配额。
第二种策略是对话精简或摘要:把完整的会话历史压缩成更短的、可放入 prompt 的摘要。
这里的一个关键技巧是:近期事件保留更完整的信息,因为它们对当前步骤更重要;而更早的事件则更大力度地压缩,因为它们相关性更低。
此外,我们还会对较早的文件读取结果去重,避免模型因为会话中多次读取同一个文件,就反复看到相同的文件内容。
总的来说,我认为这是优秀 coding agent 设计中最被低估、也最枯燥的部分之一。很多表面上的 “模型质量” 差异,本质上其实是上下文质量的差异。
5. 结构化会话记忆
实际上,这里讲的六大核心概念是高度交织的,不同章节和图表从不同侧重点或粒度对它们进行了讲解。上一节我们讲了 prompt 阶段的历史使用,以及如何构建精简的对话记录,核心问题是:下一轮调用模型时,应该把多少历史信息放回去?因此重点在于压缩、截断、去重和时效性。
而本节的结构化会话记忆,关注的是历史信息在存储层面的结构。核心问题是:代理会长期保存哪些内容作为永久记录?因此重点在于:运行时会保存一份完整的对话记录(full transcript)作为持久化状态,同时还有一个更轻量的记忆层 —— 体量更小,会被修改和压缩,而不是简单追加内容。
总结来说,coding agent 至少把状态分成两层:
-
工作记忆(working memory):代理显式维护的精简状态
-
完整对话记录(full transcript):涵盖所有用户请求、工具输出和 LLM 响应

图 11:新事件会追加到完整对话记录中,同时也会被摘要更新到工作记忆里。磁盘上的会话文件通常以 JSON 格式存储。
上图展示了两类主要的会话文件:完整对话记录和工作记忆,它们通常以 JSON 文件形式存在磁盘上。如前所述,完整对话记录存储全部历史,关闭代理后可以恢复会话;工作记忆则更像是提炼后的版本,保存当前最重要的信息,和精简对话记录有一定关联。
但精简对话记录和工作记忆的作用略有不同。精简对话记录用于重建 prompt,目的是给模型提供近期历史的压缩视图,让它不用每轮都看完整对话就能继续交流;工作记忆则更偏向任务连续性,目的是跨轮次维护一小份显式的关键信息摘要,比如当前任务、重要文件和近期记录。
按照上图的步骤 4,最新的用户请求,加上 LLM 响应和工具输出,会作为 “新事件” 同时记录到完整对话记录和工作记忆中,进入下一轮循环(图中没有画出,以避免画面杂乱)。
6. 基于受限子代理的任务委派
当代理具备了工具和状态之后,下一个实用的能力就是任务委派(delegation)。
原因在于,它可以把部分工作拆分成子任务,通过 subagents 并行处理,加快主任务的进度。比如,主代理可能正在处理某项任务,但同时还需要解答一个侧边问题 —— 比如某个符号在哪个文件中定义、配置项是什么意思、或者某个测试为什么失败。把这类问题拆成一个受限的子任务会更高效,而不是让一个循环同时处理所有工作。
(在我的 mini coding agent 中,实现方式更简单,子代理仍然同步运行,但核心思路是一致的。)
子代理只有继承了足够的上下文才能真正发挥作用。但如果不加限制,就会出现多个代理重复工作、操作同一个文件,或者不断衍生更多子代理等问题。
因此,设计的难点不只是如何生成子代理,还有如何约束它。

图 12:子代理继承足够的上下文以保证可用性,但运行在比主代理更严格的边界内。
这里的诀窍是:子代理继承足够的上下文来完成工作,但同时受到约束(比如只读模式、递归深度限制)。
Claude Code 很早就支持 subagents,Codex 近期也加入了该功能。Codex 一般不会把子代理强制设为只读模式,它们通常会继承主代理的大部分沙箱权限和审批设置。因此,边界更多体现在任务范围、上下文和深度上。
组件总结
上文讲解了 coding agent 的核心组件。如前所述,它们在实现中或多或少是深度交织的。但我希望逐一拆解的方式,能帮助大家建立对 coding harness 工作原理的整体认知,理解为什么相比简单的多轮聊天,它们能让 LLM 变得更实用。

图 13:前文讨论的 coding harness 的六大核心特性
如果你想看到这些组件用简洁、极简的 Python 代码实现,可以看看我的项目:https://github.com/rasbt/mini-coding-agent。
和 OpenClaw 相比有什么不同?
OpenClaw 是一个很有意思的参照对象,但它和 coding agent 不属于完全同类的系统。
OpenClaw 更偏向一个本地通用代理平台,也具备编码能力,而不是专门的(终端型)编码助手。
它和 coding harness 仍有不少重合之处:
-
它保存 JSONL 格式的会话文件,包含对话压缩和会话管理能力
-
它可以生成助手会话和 subagents
-
等等
不过如前所述,两者的侧重点不同。coding agents 是为在仓库中工作的用户优化的,让编码助手可以高效地检查文件、修改代码、运行本地工具。而 OpenClaw 更优化于跨聊天、频道和工作区运行多个长生命周期的本地代理,编码只是其中一项重要的工作负载。
最后,我很高兴地告诉大家,《Build A Reasoning Model (From Scratch)》已经完成撰写,所有章节都已进入早期访问阶段。出版社目前正在排版,预计今年夏天正式面世。
这大概是我迄今为止最有野心的一本书。我花了大约一年半时间撰写,其中包含了大量实验。无论是投入的时间、精力还是打磨的精细度,它都算得上是我最用心的一本书,希望你们会喜欢。
《Build a Reasoning Model (From Scratch)》购买链接:https://mng.bz/Nwr7 和 https://amzn.to/4aAKiFY
本书核心主题包括:
-
推理模型评估
-
推理时算力扩展
-
自我优化
-
强化学习
-
模型蒸馏
如今关于 LLM 中的 “推理” 有很多讨论,而我认为理解其真正含义的最佳方式,就是从零开始实现一个推理模型!
https://amzn.to/4aAKiFY(预售)
https://mng.bz/Nwr7(全书电子版,排版前版本,共 528 页)