大模型应用:代码智能体工程化实践
营长 Lv3

封面图

背景:IDE 简史

IDE 是开发者的工作环境。它将编辑器、编译器、调试器以及各类开发工具整合到一个统一的空间中。

在 IDE 出现之前的远古时期,开发环境是由一个个零散的工具组成。编辑、编译、链接、调试分别发生在不同程序中,开发者需要自己完成拼接。

这一局面在 Turbo Pascal(1983) 出现后发生了改变。Turbo Pascal 将编辑器、编译器和链接器整合为一个整体,面向 Pascal 语言提供端到端的开发体验。通过减少工具切换,显著提升了开发效率。

随后是 Microsoft Visual Studio(1997)。Visual Studio 引入了更完整的调试体系和项目系统,其核心模块 IntelliSense 可以基于语义提供代码补全和提示。这标志着 IDE 开始理解代码结构。

进入 21 世纪,IntelliJ IDEA(2001) 将“代码理解”推进到新的层级。通过全项目索引、精确的重构能力以及跨文件的导航,IDEA 将理解的范围从“当前文件”扩展到了“整个代码库”。

Visual Studio Code(2015) 则选择了不同的方向。VS Code 保持轻核心,将语言理解通过插件机制和LSP协议外包给外部插件。这一步将代码理解能力从 IDE 中解耦了出来,IDE 开始成为一个聚合上下文的平台。

在这一分化路径上,出现了两种截然不同的演进方向。

一条路线以 Cursor(2023) 为代表。Cursor 将语言模型深度嵌入 IDE 的各个环节,从代码生成、重构到调试,IDE 本身开始参与上下文组织,并主导与模型的交互。

另一条路线则以 Zed(2023) 为代表。Zed 保持编辑器的克制定位,将“思考”通过ACP协议外包给外部智能体,将智能体从 IDE 中解耦了出来。

在这种架构下,像 Claude Code(2024) 这样的代码智能体开始脱离 IDE 本体运行,独立承担代码理解、规划与执行的职责,而 IDE 退回到“观察、编辑与呈现”的角色。

今天的代码智能体正是在这一历史背景下出现的。代码智能体的价值,最终取决于它是否能在可控可重复的流程中工作,这也引来了一个新的问题 —— 如何为代码智能体设计一套可工程化的工作流程?

上下文管理

在一场对话中,智能体会维持一个上下文窗口,并且在每次推理时会把该窗口输入到模型中。窗口的长度是有限的,并且会随时间滑动 – 新的输入不断进入,旧的内容会被挤出窗口之外(但在实践中例如系统指示及 MCP 工具的关键上下文会被保护)。模型不会看到窗口外的内容,只基于当前窗口进行生成:

窗口由多种信息共同构成:

  • 系统指示,用于定义全局行为与约束
  • 用户输入,描述当前任务目标
  • 工具调用,工具调用请求以及返回结果,一般为结构化数据
  • 智能体输出,对用户任务的答复

在不微调模型的前提下,上下文窗口是模型进行推理的唯一输入来源,直接决定输出的质量。因此,需要有一套明确的管理方法确保模型在一个正确完整长度受控信噪比足够高的上下文窗口下运行。

无管理

这里有一种朴素的做法:自由提问,并祈祷自己在反复询问中接近目标。在这个过程中,上下文完全依赖对话历史线形积累,并且按照笔者本人的经验,对话会在以下几个时刻崩溃:

  • 对话长度失控,应用开始卡顿,上下文濒临溢出
  • 对话内容失控,智能体反复道歉的同时不断给出离谱答复

失控发生时,一个补救的做法是:丢弃当前会话,重开一个新会话并在最初的提示词里加入更多的约束和指引,希望这一次能回到正轨。这种方法并没有真正解决上下文管理的问题,它只是通过反复重置上下文来掩盖上下文本身缺乏约束的事实。这种方法只适合短任务,对于复杂任务很容易使得对话走向失控。

上下文压缩

一个对上述方法的改进措施是进行上下文压缩:当上下文变得臃肿时,暂停当前对话并让智能体做一个总结:

把当前的对话总结成文档progress.md,明确最终目标、当前采用的方案、已经完成的步骤以及正在解决的问题。

随后,在新的会话开始时输入:

阅读progress.md

这种方式对上下文进行了提炼,丢弃了大量临时、过程性的信息,包括:

  • 多轮代码的修改与回滚
  • 工具返回的大段 JSON 数据
  • 各种日志

