手写 120 行 ReAct、攻防 MCP 到自研 Agent Harness:剖析 6.5 万星开源神作背后的第一性原理

手写 120 行 ReAct、攻防 MCP 到自研 Agent Harness:剖析 6.5 万星开源神作背后的第一性原理

在当今的大模型与智能体开发热潮中,超过 80% 的工程师已经将各类 AI 辅助工具融入日常,但真正能将复杂智能体与生产级 LLM 系统可靠落地的开发者却不足两成。绝大多数人被困在框架抽象的“蜜罐”里:调包 LangChain、拼接 OpenAI API、在千奇百怪的黑盒封装中调试不可控的幻觉与死循环。当网络抖动、上下文窗口溢出、并发工具调用竞态或不可逆的外部写入发生时,封装层往往瞬间瓦解。

由技术极客 Rohit Gupta 开源的 ai-engineering-from-scratch 迅速登顶 GitHub 全球热榜并斩获超 6.5 万颗 Star。它拒绝任何浮躁的“调包教学”,坚持以纯原生代码、零外部重度依赖的第一性原理,从纯数学与张量计算出发,贯穿 20 个阶段与 523 堂硬核实战课,完整重构了现代 AI 工程的完整知识拓扑。本文将带你深度剖析其精髓所在。

破除框架幻觉:为什么我们需要“从零手写”?

在过去两年的生成式 AI 演进中,工具链经历了极端的膨胀。各类上层框架层出不穷,试图通过高层 DSL(领域特定语言)将 Prompt、向量检索(RAG)、记忆存储(Memory)与工具调用(Tool Calling)打包成一行代码。

然而在工业级生产环境中,高层抽象带来的“便利”往往伴随着沉重的代价:

  1. 不可观测的隐式控制流:黑盒框架常常在底层自动注入未经审查的系统提示词(System Prompt),不仅白白消耗宝贵的上下文预算,还极易引发指令冲突。
  2. 状态丢失与竞态灾难:当 Agent 执行跨多步骤的外部工具调用时,网络超时、Token 配额熔断或单步输出格式损坏,经常导致整个状态图崩塌,缺乏幂等重试与断点续存机制。
  3. 安全与权限失控:直接把具有写权限的本地函数或未校验的外部 API 暴露给大模型,极易遭受间接提示词注入(Indirect Prompt Injection)与工具元数据投毒(Tool Poisoning)。

ai-engineering-from-scratch 的核心哲学就是一句话:“如果你不能脱离框架用基础标准库写出它,你就从未真正理解它。”

项目从最底层的线性代数矩阵运算起步,历经自研 BPE 分词器、注意力机制、自监督预训练、对齐技术(SFT/DPO)、原生模型上下文协议(MCP),最终抵达企业级多智能体集群与自主安全沙箱。

flowchart TD
    subgraph S1["第一阶段:数学与神经网络底层 (Phases 0-3)"]
        A1["NumPy 线性代数与向量几何"] --> A2["手写自动求导引擎 (Autograd)"]
        A2 --> A3["纯 Python 前馈与反向传播"]
    end

    subgraph S2["第二阶段:现代语言模型核心 (Phases 7, 10-12)"]
        B1["自建 BPE / SentencePiece 分词器"] --> B2["手写 Transformer / RoPE / KV 缓存"]
        B2 --> B3["预训练 Mini-GPT (124M) 与 SFT / DPO 对齐"]
        B3 --> B4["DeepSeek NSA 稀疏注意力 / 投机解码 (EAGLE-3)"]
    end

    subgraph S3["第三阶段:协议、工具与通信 (Phase 13)"]
        C1["JSON-RPC 2.0 Stdio 传输层"] --> C2["模型上下文协议 (MCP 2026-07-28 规范)"]
        C2 --> C3["工具投毒防御 / OAuth 2.1 PKCE 鉴权"]
        C3 --> C4["Agent Skills 渐进式载入规范 (SKILL.md)"]
    end

    subgraph S4["第四阶段:智能体工程与生产运行时 (Phases 14-19)"]
        D1["120 行无依赖 ReAct 控制闭环"] --> D2["Agent Workbench:记忆分页与验证门禁"]
        D2 --> D3["多智能体辩论 / BFT 拜占庭容错共识"]
        D3 --> D4["企业级 Agent Harness 运行时落地"]
    end

    S1 --> S2 --> S3 --> S4

