乐于分享
好东西不私藏

Claude Code 源码深度解析:Agent 架构的工程实现

Claude Code 源码深度解析:Agent 架构的工程实现

Claude Code 源码深度解析:Agent 架构的工程实现

Claude Code 不仅仅是一个「AI 写代码工具」,它代表了当前 AI Agent 工程化的最佳实践之一。本文从源码层面拆解其核心设计思想,揭示一个真正可用的 Agent 系统是如何被构建出来的。


一、Claude Code 的定位与能力边界

1.1 官方定义

Claude Code 是一个终端原生的 AI 编程助手,能够:

  • 读取和编辑文件:理解项目结构,精确修改代码
  • 执行终端命令:运行测试、安装依赖、Git 操作
  • 理解项目上下文:跨文件推理,理解代码依赖关系
  • 自主完成多步骤任务:从需求到实现的全流程自动化

1.2 能力边界

Claude Code 能做什么

  • 代码重构与优化
  • Bug 修复与调试
  • 项目脚手架生成
  • 文档编写与更新
  • 测试用例生成

Claude Code 不能做什么

  • 直接访问外部网络(除非通过工具)
  • 执行需要交互式输入的命令
  • 绕过用户确认执行危险操作
  • 超出 token 预算的超长上下文推理

1.3 与传统 IDE 插件的区别

维度 传统 IDE 插件 Claude Code
交互方式 问答式 任务式
执行能力 仅提供建议 可直接执行
上下文范围 当前文件 整个项目
错误恢复 自动重试与修正

二、Agent 核心架构:三层设计

2.1 整体架构

Claude Code 采用经典的三层 Agent 架构:

┌─────────────────────────────────────────────────────────┐
│                      Claude Code                         │
├─────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐      │
│  │   感知层    │  │   决策层    │  │   执行层    │      │
│  │  (Perceive) │→ │  (Decide)   │→ │  (Execute)  │      │
│  └─────────────┘  └─────────────┘  └─────────────┘      │
│        ↑                                    ↓           │
│        └────────────────────────────────────┘           │
│                     反馈循环 (Feedback)                  │
└─────────────────────────────────────────────────────────┘

2.2 感知层(Perception Layer)

职责:收集环境信息,构建 Agent 的「世界观」

核心组件

组件 功能 实现细节
File Reader 读取文件内容 支持分块读取、编码检测
Directory Scanner 扫描目录结构 递归遍历、排除规则
Command Output Parser 解析命令输出 提取关键信息、错误识别
Context Aggregator 聚合上下文 优先级排序、token 预算控制

感知策略

  1. 渐进式感知:先读取目录结构,再按需加载文件
  2. 关键词触发:检测到特定关键词时主动扩展感知范围
  3. 差异感知:只感知变化的部分,避免重复计算

2.3 决策层(Decision Layer)

职责:基于感知信息,规划下一步行动

核心组件

组件 功能 关键技术
LLM Core 核心推理 Claude 3.5 / 4 系列
Planner 任务分解 将复杂任务拆解为子任务
Tool Selector 工具选择 基于上下文选择最合适的工具
Priority Queue 任务队列 管理待执行任务

决策流程

用户请求 → 意图理解 → 任务分解 → 工具选择 → 参数生成

2.4 执行层(Execution Layer)

职责:调用工具,执行具体操作

核心组件

组件 功能 安全措施
File Editor 文件编辑 原子操作、备份机制
Shell Runner 命令执行 沙箱隔离、超时控制
Git Operator 版本控制 操作审计、回滚能力
Result Validator 结果验证 检查执行结果是否符合预期

执行保障

  1. 原子性:每个操作要么成功,要么回滚
  2. 幂等性:同一操作多次执行结果一致
  3. 可观测性:所有操作都有日志记录

2.5 反馈循环(Feedback Loop)

职责:将执行结果反馈给感知层,形成闭环

反馈类型

类型 说明 处理策略
成功反馈 操作成功完成 更新上下文,继续下一步
错误反馈 操作失败 分析原因,尝试恢复
警告反馈 部分成功 记录警告,评估是否需要干预
用户反馈 用户主动输入 调整策略,响应用户意图

三、工具系统:Agent 的能力边界

3.1 工具接口设计

Claude Code 采用 Tool-Use Pattern,所有能力都封装为统一接口的工具:

interface Tool {
  namestring;           // 工具名称(唯一标识)
  descriptionstring;    // LLM 可理解的描述
  parametersJSONSchema; // 参数的 JSON Schema 定义
  execute(paramsany): Promise<ToolResult>;
}

interface ToolResult {
  successboolean;
  outputstring;
  error?: string;
  metadata?: Record<stringany>;
}

3.2 核心工具清单

文件操作类

工具 用途 关键参数
read_file 读取文件内容 path, offset, limit
write_file 创建或覆盖文件 path, content
edit_file 精确编辑文件 path, oldText, newText
create_directory 创建目录 path
delete_file 删除文件 path

命令执行类

工具 用途 关键参数
execute_command 执行 shell 命令 command, timeout, cwd
run_script 执行脚本文件 script_path, args

搜索类

工具 用途 关键参数
search_files 搜索文件内容 pattern, path, file_pattern
list_directory 列出目录内容 path
find_files 查找文件 pattern, path

Git 操作类

工具 用途 关键参数
git_status 查看状态 path
git_diff 查看差异 path, cached
git_commit 提交更改 message, paths

3.3 工具描述的重要性

每个工具都有 description 字段,这个描述会被 LLM 理解,决定何时、如何调用工具。

好的描述示例

edit_file: 精确编辑文件,只修改指定的文本片段。
适用于:修改函数名、修复 bug、更新配置项。
参数:
- path: 文件路径
- oldText: 要替换的原文(必须精确匹配)
- newText: 替换后的新文本
注意:oldText 必须与文件中完全一致,包括空白字符。

差的描述示例

edit_file: 编辑文件

3.4 工具选择的决策逻辑

Claude Code 如何决定使用哪个工具?

  1. 语义匹配:LLM 理解用户意图,匹配工具描述
  2. 上下文约束:当前上下文限制了可用工具(如未在 Git 仓库中则禁用 Git 工具)
  3. 历史偏好:基于历史成功案例调整选择概率
  4. 参数验证:尝试生成参数,验证是否合法

四、上下文管理:Token 预算下的智慧

4.1 问题背景

LLM 有固定的 token 预算(如 200k),而项目代码可能远超这个限制。如何在有限预算内保留最有价值的信息?

4.2 多级上下文策略

Claude Code 采用多级上下文结构:

Context Layers:
├── System Prompt (固定,约 5k tokens)
├── Project Context (项目级缓存,约 20k tokens)
│   ├── 目录结构树
│   ├── 关键文件摘要
│   ├── 技术栈识别结果
│   └── 依赖关系图
├── Conversation History (对话历史,约 50k tokens)
│   ├── 用户请求序列
│   ├── Agent 行动记录
│   └── 工具调用与结果
└── Working Memory (当前任务,约 125k tokens)
    ├── 当前编辑的文件内容
    ├── 最近命令的输出
    ├── 错误信息栈
    └── 相关代码片段

4.3 上下文压缩技术

文件摘要

对大型文件生成结构化摘要:

{
  "path": "src/core/engine.ts",
  "size": 5000,
  "exports": ["Engine", "Config", "createEngine"],
  "imports": ["./utils", "./types"],
  "key_functions": [
    {"name": "process", "signature": "(data: Data) => Result"},
    {"name": "validate", "signature": "(config: Config) => boolean"}
  ],
  "summary": "核心引擎模块,处理数据流转换和验证"
}

滑动窗口

对话历史使用滑动窗口,保留最近 N 轮对话,更早的对话被压缩为摘要。

差量更新

只传递变化的上下文:

  • 文件修改:只传递 diff
  • 命令输出:只传递新增内容
  • 状态变化:只传递变化字段

4.4 上下文优先级

当 token 预算不足时,按以下优先级截断:

  1. 最高优先级:用户当前请求
  2. 高优先级:当前编辑的文件、最近的错误信息
  3. 中优先级:对话历史中的关键决策
  4. 低优先级:项目级缓存的详细信息
  5. 最低优先级:历史对话的非关键部分

4.5 实现细节

class ContextManager {
  private tokenBudgetnumber = 200000;
  private layersContextLayer[] = [];