这些信息只在当下是必要的,但不需要长期存在于上下文中。最终的目标是把上下文提炼出稳定、可复用的结构化产物。不过,这种方式仍然是一种事后修正:只有在上下文变得臃肿之后,才通过总结来收拾残局。

子智能体委托

子智能体委托提供了另一种更为前置的管理策略。其核心思想是一些辅助性任务,例如文件搜索、代码理解,中间产生的细节信息并没有必要长期留存在窗口中,后续的推理也只是需要这些任务的最终结果。智能体接受到此类任务时,分裂出一个有独立上下文窗口的子智能体并把任务委托给它,子智能体完成任务后把最终结果返回到主智能体的上下文:

对种做法将这些任务的推理过程从主窗口中剥离了出来,提升了主窗口的信噪比的同时控制了总长度。

阶段化

通过阶段化工作流程,明确划分每个阶段的职责边界、输入与输出,将复杂任务拆解为 调研—规划—实现 三类基础阶段,并在阶段切换处引入人工审查,以避免决策混杂和上下文失控:

这一流程利用了上下文压缩进行阶段间的过渡。高噪声、探索性的工作被隔离在单独的上下文中,并通过子智能体委托完成。

调研

这一阶段的目标是搜集并确认事实,以建立对问题的准确理解,并输出一份调研报告。这一阶段通常涉及大量代码文件的查找、阅读与路径梳理。下文给出一份调研报告模版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# 调研报告:<调研主题>

**日期**<YYYY-MM-DD>
**调研人**:<姓名>
**关联仓库**<repo>
**分支**<branch>
**关联提交**<commit hash可选>

## 一、调研问题

简要描述本次调研要解决的问题,包括:
- 问题背景
- 具体问题
- 期望行为
- 调研目标

> 示例:
> Issue #XXXX 报告在某场景下出现 A 行为,但系统实际表现为 B,需要明确原因并确定修复位置。

## 二、结论摘要

**几条要点** 概括最终结论,包括:
1. 根因是什么
2. 为什么会发生
3. 修复是否明确,是否简单
4. 修复应放在哪一层

## 三、详细分析

### 相关模块

说明涉及到的系统模块、流程或架构层次,例如:
- 解析阶段
- 语义校验阶段
- 运行时阶段
- 配置 / DSL / AST 结构

### 行为分析

逐步说明问题是**在哪一层开始出现的**

- 哪些输入被接受了
- 哪些校验缺失或未触发
- 哪些数据被忽略 / 丢弃 / 未使用
- 最终导致的行为偏差

### 关键代码路径

列出关键文件、模块或函数,用于后续定位和修复。

