核心系统

查询管线

从你敲下回车到 Claude 回复的完整旅程

~8 分钟阅读

0

核心代码行数

0

管线文件

0

处理阶段

查询管线就像一个餐厅的完整点餐流程。

你(顾客)对服务员说了一句话 → 服务员把它翻译成厨房能懂的完整订单(加上你的过敏信息、座位号等)→ 厨房做菜(Claude 思考回答)→ 如果需要食材,派人去仓库取(调用工具)→ 取回食材后继续做菜 → 最终端上来(回复你)。

整个过程是流式的 — 就像日料的 omakase,一道道上,不是一次端上所有菜。

消息流水线 #

点击每个节点查看详细说明

预处理
注入上下文
发送请求
tool_use
执行结果

系统提示构建 #

Claude 实际收到的完整指令

~5KB

默认系统提示

定义 Claude Code 的身份、能力、行为规范

~1KB

用户环境信息

操作系统、Shell、工作目录、git 状态、当前日期

~20KB

工具定义

45+ 工具的名称、描述、输入 JSON Schema

可变

项目规则

CLAUDE.md / .claude/config.json 中的用户自定义规则

可变

记忆附件

之前对话中保存的记忆、文件引用

API 实际看到的数据 #

Claude Code 的真实请求和响应结构

这是 Claude Code 发送给 Anthropic API 的内容。系统提示、对话历史和所有 45+ 工具定义被打包到一个流式请求中。

// POST https://api.anthropic.com/v1/messages (stream: true)
{
  "model": "claude-sonnet-4-20250514",
  "max_tokens": 16384,
  "stream": true,
  "system": [
    {
      "type": "text",
      "text": "You are Claude Code, Anthropic's official CLI..."
      // ~5KB of system prompt
    },
    {
      "type": "text",
      "text": "# Environment\nPlatform: darwin\nShell: zsh\nCwd: /Users/dev/myproject\n..."
    }
  ],
  "messages": [
    {
      "role": "user",
      "content": "Help me fix the failing test in src/utils.ts"
    }
  ],
  "tools": [
    {
      "name": "Bash",
      "description": "Execute shell commands...",
      "input_schema": {
        "type": "object",
        "properties": {
          "command": { "type": "string" },
          "timeout": { "type": "number" }
        },
        "required": ["command"]
      }
    }
    // ... 44 more tool definitions
  ],
  "metadata": {
    "user_id": "user_abc123"
  }
}

流式处理 #

为什么回复是一个字一个字蹦出来的?

想象水龙头和水桶的区别。传统方式是等水桶装满了再端过来(等完整回复),Claude Code 用的是水龙头模式 — 水一出来就流到你杯子里。技术上这叫 "async generator",一种让数据像水流一样一点点传输的编程技巧。好处:响应快、内存小、随时可以关掉水龙头(取消操作)。

工具调用循环 #

Claude 是如何不断调用工具直到完成任务的?

  1. 1 Claude 的响应中包含 tool_use 块("我想读取 src/main.tsx")
  2. 2 权限系统评估:这个操作安全吗?→ 通过后执行工具
  3. 3 工具执行结果作为 tool_result 消息追加到对话历史
  4. 4 带着新的对话历史再次调用 API — Claude 看到工具结果后决定下一步
  5. 5 重复直到 Claude 返回 stop_reason: "end_turn"(任务完成)

交互式代码走读 #

逐步点击查询管线的执行过程

src/query.ts入口:submitMessage()
第 1 步 / 共 6 步
1// src/query.ts — The core conversation loop
2async function* submitMessage(
3 prompt: string,
4 deps: QueryDeps
5): AsyncGenerator<MessageUpdate> {
6 // Assemble full context for Claude
7 const systemPrompt = (deps);
8 const messages = (deps.messages, prompt);
9
10 // Stream response from API
11 const stream = ({
12 model: deps.model,
13 system: systemPrompt,
14 messages,
15 tools: deps.tools,
16 });
17
18 for await (const event of stream) {
19 yield processStreamEvent(event);
20 }
21
22 // If Claude called tools, execute them and loop
23 if (hasToolUse(response)) {
24 yield* (response.toolUses, deps);
25 yield* submitMessage("", deps); // ← recursive
26 }
27}

一切从这里开始。submitMessage() 是一个 async generator,编排整个对话轮次 — 从接收用户提示到流式返回 Claude 的响应。

点击高亮的函数名跟踪调用链