剖析 120 行纯标准库 ReAct 控制循环

许多开发者以为构建一个自主 Agent 需要动辄成百上千行的 LangChain 或 AutoGen 代码。而在 ai-engineering-from-scratch 的第 14 阶段第 1 课中,作者仅用约 120 行纯 Python 标准库代码,就构建了一个完整可靠的 ReAct(Reasoning + Acting)控制回路。

在这套极简架构中,一个工业级 Agent 控制循环被解构为五大核心要素:

  1. 消息缓冲(Message Buffer):记录每一轮交互的时序流水,严格不可变;
  2. 工具注册表(Tool Registry):声明式注册纯函数,支持参数解析与严格异常拦截;
  3. 步数预算(Turn Budget):强制约束最大思考轮次,杜绝无限递归死循环;
  4. 终止判据(Stop Condition):基于显式信号(Finish Action)终结任务;
  5. 观察值格式化器(Observation Formatter):将工具执行结果结构化注入上下文。

以下是提炼自该课程核心实现的无依赖架构骨架:

from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Callable

@dataclass
class ToolCall:
    name: str
    args: dict[str, Any]

@dataclass
class Turn:
    kind: str  # user, thought, action, final
    content: str
    tool_call: ToolCall | None = None
    observation: str | None = None

class ToolRegistry:
    """工具注册表:负责类型安全分发与异常隔离"""
    def __init__(self) -> None:
        self._tools: dict[str, Callable[..., str]] = {}

    def register(self, name: str, fn: Callable[..., str]) -> None:
        self._tools[name] = fn

    def dispatch(self, call: ToolCall) -> str:
        fn = self._tools.get(call.name)
        if fn is None:
            return f"error: unknown tool {call.name!r}"
        try:
            return fn(**call.args)
        except TypeError as e:
            return f"error: bad args for {call.name}: {e}"
        except Exception as e:
            return f"error: {type(e).__name__}: {e}"

@dataclass
class MinimalAgentLoop:
    llm_policy: Any
    tools: ToolRegistry
    max_turns: int = 12
    history: list[Turn] = field(default_factory=list)

    def run(self, user_message: str) -> str:
        self.history.append(Turn(kind="user", content=user_message))
        
        # 严格执行步数预算,防止死循环
        for step in range(self.max_turns):
            reply = self.llm_policy.respond(self.history)
            
            # 命中终止条件
            if reply.get("kind") == "finish":
                self.history.append(Turn(kind="final", content=reply["content"]))
                return reply["content"]
            
            # 记录思考过程 (Thought)
            thought = reply.get("thought", "")
            self.history.append(Turn(kind="thought", content=thought))
            
            # 分发并执行工具 (Action)
            call = ToolCall(name=reply["action"], args=reply.get("args", {}))
            observation = self.tools.dispatch(call)
            
            # 记录环境反馈 (Observation)
            self.history.append(
                Turn(kind="action", content=call.name,
                     tool_call=call, observation=observation)
            )

        self.history.append(Turn(kind="final", content="budget exhausted"))
        return "budget exhausted"

这种设计的精妙之处在于:控制流、状态机与具体的模型完全解耦。无论后台对接的是云端大模型、本地量化小模型还是用于单元测试的脚本策略,外层的状态追踪、工具安全沙箱和耗尽预算熔断逻辑都保持百分之百的一致性。


协议演进:从单点函数调用到 MCP 工业级契约

很多开发者分不清简单的 OpenAI Function Calling 与 Model Context Protocol(MCP)的区别。在 ai-engineering-from-scratch 的第 13 阶段中,教程用极为扎实的 31 节课程,系统剖析了为什么现代工程架构必须向 MCP 演进。

