AI 编程 Agent 究竟是如何工作的:一次源码深度剖析

我们追踪了 Amazon Q CLI 和 Claude Code 的源代码,深入理解 AI 编程 Agent 底层的真实运作方式。

zhuermu··25 分钟
AI AgentCoding AgentLLMAmazon QClaude CodeSource Code
AI 编程 Agent 究竟是如何工作的:一次源码深度剖析

Cursor、Claude Code、Amazon Q、Windsurf…… 到了 2026 年,AI 编程已经成为一片竞争白热化的红海。但你有没有想过:这些工具在底层究竟是怎么工作的?

本文基于两个开源项目的源代码 —— Amazon Q Developer CLI(用 Rust 实现)和 Claude Code(TypeScript + Python)—— 从最底层拆解 AI 编程 Agent 的核心架构。


先说清楚:AI 编程不是聊天机器人

很多人以为 AI 编程工具不过是给 ChatGPT 套了个 IDE 的外壳。这从根本上就错了。

聊天机器人只会说话,AI 编程 Agent 却能行动。区别在哪?工具使用(Tool Use,即 function calling)。

当你让 Claude Code 修一个 bug 时,幕后实际发生的是这样一串过程:

You:        "Fix the bug in src/app.js"
LLM thinks: I need to read that file first
LLM output: tool_call → fs_read("src/app.js")
Agent:      executes read → returns file content to LLM
LLM thinks: Found it — line 42 has the issue
LLM output: tool_call → fs_write("src/app.js", ...)
Agent:      executes write → returns result
LLM:        "Done. The problem was..."

这个过程被称为 Agent 循环(Agent Loop)—— 它是每一款 AI 编程工具中最重要的设计模式。

关键概念: LLM 从不直接操作你的机器。它发送结构化的 JSON 请求,告诉 Agent“我想做什么”,而 Agent 在真正代其执行之前会先校验权限。这让每一次操作都可审计、可拦截、可回滚。


Agent 循环:一台优雅的状态机

Amazon Q CLI 用 Rust 实现了一个显式的有限状态机来管理整个 Agent 循环。

这个状态机有六个状态IdleExecutingRequestExecutingHooksWaitingForApprovalExecutingTools →(循环回到起点)

这台状态机有几处设计尤为精妙:

  • 循环是自动的 —— LLM 调用工具后,结果会被重新注入对话中,并自动再次调用 LLM。
  • 工具可以并行执行 —— LLM 可以在一次响应中返回多个 tool_use 块,Agent 使用 Tokio 的 FuturesUnordered 来并发执行它们。
  • 每一次工具调用都要经过权限检查 —— 没有例外。

工具系统:AI 的手和脚

一个 AI 编程 Agent 的能力上限,完全取决于它能访问哪些工具。

工具描述的艺术

工具的 description 不是写给人看的文档 —— 它是写给 LLM 看的行为指令。它的质量直接决定了 Agent 的表现好坏。

__tool_use_purpose:逼迫 AI 在动手前先思考

Amazon Q CLI 有一个优雅的设计细节:每一次工具调用都强制要求 LLM 填写一个 purpose 字段。这个看似不起眼的约束效果显著 —— 它迫使模型在调用工具之前先阐明为什么要调用它,从而减少了幻觉式或不必要的工具调用。


安全模型:四层纵深防御

AI 编程 Agent 能直接访问你的文件系统、终端和网络。安全不是可选项 —— 它是架构层面的问题。

Amazon Q CLI 实现了一套四层安全架构:Hook → 用户确认 → 路径权限 → 工具白名单

所有文件路径都会先经过 canonicalize 规范化处理,这能防止 ../ 之类的路径穿越攻击绕过权限边界。

Claude Code 则采取了另一种思路,使用 Hook 系统来实现声明式的安全策略,自动检测九类常见的安全风险。


上下文窗口管理:最稀缺的资源

在传统软件中,瓶颈是 CPU、内存和 I/O。而在 AI 编程中,瓶颈是上下文窗口

每一个 token 都很重要。系统提示词、对话历史、工具描述、文件内容以及工具返回结果,都在争抢一个固定大小窗口中的空间。一旦超出限制,模型要么丢失关键上下文,要么请求彻底失败。

