揭秘Claude Code实现:通过抓包与逆向完全解析

分类:AI功能使用

通过接口抓包代码逆向,我们可以完整了解Claude Code的全貌,并学习其实现来打造自己的Agent。本文基于Go实现的核心代码、完整系统提示词、工具定义及真实API请求,揭秘Agent核心循环、工具分发机制、Prompt Caching策略等关键技术细节。

一、核心循环:极简的Agent设计

打开 agent.go 文件,第374-432行是整个Agent的核心逻辑,令人震撼的是其极简设计:

1.1 主循环代码

func query(cfg Config, messages []Message) ([]Message, error) {
    sysPrompt := fmt.Sprintf(systemPrompt, cfg.WorkDir)

    for idx := 0; idx < maxAgentIterations; idx++ {
        spin := newSpinner("Waiting for model")
        spin.Start()
        resp, err := callOpenAI(cfg, fullMessages)
        spin.Stop()

        if err != nil {
            return messages, err
        }

        // 打印文本内容
        if assistantMsg.Content != "" {
            fmt.Println(assistantMsg.Content)
        }

        // 检查是否有 tool calls
        if choice.FinishReason == "tool_calls" && len(assistantMsg.ToolCalls) > 0 {
            // 执行所有工具
            for _, tc := range assistantMsg.ToolCalls {
                result := dispatchToolCall(cfg, tc)
                messages = append(messages, result)
                fullMessages = append(messages, result)
            }
            continue
        }

        // 跟踪没有使用 todo 的轮次
        agentState.mu.Lock()
        agentState.roundsWithoutTodo++
        if agentState.roundsWithoutTodo > 10 {
            ensureContextBlock(nagReminder)
        }
        agentState.mu.Unlock()

        return messages, nil
    }

    return messages, errors.New("agent max iterations reached")
}

核心逻辑可以总结为三步

  • 调用模型 - 等待LLM响应
  • 执行工具 - 如果模型请求工具调用,执行并返回结果
  • 循环 - 重复直到模型返回最终答案或达到最大迭代次数

💡 设计精髓

对比传统Agent框架动辄几千行的状态管理代码,Claude Code这种极简设计令人震撼。没有复杂的状态机,没有繁琐的调度器,只有最纯粹的"思考-行动-观察"循环。

1.2 工具分发:Unix哲学的体现

第515-567行的 dispatchToolCall 函数展示了工具调用的处理方式:

func dispatchToolCall(cfg Config, tc ToolCall) Message {
    // 解析参数
    var input map[string]interface{}
    json.Unmarshal([]byte(tc.Function.Arguments), &input)

    var result string
    var err error

    // 分发到具体工具
    switch tc.Function.Name {
    case "Bash":
        result, err = runBash(cfg, input)
    case "Read":
        result, err = runRead(cfg, input)
    case "Write":
        result, err = runWrite(cfg, input)
    case "Edit":
        result, err = runEdit(cfg, input)
    case "TodoWrite":
        result, err = runTodoUpdate(cfg, input)
    default:
        err = fmt.Errorf("unknown tool: %s", tc.Function.Name)
    }

    if err != nil {
        result = err.Error()
    }

    return Message{
        Role:       "tool",
        ToolCallID: tc.ID,
        Name:       tc.Function.Name,
        Content:    clampText(result, cfg.MaxResult),
    }
}

每个工具都是独立的纯函数,输入参数,输出结果,不维护任何状态。这正是Unix哲学"Do one thing and do it well"的代码体现。

二、Todo管理:模型的自我追踪

Claude Code实现了一个巧妙的Todo系统,让模型能够自我追踪任务进度:

2.1 Todo更新机制

func runTodoUpdate(cfg Config, input map[string]interface{}) (string, error) {
    itemsList, ok := input["items"].([]interface{})
    if !ok {
        return "", errors.New("items must be an array")
    }

    items := make([]TodoItem, 0, len(itemsList))
    for i, rawItem := range itemsList {
        itemMap, ok := rawItem.(map[string]interface{})
        if !ok {
            return "", fmt.Errorf("item %d is not an object", i)
        }

        items = append(items, TodoItem{
            ID:         getString(itemMap, "id"),
            Content:    getString(itemMap, "content"),
            Status:     getString(itemMap, "status"),
            ActiveForm: getString(itemMap, "activeForm"),
        })
    }

    // 更新全局状态并渲染看板
    boardView, err := renderTodoBoard(items)
    return boardView, err
}

2.2 上下文注入策略

当模型超过10轮没有使用Todo工具时,系统会自动注入提醒:

if agentState.roundsWithoutTodo > 10 {
    ensureContextBlock(nagReminder)
}

这个提醒被包装在 <system-reminder> 标签里,并明确告诉模型不要提及这个提醒,这是一种"隐形引导"——影响模型行为但对用户透明。

三、系统提示词:行为的塑造者