  buildContext(taskTask): PromptContext {
    let tokens = 0;
    const contextPromptContext = {};

    // 1. 系统提示词(固定)
    context.system = this.getSystemPrompt();
    tokens += this.countTokens(context.system);

    // 2. 项目上下文(缓存)
    const projectCtx = this.getProjectContext();
    if (tokens + projectCtx.tokens < this.tokenBudget * 0.3) {
      context.project = projectCtx;
      tokens += projectCtx.tokens;
    }

    // 3. 对话历史(滑动窗口)
    const history = this.getRecentHistory(this.tokenBudget * 0.25);
    context.history = history;
    tokens += this.countTokens(history);

    // 4. 工作记忆(剩余预算)
    const workingMemory = this.buildWorkingMemory(
      this.tokenBudget - tokens
    );
    context.working = workingMemory;

    return context;
  }
}

五、决策循环:Agent Loop 的实现

5.1 核心循环结构

def agent_loop(task: Task, context: Context) -> Result:
    iterations = 0
    max_iterations = 50

    while iterations < max_iterations:
        iterations += 1

        # 1. 感知:收集当前状态
        current_state = perceive(context)

        # 2. 决策:LLM 选择行动
        decision = llm.decide(
            system_prompt=AGENT_SYSTEM_PROMPT,
            context=current_state,
            available_tools=TOOLS,
            task=task
        )

        # 3. 执行:调用工具
        if decision.type == "tool_call":
            result = execute_tool(decision.tool, decision.params)

            # 4. 反馈:更新上下文
            context.update(result)

            # 5. 检查是否需要用户确认
            if requires_confirmation(decision):
                user_response = ask_user(decision)
                if not user_response.approved:
                    context.add(user_response.feedback)
                    continue

        # 6. 检查终止条件
        if decision.type == "task_complete":
            return Result(success=True, output=decision.output)

        if decision.type == "need_help":
            return Result(success=False, need_user_input=True)

    return Result(success=False, reason="max_iterations_reached")

5.2 终止条件

Agent 循环在以下情况下终止:

条件 说明 处理
task_complete LLM 认为任务完成 返回成功结果
need_help LLM 需要用户帮助 暂停,等待用户输入
max_iterations 达到最大迭代次数 返回超时错误
error 遇到不可恢复的错误 返回错误信息
user_cancel 用户主动取消 终止执行

5.3 迭代次数的控制

为什么设置 max_iterations?

  1. 成本控制:每次迭代都消耗 API 调用
  2. 防止死循环:Agent 可能陷入无限尝试
  3. 用户体验:长时间无响应会让用户焦虑

典型值:

  • 简单任务:5-10 次
  • 中等任务:20-30 次
  • 复杂任务:50-100 次

5.4 防止退化

Agent 可能陷入以下退化模式:

退化模式 表现 解决方案
重复尝试 反复执行相同操作 检测重复,强制跳过
绕圈子 在多个工具间循环 记录路径,阻止重复序列
过度思考 分析多过行动 设置思考/行动比例限制
放弃过早 轻易声明无法完成 要求提供具体阻碍原因

六、错误恢复:智能体的核心能力

6.1 错误分类

错误类型 示例 恢复策略
参数错误 文件路径不存在 修正参数,重试
权限错误 没有写权限 提示用户,请求权限
依赖错误 缺少包 安装依赖,重试
语法错误 代码有 bug 分析错误,修复代码
网络错误 下载失败 重试,换源
逻辑错误 结果不符合预期 回滚,换策略

6.2 恢复流程

错误发生 → 解析错误信息 → 分类错误类型
         ↓
    选择恢复策略
         ↓
    ┌────┴────┐
    ↓         ↓
  可恢复    不可恢复
    ↓         ↓
  执行恢复   请求用户帮助
    ↓
  验证恢复结果

6.3 错误信息解析

Claude Code 如何理解错误?

def parse_error(error: Exception) -> ErrorInfo:
    """解析错误信息,提取关键要素"""

    error_str = str(error)
    error_type = type(error).__name__

    # 常见错误模式匹配
    patterns = {
        "file_not_found"r"ENOENT.*'([^']+)'",
        "permission_denied"r"EACCES|Permission denied",
        "syntax_error"r"SyntaxError.*line (\d+)",
        "import_error"r"ModuleNotFoundError.*'([^']+)'",
        "command_not_found"r"command not found: (\w+)",
    }

    for error_kind, pattern in patterns.items():
        match = re.search(pattern, error_str)
        if match:
            return ErrorInfo(
                kind=error_kind,
                details=match.groups(),
                raw=error_str
            )

    return ErrorInfo(kind="unknown", raw=error_str)

