Learn Claude Code

从零构建类似 Claude Code 的 AI Coding Agent

核心架构

                    THE AGENT PATTERN
                    =================

    User --> messages[] --> LLM --> response
                                      |
                            stop_reason == "tool_use"?
                           /                          \
                         yes                           no
                          |                             |
                    execute tools                    return text
                    append results
                    loop back -----------------> messages[]

核心循环代码:

def agent_loop(messages):
    while True:
        response = LLM(messages, tools)
 
        if response.stop_reason != "tool_use":
            return  # 完成
 
        # 执行工具调用
        for block in response.content:
            if block.type == "tool_use":
                output = TOOL_HANDLERS[block.name](**block.input)
                results.append(tool_result(output))
 
        messages.append(results)  # 结果返回给模型,继续循环

12 个递进式课程

第一阶段:循环基础

s01 - Agent 循环

“One loop & Bash is all you need”

核心:

  • 一个 while True 循环
  • 一个 bash 工具
  • 检查 stop_reason 决定是否继续
while (true) {
  const response = await client.messages.create({...});
  if (response.stop_reason !== "tool_use") return;
  // 执行工具,结果追加到 messages,继续循环
}

s02 - Tool Use

“加一个工具,只加一个 handler”

核心:

  • 工具注册到 TOOLS 数组
  • 处理器注册到 TOOL_HANDLERS map
  • 循环逻辑不变
const TOOL_HANDLERS = {
  bash: (input) => runBash(input.command),
  read_file: (input) => runRead(input.path),
  write_file: (input) => runWrite(input.path, input.content),
  edit_file: (input) => runEdit(input.path, input.old_text, input.new_text),
};

第二阶段:规划与知识

s03 - TodoWrite

“没有计划的 agent 走哪算哪”

核心:

  • TodoManager 类管理任务列表
  • Nag Reminder:3 轮未更新 todo 则注入提醒
  • 任务状态:[ ] pending / [>] in_progress / [x] completed
class TodoManager {
  items: TodoItem[];
  update(items): string;  // 更新并验证
  render(): string;       // 格式化输出
}

s04 - Subagents

“大任务拆小,每个小任务干净的上下文”

核心:

  • 子 agent 使用全新的 messages[]
  • 完成后只返回摘要给父 agent
  • 父 agent 上下文保持干净
async function runSubagent(prompt: string): Promise<string> {
  const childMessages = [{ role: "user", content: prompt }];
  // 子 agent 独立运行,不污染父上下文
  const result = await agentLoop(childMessages);
  return result.slice(0, 8000);  // 只返回摘要
}

s05 - Skills

“用到什么知识,临时加载什么知识”

核心:

  • Layer 1:系统提示中只放技能元数据(~100 tokens/skill)
  • Layer 2:通过 load_skill 工具按需加载完整内容
skills/
  pdf/SKILL.md      # frontmatter(元数据) + body(完整指令)
  code-review/SKILL.md
class SkillLoader {
  getDescriptions(): string;  // Layer 1: 短描述
  getContent(name): string;   // Layer 2: 完整内容
}

s06 - Context Compact

“上下文总会满,要有办法腾地方”

三层压缩策略:

  1. micro_compact:每轮静默替换旧工具结果为占位符
  2. auto_compact:Token 超过阈值时自动压缩,保存完整记录并生成摘要
  3. manual_compact:模型调用 compact 工具手动触发
function estimateTokens(messages): number {
  return JSON.stringify(messages).length / 4;  // 粗略估算
}
 
async function autoCompact(messages): Promise<Message[]> {
  // 1. 保存完整记录到 .transcripts/
  // 2. 让 LLM 生成摘要
  // 3. 返回压缩后的 messages
}

第三阶段:持久化

s07 - Task System

“大目标要拆成小任务,排好序,记在磁盘上”

