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_HANDLERSmap - 循环逻辑不变
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
“上下文总会满,要有办法腾地方”
三层压缩策略:
- micro_compact:每轮静默替换旧工具结果为占位符
- auto_compact:Token 超过阈值时自动压缩,保存完整记录并生成摘要
- 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
“队友之间要有统一的沟通规矩”
两个协议:
-
Shutdown Protocol:优雅关闭队友
shutdown_request→shutdown_response
-
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) │
│ └───────────┘ │
└─────────────────────────────────────────────────────────────┘
关键设计原则
- 循环不变:所有功能通过工具和处理器扩展,核心循环始终不变
- 分层注入:系统提示放元数据,tool_result 放完整内容
- 文件持久化:状态存磁盘,不怕上下文压缩
- 异步消息:JSONL 收件箱实现队友间通信
- 自组织:空闲轮询 + 自动认领,无需中央分配
参考
- GitHub: https://github.com/chelseachen007/learn-claude-code
- 原项目: https://github.com/shareAI-lab/learn-claude-code
- Claude Code 官方: https://docs.anthropic.com/claude-code
- Site Unreachable