Amazon Q CLI 采用四种策略来管理它:

  1. 自动压缩(Auto-compaction) —— 当窗口被填满时,把 20 万 token 的对话压缩成约 2K token 的摘要。
  2. 消息截断 —— 读取大文件时,只保留前 10,000 个字符。
  3. 历史裁剪 —— 保留最近的消息,同时维护结构完整性(确保工具调用/结果成对匹配)。
  4. 资源文件上限 —— 自动纳入的资源文件(如 .qdeveloper 配置)被限制在 10KB 以内。

MCP 协议:工具扩展的事实标准

两个项目都采用了 **MCP(Model Context Protocol,模型上下文协议)**作为它们的工具扩展协议。MCP 提供了一种标准化方式,可以在不修改 Agent 核心代码的前提下为其添加新工具 —— 工具被定义为通过明确定义的协议进行通信的外部服务器。

Amazon Q CLI 使用 Actor 模型来管理多个 MCP 服务器,其中每个 MCP 服务器都作为一个拥有独立生命周期的 actor 运行。这提供了天然的隔离性:如果某个 MCP 服务器崩溃,也不会拖垮其他服务器。


插件架构:Claude Code 的五维扩展模型

Claude Code 定义了五个正交的扩展点,让插件作者能对 Agent 行为的不同方面进行细粒度的控制。

最有意思的例子是 feature-dev 插件的七阶段工作流 —— 它会并行启动多个子 Agent,同时探索不同的代码路径。每个子 Agent 在自己的探索分支上运作,最终结果被综合成一份连贯的实现方案。这是一种真正的多 Agent 模式,而不只是顺序的工具调用。


架构对比

维度Amazon Q CLIClaude Code
语言RustTypeScript + Python
架构单体 Agent + Actor 并发核心引擎 + 插件生态
并发Tokio 异步 + Actor 模型Node.js 事件循环 + 子进程
扩展MCP + Hook 脚本五维插件系统
状态SQLite 持久化文件系统 + 会话状态
优势性能、类型安全开发速度、丰富的生态

尽管存在这些表面上的差异,核心范式却是完全一致的:LLM Agent + 工具使用 + 流式输出 + 安全 + MCP。

这种趋同并非巧合。这些正是在真实世界的编程任务中经受住考验、存活下来的设计模式。每一款严肃的 AI 编程工具,无论用什么语言实现,最终都会以惊人相似的方式去解决同样的根本问题。


七条设计原则

在深入研究了这两个代码库之后,以下是定义现代 AI 编程 Agent 构建方式的七条原则:

  1. LLM 是大脑,工具是手脚。 模型负责推理和决策,工具负责执行。切勿混淆二者。
  2. 流式优先。 每一次交互都实时流式传输 token 和事件。批量式的请求-响应对开发者体验而言是行不通的。
  3. 安全是架构问题,而非一项功能。 权限检查、路径校验和用户确认被内建进 Agent 循环本身 —— 而不是事后再补上去的。
  4. 上下文窗口是最稀缺的资源。 每一项设计决策 —— 从工具结果的格式化到对话历史的管理 —— 都必须考虑上下文预算。
  5. 工具描述就是提示词。 工具 description 字段里的文字实际上就是系统提示词的一部分,要以同样的用心去撰写。
  6. MCP 标准化了工具生态。 一套共享协议意味着工具可以在不同 Agent 之间移植,正如 REST 标准化了 Web API 一样。
  7. 状态机驱动对话管理。 显式的状态转换让 Agent 循环变得可预测、可调试、更安全。

结语

AI 编程看起来像魔法。但把它拆开来看,本质却出奇地简单:一个循环、一组工具、一套权限系统

循环调用 LLM,LLM 挑选一个工具,工具执行,结果再反馈回循环。如此反复,直到任务完成。所有的复杂性 —— 流式输出、安全、上下文管理、插件系统 —— 都不过是围绕这个核心循环的展开与精细化。

理解这些内部机制,不只是满足好奇心。它给了你一套框架,去评估该采用哪些工具、如何扩展它们,以及真正的技术护城河在哪里(提示:护城河更多不在于循环本身,而在于工具和提示词)。

参考项目:

参考资料

  1. Claude Code repository — GitHub
  2. Claude Code documentation — Anthropic
  3. Anthropic engineering blog — Anthropic
  4. Model Context Protocol — MCP Documentation