6.4 恢复策略执行

def execute_recovery(error_info: ErrorInfo, context: Context) -> RecoveryResult:
    """执行恢复策略"""

    strategies = {
        "file_not_found"lambda e: create_file_or_fix_path(e),
        "permission_denied"lambda e: request_permission(e),
        "syntax_error"lambda e: fix_syntax(e, context),
        "import_error"lambda e: install_package(e.details[0]),
        "command_not_found"lambda e: install_command(e.details[0]),
    }

    strategy = strategies.get(error_info.kind, ask_user_for_help)
    return strategy(error_info)

6.5 恢复次数限制

每次操作最多尝试恢复 N 次,超过则放弃并请求用户帮助。

class RecoveryLimiter:
    def __init__(self, max_attempts: int = 3):
        self.attempts = defaultdict(int)
        self.max_attempts = max_attempts

    def can_retry(self, operation_id: str) -> bool:
        return self.attempts[operation_id] < self.max_attempts

    def record_attempt(self, operation_id: str):
        self.attempts[operation_id] += 1

七、人机协作:半自动化的边界

7.1 为什么不是全自动?

  1. 安全考虑rm -rf 等危险操作需要确认
  2. 意图对齐:LLM 可能误解用户意图
  3. 责任归属:用户需要对关键决策负责
  4. 信任建立:逐步建立用户信任

7.2 需要确认的操作

操作类型 触发条件 确认方式
删除文件 rmdelete 命令 显式确认
大规模修改 修改超过 N 个文件 摘要确认
Git 强制操作 force pushreset --hard 显式确认
安装软件 npm installpip install 首次确认
网络请求 访问外部 API 首次确认

7.3 确认交互设计

Agent: 检测到删除操作,确认继续?
       将删除以下文件:
       - /src/old_module.ts
       - /src/deprecated.ts

User:  确认 / 取消 / 查看详情

7.4 学习用户偏好

Claude Code 会学习用户的确认偏好:

class UserPreferenceLearner:
    def __init__(self):
        self.preferences = {
            "auto_approve_npm_install"False,
            "auto_approve_git_commit"False,
            "auto_approve_file_delete"False,
        }

    def learn_from_response(self, operation: str, approved: bool):
        """从用户响应中学习"""
        # 连续 3 次批准同一类操作,自动批准
        key = f"auto_approve_{operation}"
        if approved:
            self.approval_counts[key] = self.approval_counts.get(key, 0) + 1
            if self.approval_counts[key] >= 3:
                self.preferences[key] = True

    def should_auto_approve(self, operation: str) -> bool:
        return self.preferences.get(f"auto_approve_{operation}"False)

7.5 进度可见性

Agent 执行过程中,实时显示:

[1/5] 读取项目结构...
[2/5] 分析依赖关系...
[3/5] 执行重构...
      - 重命名 UserService → AccountService
      - 更新 12 处引用
[4/5] 运行测试...
      ✓ 23 passed, 0 failed
[5/5] 生成总结...

八、安全机制:沙箱与审计

8.1 命令执行沙箱

class CommandSandbox:
    BLACKLIST = [
        "rm -rf /",
        "dd if=",
        ":(){ :|:& };:",  # Fork bomb
        "chmod -R 777",
        "> /dev/sda",
    ]

    def validate(self, command: str) -> ValidationResult:
        # 1. 黑名单检查
        for pattern in self.BLACKLIST:
            if pattern in command:
                return ValidationResult(
                    allowed=False,
                    reason=f"黑名单命令: {pattern}"
                )

        # 2. 权限检查
        if self.requires_elevation(command):
            return ValidationResult(
                allowed=False,
                reason="需要提升权限",
                need_confirmation=True
            )

        # 3. 网络检查
        if self.accesses_network(command) and not self.network_allowed:
            return ValidationResult(
                allowed=False,
                reason="网络访问未授权",
                need_confirmation=True
            )

        return ValidationResult(allowed=True)

8.2 文件访问控制