```text
<模块路径>:<大致行号>
- 作用说明
- 与问题的关系
````

如有必要,可附少量关键代码片段(非完整实现)。

### 运行分析

说明:

* 哪些数据在运行时被真正使用
* 哪些结果被纳入最终判定
* 哪些结果被计算了但未生效

## 四、修复建议

### 修复位置

说明**最合理的修复层级**

### 修复思路

用自然语言描述修复策略,例如:

* 增加显式校验
* 拒绝非法用法
* 提供错误信息
* 防止静默故障

如适合,可给出伪代码或逻辑示意。

## 五、架构设计

总结本次调研对整体系统设计的启示,例如:

* 语法与语义分离是否清晰
* 校验职责是否遗漏
* 现有设计是否容易产生静默故障
* 是否符合系统的一贯设计原则

## 六、相关资料

* 关联 Issue / 设计文档
* 过往修改或讨论
* Changelog / TODO / notes

## 七、遗留问题

列出仍需进一步确认的问题,例如:

1. 是否需要补充测试用例?
2. 是否存在类似问题的其他场景?
3. 是否需要同步更新文档或规范?

规划

这一阶段的目标是把之前的理解转化成可执行的操作序列,最终输出一份技术方案。下文给出一份技术方案模版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# <功能 / 缺陷> 实现规划报告

## 一、概述

简要说明**当前存在的问题或缺失的能力**,以及**期望的正确行为**

## 二、现状分析

描述系统当前的实际行为,以及**问题产生的原因**

### 关键发现

* 涉及的核心模块或组件
* 系统目前在哪些位置接受了不合理或无效的配置 / 输入
* 这些配置在后续流程中是如何被忽略、丢失或错误处理的
* 是否存在可参考的类似实现或既有约束模式

## 三、范围约束

明确列出**不会做的事情**,用于约束实现范围,防止需求蔓延。

* 不修改语法或解析规则(如适用)
* 不调整运行时行为或执行逻辑
* 不引入新的功能支持
* 不做破坏性或不兼容的变更

## 四、实现思路

从整体上说明**采用什么方式解决问题**,以及**为什么选择这种方式**
如有可能,指出本次实现将遵循的既有模式或惯例。

## 五、核心实现

### 阶段目标

说明这一阶段完成后,系统行为将发生的变化。

### 具体改动

#### 1. <模块 / 校验器 / 组件> 增强

**文件路径**`<path/to/file>`
**改动说明**

* 新增哪些校验或逻辑判断
* 检查哪些非法或不支持的情况
* 在何处抛出错误或提示
* 错误信息应具备的清晰度和定位能力

```pseudo
遍历相关实体:
遍历其配置或属性:
如果命中非法条件:
生成明确的校验错误并标注精确位置
```

### 成功标准

#### 自动化验证

* [ ] 针对性测试通过
* [ ] 全量测试套件通过
* [ ] 静态检查 / lint 通过

#### 人工验证

* [ ] 非法用法能正确报错
* [ ] 错误信息清晰、可理解
* [ ] 报错位置准确
* [ ] 合法用法不受影响

## 六、回归测试

### 阶段目标

确保新增校验逻辑不会在未来被意外移除或回退。

### 具体改动

#### 新增测试用例

**文件路径**`<path/to/test/file>`
**改动说明**

* 构造一个明确的非法示例
* 声明期望的错误信息与位置

```text
// 非法配置示例
// 期望的错误输出与定位说明
```

### 验收标准

#### 自动化验证

* [ ] 测试被自动纳入测试套件
* [ ] 期望输出与实际一致
* [ ] 常规测试执行通过

#### 人工验证

* [ ] 错误信息符合预期
* [ ] 定位信息准确无误

## 七、测试策略

### 单元测试

* 覆盖所有非法场景
* 覆盖不同变体和边界情况

### 集成测试

* 确认无回归问题
* 原有合法行为保持不变

### 人工测试步骤

1. 构造非法配置
2. 执行校验,确认报错
3. 修正配置
4. 再次验证通过

## 八、性能影响评估

说明为什么该改动在性能上是安全的,例如:

* 数据规模预期较小
* 遍历层级有限
* 相较于现有校验逻辑,额外开销可以忽略

## 九、迁移说明

说明是否需要迁移或用户操作:

* 无需迁移(仅新增校验)
* 或说明必要的迁移步骤(如适用)

## 十、参考资料

* 原始问题 / 工单
* 调研记录或分析文档
* 相关实现或相似模式
* 对应测试或文档位置

实现

这一阶段的目标是严格执行已确认的技术方案,按照既定计划逐步落地,并在每个步骤完成后进行对应的验证。

人工审查

每个阶段都会产出对应的文档或代码,这些产出都需要经过人工审查。审查的重点会随着阶段前移而提高:越靠前的环节,其结论和决策对后续影响越大,因此审查也应越严格。

换言之,应当重文档、轻代码——前期通过对调研报告和技术方案的严格审查,尽可能消除方向性错误;一旦进入实现阶段,代码改动本身反而更偏向执行与验证,其审查成本也相对可控。

代码库优化

在引入代码智能体之后,代码库中的文档不再只有一个受众。因此,需要对代码库文档结构做有意识的拆分。

README.md

README.md 的定位是面向人类的入口文档,其目标是帮助开发者快速理解项目,常见的章节包括:

  • 项目简介
  • 快速上手指南
  • 基本使用方式
  • 贡献指南

AGENTS.md

与 README.md 相对应,AGENTS.md 的定位是面向代码智能体的入口文档,其目标是提供精确的上下文,常见的章节包括:

  • 架构介绍,列举关键模块与模块之间的职责边界
  • 构建与测试命令,明确指出标准构建方式、测试入口以及常见组合命令
  • 代码风格与约定,包括命名规范、目录约定、是否允许自动格式化等
  • 测试流程,哪些测试必须通过
  • 安全与限制,禁止修改的目录、敏感文件、外部依赖使用限制等

大部分代码智能体会约定性地读取 AGENTS.md,而不是让用户显示说明。虽然 README.md 通常也会被读取,但只有 AGENTS.md 被视为必须遵守的规则。