21 天手搓一个 Coding Agent
第 1 周 · 核心循环
一个 Coding Agent 由哪几层组成:REPL 骨架、命令系统与不绑厂商的网关抽象
先把一个终端 Coding Agent 拆成五层,看清哪一层是自己的、哪一层是厂商的,再动手写出一个能对话的空壳:readline 循环、斜杠命令表、OpenAI 兼容网关 provider 与一套离线剧本,让它在没有余额时也能跑。
流式输出与终端渲染:手写 SSE 解析、增量 Markdown 与可打断的打字机
把网关吐出的 SSE 字节流一层层剥开:先解析事件、再归并成增量事件、最后交给渲染器逐字打印,并处理流中断、光标控制与用户按键打断这三件真实工程里最容易做错的事。
工具协议与只读三件套:schema 设计、分片归并与结果截断
给 Agent 装上读代码的眼睛:写出读文件、找文件、搜内容三个只读工具,把工具 schema、流式工具调用分片的归并、以及超长结果怎么截断这三件事一次定清楚,之后十八天都靠它。
文件编辑与 shell 执行:精确替换、冲突检测与超时可杀的子进程
把读权限升级成写权限:实现基于精确替换的编辑工具与能跑命令的 shell 工具,处理旧内容不匹配、文件被外部改动、命令卡死与输出过大四种真实故障,然后让 Agent 第一次把失败的测试修绿。
权限与审批:三态规则、按工具与路径匹配,以及自动模式的边界
给 Agent 装一道审批门:把每次工具调用交给一套 allow 与 ask 与 deny 三态规则判定,规则按工具名与路径模式匹配,审批结果能记住,并想清楚全自动模式在什么条件下才是负责任的。
错误处理与自纠:失败回灌、退避重试、死循环检测与取消中断
把六类真实故障一次处理干净:工具失败、参数非法、网关限流、命令超时、流中断、模型打转。原则只有一条——能让模型自己改的错误就回灌给它,不能的才向用户抬头,并且任何时候用户都能按下取消。
会话持久化与恢复:只追加的事件日志、resume 与分叉,第一周复盘
让对话不再随进程消失:用只追加的 JSONL 事件日志记下每一次消息、工具调用与用量,重启后重放日志恢复现场,还能从任意一条事件分叉出一条新会话,最后回头复盘第一周这七层是怎么叠起来的。
第 2 周 · 智能化
引用注入:解析 @ 文件、目录、URL 与图片,并把注入量说清楚
别让 Agent 自己翻遍整个仓库:实现 @ 引用语法,把文件、目录、网页地址解析成结构化的注入内容,处理二进制与超大文件,并在终端显式打印这一次注入了多少字符、占掉多少预算。
项目指令文件:三层加载、导入展开与 system prompt 的合并顺序
让 Agent 一进仓库就知道规矩:实现用户级、项目级、目录级三层指令文件的发现与加载,支持文件之间的导入,定义确定的合并顺序与冲突规则,并让用户能一条命令看清最终 system prompt 是怎么拼出来的。
任务清单与自我规划:todo 工具、进度渲染与打转的早期发现
给长任务装一块看板:实现一个让模型自己维护待办清单的工具,把清单实时渲染在终端里,用它约束模型一次只做一件事,并借清单的变化在模型开始打转时第一时间发现。
跨会话记忆:显式记忆、自动记忆与检索注入的三个判据
让 Agent 记住这个仓库的坑:实现一个文件式的记忆目录,区分用户显式写下的记忆与模型自动沉淀的记忆,用关键词与路径做检索并只注入相关的几条,同时想清楚什么东西不该被记住。
上下文压缩:token 怎么数、压什么留什么、压完怎么验证没丢
上下文总会满:先用真实用量校准一个本地 token 估算器,再实现分段摘要式压缩,明确哪几类消息必须原样保留,最后用一组回答早期事实的探针验证压缩没有丢掉关键信息。
先问后做:结构化提问工具、只读探索模式与计划审批
让 Agent 在动手前先把话说清楚:实现一个让模型结构化反问的工具,加一个只放行只读工具的探索模式,最后让它产出一份可审批的计划,用户批准后才切回可写状态执行。
checkpoint 与 rewind:文件快照、对话回退,以及两者为什么必须独立
改坏了要能退回来:实现基于内容哈希的文件快照,把它与会话事件日志组成两条独立的时间线,支持只回滚文件、只回滚对话或两者一起,并处理仓库里本来就有未提交改动的情况,第二周复盘。
第 3 周 · 扩展与发布
接入 MCP:手写 JSON-RPC 客户端、两种传输与工具命名空间
把别人的工具接进自己的 Agent:不用官方 SDK,手写一个 MCP 客户端,跑通 stdio 与 Streamable HTTP 两种传输,把远端工具聚合进本地清单并加命名空间,最后让它们复用第五天那道审批门。
加载 Skills:扫描、渐进披露与触发判定,让经验按需上桌
把可复用的经验做成技能包:实现一个技能加载器,启动时只读摘要、命中触发条件时才读全文、需要时才执行附带脚本,并用真实数字说明这套渐进披露到底省下了多少上下文。
子 Agent 与并行:独立上下文、工具白名单、worktree 隔离与结果汇总
一个人干不完就分头干:实现子 Agent 机制,让每个子 Agent 有自己的上下文与工具白名单,在各自的 git worktree 里改文件互不干扰,最后把结果结构化汇总回主会话,并想清楚什么任务不该并行。
hooks 与后台任务:生命周期钩子、确定性检查与不打断对话的通知
有些事不该交给模型判断:实现生命周期钩子,在工具执行前后插入确定性的检查与格式化,再实现后台任务,让长时间运行的命令不阻塞对话、结束时把结果通知回 REPL。
多模态输入:粘贴截图、图片校验与照图改代码
让 Agent 看得见:把图片接进消息结构,处理粘贴与文件两种来源、体积与尺寸下限、以及不支持图片的模型该怎么降级,最后用一张界面截图驱动一次真实的代码改动。
评估与成本:基准集怎么设计、通过率怎么算、token 与缓存命中怎么看
凭感觉调 Agent 会越调越差:设计一个能自动判分的任务基准集,跑出通过率、平均轮数与 token 消耗,把缓存命中率算出来,再用一次提示词改动的前后对比说明为什么评估必须先于优化。
打包与发布:全局命令、配置目录、版本与更新,二十一天总复盘
把它变成别人也能用的工具:配好可执行入口与打包产物,把散在环境变量里的配置收进配置目录并保留覆盖顺序,处理版本与更新提示,写好 README 与演示,最后回头看这二十一层是怎么长成一个工具的。