核心:

  • 任务以 JSON 文件持久化在 .tasks/ 目录
  • 支持依赖图(blockedBy / blocks
  • 任务完成时自动解除其他任务的阻塞
.tasks/
  task_1.json  {"id":1, "status":"completed", ...}
  task_2.json  {"id":2, "blockedBy":[1], ...}
class TaskManager {
  create(subject, description): string;
  update(taskId, status, addBlockedBy, addBlocks): string;
  listAll(): string;
}

s08 - Background Tasks

“慢操作丢后台,agent 继续想下一步”

核心:

  • 后台线程执行命令
  • 完成后将通知注入消息队列
  • Agent 循环开始时排空通知
class BackgroundManager {
  run(command): string;       // 返回 task_id
  check(taskId): string;      // 检查状态
  drain(): Notification[];    // 排空通知
}

第四阶段:团队协作

s09 - Agent Teams

“任务太大一个人干不完,要能分给队友”

核心:

  • 持久化队友配置(.team/config.json
  • JSONL 格式的收件箱(.team/inbox/alice.jsonl
  • 每个队友独立运行 agent 循环
Subagent (s04):  spawn -> execute -> return summary -> destroyed
Teammate (s09):  spawn -> work -> idle -> work -> ... -> shutdown
class MessageBus {
  send(from, to, content, msgType): string;
  readInbox(name): Message[];  // 读取并清空
  broadcast(from, content, teammates): string;
}

s10 - Team Protocols

“队友之间要有统一的沟通规矩”

两个协议:

  1. Shutdown Protocol:优雅关闭队友

    • shutdown_requestshutdown_response
  2. Plan Approval Protocol:计划审批

    • 队友提交计划 → lead 审批 → 队友执行
// 请求 ID 关联请求和响应
const shutdownRequests: Record<string, ShutdownRequest> = {};
const planRequests: Record<string, PlanRequest> = {};

s11 - Autonomous Agents

“队友自己看看板,有活就认领”

核心:

  • Work Phase:正常 agent 循环,最多 50 轮
  • Idle Phase:轮询收件箱 + 扫描未认领任务
  • 自动认领:claim_task(taskId)
  • 身份重注入:压缩后恢复上下文
while (running) {
  // Work Phase
  for (let i = 0; i < 50; i++) {
    // 正常 agent 循环
    if (idleRequested) break;
  }
 
  // Idle Phase: 轮询新任务
  setStatus("idle");
  for (let i = 0; i < polls; i++) {
    await sleep(POLL_INTERVAL);
    if (inbox.length > 0 || unclaimedTasks.length > 0) {
      resume = true;
      break;
    }
  }
  if (!resume) shutdown();
}

s12 - Worktree Isolation

“各干各的目录,互不干扰”

核心:

  • 任务管目标,worktree 管目录
  • 按 task_id 绑定
  • 每个 agent 在独立目录工作
interface Task {
  id: number;
  worktree?: string;  // 绑定的目录
}

完整架构图

┌─────────────────────────────────────────────────────────────┐
│                        Lead Agent                            │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐        │
│  │ TodoMgr │  │ Skills  │  │ TaskMgr │  │ BgMgr   │        │
│  └────┬────┘  └────┬────┘  └────┬────┘  └────┬────┘        │
│       │            │            │            │              │
│       └────────────┴────────────┴────────────┘              │
│                          │                                   │
│                    Agent Loop                                │
│                          │                                   │
│       ┌──────────────────┼──────────────────┐               │
│       ▼                  ▼                  ▼               │
│  ┌─────────┐       ┌─────────┐       ┌─────────┐           │
│  │ Teammate│       │ Teammate│       │ Teammate│           │
│  │  Alice  │       │   Bob   │       │  Carol  │           │
│  │ worktree│       │ worktree│       │ worktree│           │
│  └────┬────┘       └────┬────┘       └────┬────┘           │
│       │                 │                 │                 │
│       └─────────────────┼─────────────────┘                 │
│                         ▼                                   │
│                   ┌───────────┐                             │
│                   │ MessageBus│  (JSONL inboxes)            │
│                   └───────────┘                             │
└─────────────────────────────────────────────────────────────┘

关键设计原则

  1. 循环不变:所有功能通过工具和处理器扩展,核心循环始终不变
  2. 分层注入:系统提示放元数据,tool_result 放完整内容
  3. 文件持久化:状态存磁盘,不怕上下文压缩
  4. 异步消息:JSONL 收件箱实现队友间通信
  5. 自组织:空闲轮询 + 自动认领,无需中央分配

参考


AI Agent Claude TypeScript 学习笔记