从 LLM 到 Coding Agent
逐层拆解一个生产级 Coding Agent 在裸 LLM API 之上做的每一件事。
序 · LLM 只是块芯片,Agent 才是整台机器
现在人人都在用 Coding Agent:你说一句“帮我把这个 bug 修了”,它自己去读文件、搜代码、改几处、跑测试、看报错、再改,最后告诉你搞定了。整个过程像有个真人在你的终端里干活。
但如果你去看它底层依赖的东西——一个 LLM 的 API——你会发现那玩意儿“什么都不会”:
- 它无状态:每次调用都是一张白纸,不记得上一句你说过什么。
- 它没有记忆:关掉这次请求,所有上下文烟消云散。
- 它不能做任何事:它只会输出文本。它读不了你的文件,跑不了命令,改不了代码。它连“现在几点”都不知道。
- 它甚至不知道自己该停在哪:给它一段话,它就续写一段话,仅此而已。
于是本专栏的核心问题只有一个:
一个只会“输出文本”的无状态函数,是怎么变成一个能自主完成复杂编程任务的 Agent 的?这中间,工程上到底做了哪些事?
一块芯片和一台机器的距离
打个比方:LLM 就像一块 CPU。CPU 很强,但一块裸芯片什么也干不了——你没法拿一块 CPU 去打字、上网、写代码。要让它变成一台能用的电脑,你还得给它配上内存、总线、硬盘、操作系统、驱动、输入输出……
Coding Agent 之于 LLM,正是整台机器之于那块芯片。模型提供“智能”,但把智能变成“能自主干活的系统”,靠的是外面这一整圈工程:
- 怎么让它能调用工具(读文件、跑命令)?
- 怎么让它自主循环,而不是问一句答一句?
- 怎么喂给它恰到好处的上下文,又不撑爆那有限的上下文窗口?
- 怎么在它跑飞、报错、被打断时优雅恢复?
- 怎么控制权限,不让它把你的机器搞坏?
- 怎么省钱省延迟,不让每次对话烧掉一杯咖啡的钱?
这些问题,每一个都不在“模型”里,而在“模型外面那一圈”。这一圈,就是本专栏要逐层拆开的东西。
本专栏的方法论:一篇文章只解决一个问题。每篇都按「这个问题的背景 → 解决方案的思路 → 落到代码的实现细节」三段式展开,力求把每个技术点揉碎讲透。我们会从“一次最朴素的 API 调用”出发,每加一篇,就往这块裸芯片上焊一个部件,直到最后拼出一台完整的机器。
路线图
专栏按“从裸 API 逐步长成完整 Agent”的顺序推进,大致分七个阶段:
第一阶段 · 起点 —— 先看清我们手里到底有什么。
- 一次 LLM API 调用到底给了你什么,又没给你什么。
第二阶段 · 让模型能做事 —— 从“输出文本”到“能操作世界”。
- 工具调用(function calling):让模型开口说“我要调用哪个工具”。
- Agent Loop:把一次性问答变成一场自主循环——这是“Agent”这个词真正的分水岭。
- 工具系统的抽象设计:一个可扩展、类型安全、自带权限的工具到底长什么样。
第三阶段 · 流式与并发 —— 让它快起来、并行起来。
- 流式处理:边生成边解析,以及增量到达的工具参数。
- 边流边执行 + 并发编排:工具块一到就派发,安全的工具并行跑。
第四阶段 · 安全与控制 —— 别让它把你机器搞坏,也别让它跑飞。
- 权限系统:allow / deny / ask,权限模式,危险操作的闸门。
- 中断与转向:如何在流式中途叫停,并保持消息历史的合法性。
- Hooks:在工具调用前后、回合结束时插入你自己的逻辑。
第五阶段 · 上下文工程 —— 整个 Agent 最难、最见功力的部分。
- Token 预算:与有限上下文窗口的持久战。
- 系统提示与上下文注入:该塞什么、在哪塞、怎么塞。
- Prompt 缓存:省钱省延迟的命脉,以及“字节稳定性”这条隐形红线。
- 自动压缩:上下文快满了,怎么把历史“折叠”成摘要还不丢关键信息。
- 精细化上下文管理:按需删除巨型工具结果、外置存储、内容替换。
第六阶段 · 健壮性 —— 生产环境里,出错是常态。
- 错误恢复与模型回退:重试、退避、降级换模型、孤儿消息清理、各类限额恢复。
- 成本与用量追踪:把 token 换算成钱,并实时盯住。
- 思考(extended thinking)的处理:签名、模型绑定,以及那些能让你调试一整天的坑。
第七阶段 · 扩展与规模 —— 一个 Agent 打不过,就上一群。
- 子 Agent:任务委派与上下文隔离,让主线程不被细节淹没。
- MCP 与工具的懒加载:接入外部工具生态,以及几百个工具怎么按需加载。
- 会话历史与持久化:JSONL 落盘、断点续接、撤销。
实战番外 · 综合运用 —— 把上面所有零件组装起来,干一件真正复杂的活。
- 仓库总结的完整流程:一个几百万 token 的仓库塞不进窗口,Agent 是怎么建立起那张地图的。
一句前置声明:本专栏聚焦通用的 Agent 工程技术——这些模式适用于任何基于 LLM 构建的 Agent。文中所有代码均为讲解而写的独立示例,用来演示技术要点本身,你可以照着在任何 LLM API 上复刻。我们只谈技术,不谈具体产品。
配套代码:一个从零搭起的最小 Agent
本专栏配一个可运行的开源仓库 👉 github.com/davidapp/coding-agent-from-scratch。它不是一堆零散片段,而是一个随专栏逐篇长大的真实 Agent:每读完一篇,仓库就演进一步,加上那一篇讲的部件。你可以 git checkout 到任意一篇对应的版本,直接把那个阶段的 Agent 跑起来。
读到第二阶段结束,这个仓库已经是一个真能自主读写文件、跑命令、改代码的最小 Coding Agent 了——总共不过几百行。文章讲“为什么这么设计”,代码给“具体怎么落地”,两边对照着看。
读之前,你最好有
- 用过至少一次某个 LLM 的 API(知道
messages、system、stream大概是什么)。 - 会读 TypeScript(示例用 TS 写,但讲的是思想,换成 Python/Go 一样成立)。
- 对“Agent 到底是不是黑魔法”心存好奇——读完你会发现,它一点也不魔法,全是扎实的工程。
准备好了,我们从最朴素的起点开始:一次 LLM API 调用,到底给了你什么。