class FileAccessControl:
    def __init__(self, allowed_paths: List[str]):
        self.allowed_paths = [Path(p).resolve() for p in allowed_paths]

    def can_access(self, path: str, mode: str) -> bool:
        resolved = Path(path).resolve()

        for allowed in self.allowed_paths:
            if str(resolved).startswith(str(allowed)):
                return True

        return False

8.3 操作审计日志

class AuditLogger:
    def log_operation(self, op: Operation):
        entry = {
            "timestamp": datetime.now().isoformat(),
            "operation": op.type,
            "params": op.params,
            "result": op.result,
            "duration_ms": op.duration_ms,
        }
        self.entries.append(entry)

    def export_log(self) -> str:
        return json.dumps(self.entries, indent=2)

九、性能优化:让 Agent 更快

9.1 缓存策略

缓存类型 内容 失效条件
项目结构 目录树、文件列表 文件变化
依赖关系 import 关系图 代码变化
LLM 响应 相同 prompt 的结果 新对话
工具结果 只读操作的结果 输入变化

9.2 并行执行

独立操作并行执行:

async def execute_parallel(operations: List[Operation]):
    tasks = [execute_op(op) for op in operations]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    return results

9.3 流式响应

LLM 响应流式返回,用户可以提前看到部分结果:

Agent: 正在分析代码...
       发现 3 处可以优化的地方:
       1. UserService 的缓存逻辑...
       2. DatabaseManager 的连接池...
       3. Logger 的异步写入...

十、测试与调试

10.1 工具测试

每个工具都有单元测试:

def test_edit_file():
    # 准备测试文件
    test_file = create_test_file("hello world")

    # 执行编辑
    result = edit_file(
        path=test_file,
        oldText="hello",
        newText="goodbye"
    )

    # 验证结果
    assert result.success
    assert read_file(test_file) == "goodbye world"

10.2 Agent 集成测试

def test_agent_refactor():
    """测试重构任务"""
    project = create_test_project("""
    // src/user.ts
    export class UserService {
        getUser(id: string) { ... }
    }
    """
)

    result = agent.execute(
        task="将 UserService 重命名为 AccountService"
    )

    assert result.success
    assert project.has_file("src/account.ts")
    assert project.file_content("src/account.ts").contains("AccountService")

10.3 调试模式

启用调试模式后,输出详细信息:

DEBUG [perception] 扫描目录: src/
DEBUG [perception] 发现文件: 23 个
DEBUG [decision] LLM 输出: {"tool": "read_file", "params": {"path": "src/main.ts"}}
DEBUG [execution] 执行 read_file
DEBUG [execution] 结果: 成功, 1234 tokens
DEBUG [feedback] 上下文更新: +1234 tokens, 当前 15678/200000

十一、总结:Agent 工程化的核心启示

11.1 设计原则

Claude Code 的成功揭示了 AI Agent 工程化的核心原则:

1. 工具优先

先定义能力边界(工具),再设计交互(Prompt)。Agent 能做什么,完全由工具集定义。

2. 反馈为王

错误信息是最好的训练数据。Agent 的智能体现在错误恢复能力,而非单次决策正确率。

3. 上下文是瓶颈

所有优化都围绕 token 预算展开。压缩、缓存、优先级,本质都是在做信息取舍。

4. 人是决策者

危险操作需要确认,模糊意图需要澄清。Agent 是副驾驶,不是驾驶员。

5. 安全内置

沙箱、审计、权限控制,这些不是事后补充,而是架构的一部分。

11.2 技术栈总览

层级 技术选型
LLM Claude 3.5 / 4 系列
编程语言 TypeScript / Python
工具框架 自研 Tool-Use 协议
沙箱 Docker / namespaces
存储 SQLite / 文件系统
日志 结构化 JSON

11.3 未来方向

  1. 多模态支持:理解图片、图表、UI 截图
  2. 主动学习:从用户反馈中持续改进
  3. 协作模式:多 Agent 协作完成复杂任务
  4. 领域特化:针对特定领域(前端、后端、数据)优化

11.4 最终思考

AI Agent 的终极形态,不是「替代人类」,而是「放大人类的意图」。

工具越来越强,但决策权始终在人手中。这才是 Agent 工程化的正确方向。


本文基于公开信息和技术推断撰写,具体实现以官方源码为准。