系统提示词定义了Claude Code的核心行为准则,包含以下关键部分:

  • 身份定义:"You are Claude Code, Anthropic's official CLI for Claude."
  • 工作目录:动态注入当前工作路径,让模型理解上下文环境。
  • 工具使用策略:详细说明何时使用Read、Write、Edit、Bash等工具。
  • Todo管理规范:要求模型在复杂任务中主动维护Todo列表。
  • 输出格式要求:指导模型如何组织回复内容,保持简洁专业。

⚠️ 提示词的威力

系统提示词是Agent能力的边界。Claude Code通过精心设计的提示词,让模型在没有复杂状态管理的情况下,依然能够处理复杂的多步骤任务。

四、工具定义:能力的边界

Claude Code提供了15+核心工具,每个工具都有完整的JSON Schema定义:

4.1 核心工具列表

  • Bash - 执行Shell命令
  • Read - 读取文件内容
  • Write - 写入文件
  • Edit - 编辑文件(搜索替换)
  • TodoWrite - 更新Todo列表
  • GrepSearch - 代码搜索
  • ListDir - 列出目录内容

4.2 MCP工具:插件化扩展

除了核心工具,Claude Code还支持通过MCP(Model Context Protocol)协议接入外部工具:

{
  "name": "mcp__ide__getDiagnostics",
  "description": "Get language diagnostics from VS Code"
},
{
  "name": "mcp__ide__executeCode",
  "description": "Execute python code in the Jupyter kernel..."
}

这些以 mcp__ 前缀的工具来自外部MCP服务器。这是一种插件化架构:核心保持简洁,能力可无限扩展,第三方可贡献工具。

五、Prompt Caching:成本优化的秘密武器

从实际API请求中可以看到多处 "cache_control": {"type": "ephemeral"},这是Anthropic的Prompt Caching特性:

5.1 缓存策略

  • System消息缓存 - 系统提示词几乎不变,每次请求复用缓存
  • Tool定义缓存 - 工具Schema很大但固定,缓存后省90% token
  • 长文档缓存 - 读取的文件内容标记为可缓存

5.2 实际请求示例

{
  "model": "claude-sonnet-4-5-20250929",
  "system": [
    {
      "type": "text",
      "text": "You are Claude Code, Anthropic's official CLI...",
      "cache_control": {"type": "ephemeral"}
    }
  ],
  "tools": [...],  // 工具定义也被缓存
  "max_tokens": 32000,
  "stream": true
}

💰 成本节省

据Anthropic披露,Prompt Caching可节省90%的输入token费用。这使得Claude Code能够在每次请求中携带完整的系统提示词和工具定义,而不会产生高昂的成本。

六、多模态内容组织

User消息可以包含多个content blocks,系统可以在用户输入前后插入任意数量的上下文:

{
  "role": "user",
  "content": [
    {"type": "text", "text": "<system-reminder>...</system-reminder>"},
    {"type": "text", "text": "IDE打开文件的提醒"},
    {"type": "text", "text": "CLAUDE.md的内容"},
    {"type": "text", "text": "用户的实际输入"}
  ]
}

这种结构让系统可以灵活地注入各种上下文信息,且保持清晰的分隔。

七、工具调用的完整流程

从请求中可以看到一个完整的工具使用循环:

第1轮(Assistant主动)

{
  "role": "assistant",
  "content": [
    {"type": "text", "text": "我来审查代码"},
    {"type": "tool_use", "name": "Read", "input": {...}},
    {"type": "tool_use", "name": "Read", "input": {...}}
  ]
}

第2轮(User返回结果)

{
  "role": "user",
  "content": [
    {"type": "tool_result", "tool_use_id": "...", "content": "文件内容..."}
  ]
}

第3轮(Assistant继续)

{
  "role": "assistant",
  "content": [
    {"type": "text", "text": "根据文档分析..."}
  ]
}

这是标准的OpenAI Function Calling协议,但Anthropic的实现更灵活:允许在一轮中同时调用多个工具

八、关键技术总结

通过对Claude Code的完整解析,我们可以提炼出以下关键技术点:

  • 极简循环 - 不到100行代码实现完整Agent逻辑
  • 纯函数工具 - 每个工具独立无状态,易于测试和扩展
  • 智能缓存 - 通过Prompt Caching节省90%成本
  • 插件化架构 - MCP协议支持无限扩展能力
  • 隐形引导 - 通过上下文注入影响模型行为
  • 自我追踪 - Todo系统让模型管理复杂任务

🎯 学习价值

Claude Code的实现为我们提供了一个优秀的Agent设计范本。它证明了:简单的设计往往比复杂的框架更有效。通过精心设计的提示词和工具定义,配合智能的缓存策略,就能打造出强大而高效的AI Agent。

常见问题

  • Q: 如何获取Claude Code的源代码?
    A: Claude Code是开源项目,可以在GitHub上找到相关实现。抓包工具claude-trace也可以帮助你分析实际的API请求。
  • Q: Prompt Caching如何启用?
    A: 在API请求中为需要缓存的内容添加 cache_control: {type: "ephemeral"} 标记即可。
  • Q: MCP协议如何集成?
    A: 可以参考Cursor MCP配置教程了解详细集成方法。