30天手搓AI Agent:从零构建代码地图智能体

30天手写实现代码库地图Agent,从裸HTTP调用到生产化评估,全程不用框架起步。
该项目用三十天、每天一个概念的方式,从零手写构建一个名为 cartographer 的 AI Agent:它读取陌生代码仓库并生成上手地图。核心约束是代码库无法装进任何上下文窗口,迫使 Agent 自己决定读什么,从而让工具调用、检索和成本控制成为必需而非演示。第一周仅用约四十行 Python 通过原始 HTTP 调用模型,手写循环与记忆;第二周学习 MCP 协议及其 2026-07-28 修订;第三周引入 LangGraph 处理循环、持久化与人类审批;第四周完成评估、可观测性和成本路由。系列强调不构建不描述、不编造数字,所有模型调用跑在免费层。
30天手搓AI Agent:从零构建代码地图智能体

大多数人学习 AI Agent 的方式,是打开某个框架的快速开始文档。三行代码之后,某个令人印象深刻的东西跑起来了——但真正有趣的部分,那个循环、那个决定发送什么的判断、那个在大规模场景下会出错的地方,全都发生在一个你从未打开过的函数内部。
这不是学习者的问题。几乎所有关于 Agent 的教程都在演示某个库,于是它教给你的是词汇,而不是机制。
一个名为 "Learn AI agents by building one" 的系列选择了一条更难但更扎实的路:用三十天,每天一个概念,全部手写实现,最终组装成一个真实可用的工具。
为什么只做一个项目,而不是三十个演示
大多数教程习惯为每个概念配一个全新的玩具:讲工具调用就写个天气查询,讲检索就做个 PDF 问答机器人。每个都能跑通,但都教不了你太多东西——因为玩具不会反抗你。你从未撞上那堵让概念变得必要的墙,所以你学到的是 API,而不是原因。
这个系列反其道而行,三十天只构建一个工具,选择它的理由正是因为它会跟你较劲。
这个工具叫 cartographer。它指向一个你从未见过的代码仓库,返回一份上手地图:执行究竟从哪里开始、哪一小部分文件承载了整个系统、一条端到端追踪的数据路径,以及你的第一个修改应该放在哪里。任何加入过新团队的人都熟悉这种要花一周才能搞清楚的痛苦。
它之所以是个好老师,源于一个特性:代码仓库装不下。一个中型开源项目动辄数百万 token,没有任何上下文窗口大到能容纳它,没有足够聪明的提示词能绕过它,也没有明年更大的模型能让这个问题消失。Agent 必须自己决定读什么。
这一个约束,就把课程里每个概念从演示变成了必需品。工具调用成为唯一的入口,检索不再是你被告知要加的某个阶段,成本控制变成算术题。你在需要它的那一刻遇见每个概念——这是唯一能让知识真正留存的时机。
它还有第二个有用的特性:存在正确答案。把它指向一个你熟悉的代码库,你就能检验这份地图是否正确。这让第 25 天的真实评估成为可能,而不是靠"看起来能用"的直觉判断。
四周分别构建什么
第一周:裸模型,前面什么都不放
用大约四十行 Python 直接通过原始 HTTP 调用模型,不用 SDK,不用任何 Agent 库。你会亲手处理区分"完整回答"和"被截断回答"的那个字段,手动构建对话记忆并理解为什么"记忆"这个词具有误导性,做贯穿后续所有设计决策的 token 算术,让模型返回带类型的记录而非散文,并手写工具调用——这样你就亲眼看到了到底什么东西在网络上传输。到第一周结束时,你有一个能工作的 Agent,以及一份清晰的"它还有哪些毛病"的清单。
原始 HTTP 调用与 SDK 的区别值得展开。绝大多数教程使用 openai 或 anthropic 这类 SDK,它替你封装了鉴权头、请求体序列化、流式响应的分块解析、重试和错误映射。当你直接向 /v1/chat/completions 发送 POST 请求时,这些都不能省略:你需要手动设置 Authorization: Bearer <key>、Content-Type: application/json,把 messages 数组、model、max_tokens、temperature 等字段组装进 JSON body,再解析返回的 choices[0].message.content。区分“完整回答”和“被截断回答”的字段是 finish_reason——当它为 stop 时模型自然结束,为 length 时说明撞上了 max_tokens 上限,回答被硬生生切断了。手写这一层最大的价值在于:之后使用任何框架时,你能看清它到底封装了什么,而不是把黑箱当成魔法。
第二周:MCP 协议
MCP 是让任何编辑器或客户端与你的 Agent 对话的协议,而不需要它困在某个脚本里。现在学正是好时机,因为 MCP 在 2026-07-28 修订版中移除了初始化握手和协议级会话。这意味着目前大量关于 MCP 工作原理的教程,描述的是一个已经不存在的协议。你将学到当下真实的版本,构建一个值得保留的服务器,并处理 Agent 读取非自己所写代码时必然出现的那个安全问题。
MCP(Model Context Protocol) 是 Anthropic 于 2024 年底提出的开放协议,目的是让模型或 Agent 以统一方式连接外部工具、资源和提示模板,而不必为每个客户端单独适配。它的核心通信机制基于 JSON-RPC 2.0,通过 stdio 或 HTTP/SSE 传输,把“服务器提供什么能力”与“客户端如何使用”解耦。历史上 MCP 使用初始化的 initialize 握手来交换协议版本和能力清单,并维持一个有状态的会话对象。2026-07-28 修订版移除了这一握手和协议级会话,改为更接近无状态的请求-响应模型,这简化了部署和横向扩展,但也让大量基于旧握手的教程和示例服务器代码失效。学习时务必以官方最新规范为准,而不是搜索引擎排名靠前的旧文章。
第三周:LangGraph,以及为什么仅有循环不够
阅读代码库不是一条流水线。你读了一个文件,没看懂,回头再找更多上下文——这是一个循环,而循环恰恰是链式结构无法表达的东西。你还会加入两个把脚本变成软件的功能:在扫描到四千个文件时崩溃后能否恢复,以及在执行有后果的操作前停下来询问人类。
LangGraph 是 LangChain 生态中用于构建有状态、可循环 Agent 的编排库。它把工作流建模成一张图:节点是执行单元(调用模型、运行工具、做判断),边定义控制流,而“状态”是一个在节点之间传递的共享数据结构。与链式(chain)结构最本质的区别是,图允许条件边和环,因此可以表达“读文件—没懂—回头找更多上下文”这类重复过程。它内置的检查点(checkpointer)机制把每一步状态持久化,让崩溃后能从最近的检查点恢复,而不是从头再跑一遍;同时支持在特定节点前中断并等待人类输入,这正是扫描四千个文件后崩溃恢复、以及执行有后果操作前征求同意的实现基础。理解这一层,需要先把握“状态机 + 持久化”这个抽象,而不是死记 API。
第四周:决定它是否真实可用的那一半
把记忆拆成三个独立问题而非一个词,把检索变成 Agent 自主选择调用的工具,建立带已知正确答案的评估集,让"它变差了吗"有据可查。可观测性追踪、成本路由,以及它在生产环境中会失败的七种方式——大多数教程跳过的部分。
评估集(eval set) 是衡量 Agent 是否变差的基准:一组带有已知正确答案的输入-输出样本,每次改动后跑一遍,用通过率、准确率等指标量化变化,而不是凭“看起来能用”的直觉。对 cartographer 而言,把一个自己熟悉的代码库作为输入,人工核对它生成的入口点、核心文件和调用路径是否正确,就等于拥有了一份可复现的参考答案。与之配套的可观测性(observability) 通常指追踪(trace):记录每次模型调用、工具调用、token 消耗和延迟,把整条执行链路串起来。没有 trace,出问题时只能靠打印日志猜;有了 trace,就能定位是检索召回了错文件、还是模型在某个判断节点走了弯路。成本路由则是根据请求复杂度把简单任务分给便宜模型、复杂任务给强模型,在准确率与费用之间做取舍。
如何跟进学习
每天的内容分两部分:一篇解释概念及其重要性的文章,以及具体的开发笔记,告诉你该在哪个文件夹创建哪个文件、往里面输入什么、每一行做什么。
第零天的构建没有任何 Agent 代码,只创建仓库结构。每个文件都有明确职责:pyproject.toml 声明项目名、Python 版本和唯一的运行时依赖;src/cartographer/__init__.py 让文件夹成为可导入的包并保存版本号;.gitignore 把环境、缓存和密钥挡在版本历史之外;LICENSE 让代码可被复用;README.md 说明工具将要做什么,并坦诚承认目前什么都还没跑通;.github/workflows/ci.yml 在每次推送时执行 lint、类型检查和测试;tests/test_package.py 是一个真实的测试。它还会克隆 click 8.5.0——Agent 在整个系列中研究的那个仓库,固定版本以确保每一天都在测量同一份代码。
你需要 Python 3.12、一个终端,以及每天大约一小时。所有模型调用都通过一个 OpenAI 兼容端点运行在免费模型上,不会有任何账单。
你不需要任何 Agent 方面的经验。如果 Agent 对你来说是全新的,先读那篇入门文章《在任何代码之前,解释每个 AI Agent 的六个概念》:大约十五分钟,不含代码,涵盖什么是模型调用、token、上下文窗口、为什么模型什么都不记得、工具调用,以及让它成为 Agent 的那个循环。如果你已经熟悉,直接从第一天开始。但你确实需要能够舒适地阅读 Python 代码。
写作的两条规则
没有构建过的东西不会被描述。 代码先于文章发布。当某个东西不工作时,那就是当天的文章——而且一定会有好几篇,因为用三十天构建一个困难的东西,不是三十天的胜利。
不编造数字。 任何关于准确率的声明都来自第 25 天的评估,针对带有已知正确答案的仓库,方法论一并发布。如果某个数字是示意性的,句子会明确说明。
这个系列的核心价值在于:它不教你某个框架的用法,而是让你在采用框架之前就亲手写出那个循环。当你真正使用框架时,你能够说清楚它到底替你做了什么。
如果你也曾在一个陌生的代码库里浪费过一周——我们大多数人都有过——哪个环节真正消耗了你的时间:找到入口点,还是搞清楚哪些文件重要?
相关推荐

OpenAI与Shield合作:Astra智能体如何革新IT故障修复
OpenAI与Shield合作推出Astra智能体,可自动登录电脑和遗留系统,实时修复IT故障,比传统模型快35%到40%,仅在需要人类判断时引入人工。

iPhone Duo续航实测:一天一充跑不掉,大屏是耗电元凶
iPhone Duo续航实测:重度使用一天需至少充电一次,6.5小时亮屏约剩30%电量。大屏展开频率是耗电关键,MagSafe电池背夹可救场,长期衰减同样值得关注。

Kimi K3.1 Pro开源发布:2.8万亿参数逼近Opus
Moonshot发布开源MoE模型Kimi K3.1 Pro,2.8万亿总参数、1040亿激活参数,Terminal Bench 4.0仅落后Opus 5.5不到1分,单任务成本约三分之一,API价格减半,开源权重11月4日开放。