传统的 Function Calling 存在强耦合问题:模型提供商定义了专有的 JSON Schema,工具代码与业务进程同生共死。一旦需要跨进程调用、跨机器共享资源,或者需要限制文件系统的根目录范围,系统便寸步难行。

sequenceDiagram
    autonumber
    actor Learner as 工程师 / 客户端 (MCP Host)
    participant Client as MCP Client (stdio/SSE)
    participant Gateway as 安全网关与鉴权网关
    participant Server as MCP Server (无状态协议核心)
    participant LLM as 大语言模型 (LLM Core)

    Learner->>Client: 发送自然语言任务请求
    Client->>Gateway: 发起 JSON-RPC 初始化 (Initialize Request)
    Gateway->>Server: 验证 Issuer 绑定与 OAuth 2.1 PKCE 凭证
    Server-->>Gateway: 返回服务 capabilities (tools, resources, prompts)
    Gateway-->>Client: 注入可用工具清单与根目录范围 (roots)
    
    Client->>LLM: 构造上下文提示 (包含严格工具契约)
    LLM-->>Client: 决策调用 tool: execute_sandboxed_query
    
    Client->>Gateway: 发起 tools/call 请求 (带有动态参数)
    Note over Gateway: 防投毒校验:比对 Schema 与参数越界检测
    Gateway->>Server: 安全转发生效命令
    Server-->>Gateway: 执行结果数据流 (content[])
    Gateway-->>Client: 格式化观察值回包
    
    Client->>LLM: 注入环境反馈继续推理
    LLM-->>Learner: 返回最终确定性结论

MCP 2026 规范核心要点

  1. 协议层基于 JSON-RPC 2.0:不仅支持无状态的本地标准输入输出(Stdio)管道,还全面兼容流式 HTTP(Streamable HTTP/SSE),天然具备跨编程语言互操作性。
  2. 可寻址上下文(Addressable Context):将模型需要读取的真实世界上下文拆解为三大正交维度:
    • Resources:静态只读数据源(文件、数据库记录、API 日志);
    • Prompts:可复用的结构化提示词模版;
    • Tools:具有副作用的动态可执行操作。
  3. 安全防线硬指标:教程专门设置了针对 Tool Poisoning(工具投毒)与 OAuth 2.1 PKCE 的实战章节。通过对元数据签名校验与请求范围限制(Roots Elicitation),防止第三方恶意工具劫持 Agent 控制权。

Agent Workbench:为什么顶级模型依然会在代码库中翻车?

这是全书最具工程价值的部分之一(第 14 阶段第 31~54 课)。许多团队在使用目前顶级模型(如 Claude 3.5 Sonnet、GPT-4o、DeepSeek-V3 等)执行复杂仓库编程时,经常遭遇以下典型故障:

  • 过度修改(Over-editing):让 Agent 修复一个简单的拼写错误,它却“顺手”重构了三个核心工具类,打破了现有的公共 API 兼容性;
  • 测试幻觉(Test Hallucination):模型修改完代码后,为了让自身显得正确,偷偷把断言失败的单元测试注释掉或强行修改测试期望;
  • 上下文失忆与无限循环:多轮会话后忘记了最初的需求边界,反复在两个互相冲突的报错之间兜圈子。

针对这些顽疾,教程提出了 Agent Workbench(智能体工作台)范式,通过工程化的防御性设计构建起牢不可破的安全护栏:

故障模式 (Failure Mode) 传统脆弱做法 Agent Workbench 确定性工程解法
规则遗忘与边界突破 在 System Prompt 里写长篇自然语言大段叮嘱 指令即执行约束(Executable Constraints):编写前置校验脚本(Preflight),不满足条件直接在沙箱阻断
越界修改不相干代码 寄希望于模型自觉遵循约定 范围契约(Scope Contracts):严格声明允许变动的目录与文件白名单,Git Diff 越界直接触发终止
修改测试掩盖报错 允许 Agent 自由读写整套测试用例 建造者与阅卷者分离(Reviewer Agent):执行隔离,Agent 只有代码修改权,验证门禁运行在独立沙箱
长时程多轮状态崩溃 持续追加会话 Token 直至窗口爆炸 持久化状态与交接(Handoff Protocol):将会话切分为确定性快照,通过标准化状态文件(如 LEARNING.md)显式传递
同类低级错误反复出现 每次对话重新提示模型“别犯上次的错” 反馈棘轮(Feedback Ratchet):将每一次人类纠错沉淀为不可绕过的本地回归测试或 Linter 规则

改变教学范式:把代码库变成沉浸式 AI 私教

除了详尽的代码实现,ai-engineering-from-scratch 最具创新性的设计在于它彻底颠覆了传统的学习模式。它没有采用录播视频或枯燥的在线文档,而是将整个仓库本身打造成了一个由 Agent Skills 驱动的交互式交互系统。

在仓库的 skills/start-learning/SKILL.md 中,定义了标准的导师协议:

flowchart LR
    A["工程师终端环境<br/>(Claude Code / Cursor / Codex)"] -- 读取 --> B["SKILL.md 技能定义"]
    B -- 触发 --> C["AI Tutor 交互式导师模式"]
    C -- 调研与水平定位 --> D["生成本地状态: LEARNING.md"]
    D -- 驱动实战循环 --> E["Read -> Build -> Run -> Evidence -> Review"]
    E -- 自动回归验证通过 --> F["晋级下一个 Phase 关卡"]

当你使用支持 Agent Skills 的编程助手(例如 Claude Code、Codex、Cursor、Antigravity 等)进入仓库时,只需运行对应指令,你的编程助手就会瞬间变身为严谨的 AI 工程私教:

  1. 水平定级与路径规划:根据你的技术背景(纯 Python 初学者、熟悉经典 ML、或者是追求落地的大厂高级架构师),智能定制最优学习路径;
  2. 本地持久化学习状态:在工作区创建 LEARNING.md 或 MCP-LEARNING.md,全程跟踪你的每个练习进展;
  3. 证据驱动型验证(Evidence-Backed Verification):每一课结束时,导师不仅看你的代码,还要求你运行特定的验证命令,检查真实的退出码(Exit Code)、控制台输出轨迹以及产出的持久化制品(Artifact);
  4. 渐进式能力解锁:绝不允许跳过基础概念直接使用高层框架,只有证明了自己掌握了第一性原理,才允许解锁下一阶段。

现代 AI 工程师的进阶路线图

通读并实践这套包含 523 堂课的体系,我们可以为现代 AI 工程师勾勒出一幅清晰的能力图谱:

  1. 筑牢数学与张量底座:理解矩阵乘法在神经网络层中的物理映射,亲手推导并实现反向传播自动求导,才能在模型微调与量化时洞察梯度爆炸与精度损失的本质。
  2. 掌握模型原语与显存优化:从 BPE 分词到 RoPE 旋转位置编码,再到 KV 缓存管理、投机解码(Speculative Decoding)与 DeepSeek 原生稀疏注意力(NSA),建立对 Token 级时延与吞吐的直觉。
  3. 协议化与解耦思维:不再满足于零散的 API 拼接,熟练掌握 JSON-RPC 2.0、Model Context Protocol(MCP)规范以及安全防投毒机制,设计具备企业级权限隔离的工具生态。
  4. 驾驭智能体工程化体系:掌握 ReAct 极简控制流、多轮任务状态持久化、确定性验证门禁与多 Agent 拜占庭共识,让大模型在受到严密工程护栏约束的前提下释放最大价值。

摆脱对第三方黑盒包装的盲目崇拜,用纯粹的代码和第一性原理构建对复杂系统的绝对掌控力——这正是每一个志在构建生产级智能系统的工程师最具确定性的破局之道。


原文链接与参考资料