Claude Code CLI 是一个成熟的 AI Agent 实现。它不是简单的 "发送消息→接收响应",而是一个复杂的、多层次的 Agent 系统。这个系列将从 Agent 设计模式的角度,深入分析 Claude Code 的架构。
为什么研究 Claude Code?
Claude Code 是一个生产级的 AI Agent:
- 真实场景:不是演示项目,而是每天被数千开发者使用的工具
- 复杂任务:处理文件编辑、命令执行、多步任务编排
- 安全边界:严格的权限控制,沙箱执行
- 用户交互:实时进度、权限对话框、错误反馈
- 扩展性:Skills、Hooks、MCP 协议
这些特性让它成为一个绝佳的 Agent 设计参考。
本系列主题
我们将从 11 个角度分析 Agent 设计:
| 篇数 | 主题 | 核心问题 |
|---|---|---|
| 01 | Agent 生命周期 | Agent 如何启动、运行、终止?状态如何流转? |
| 02 | 工具编排 | 30+ 工具如何统一管理?执行流水线如何设计? |
| 03 | 上下文管理 | Token 预算如何分配?文件状态如何追踪? |
| 04 | 子 Agent 架构 | Fork 模式如何工作?父子 Agent 如何通信? |
| 05 | MCP 协议集成 | 外部工具如何接入?协议如何抽象? |
| 06 | 对话压缩 | Token 超限时如何压缩?信息如何保留? |
| 07 | 记忆系统 | 如何跨会话记忆?持久化策略是什么? |
| 08 | 权限决策 | 如何判断操作安全?AI 分类器如何辅助? |
| 09 | 流式响应 | 如何实时显示进度?中断如何处理? |
| 10 | 并发与调度 | 多 Agent 如何并发?资源如何管理? |
| 11 | 系列总结 | 整体架构回顾,设计原则提炼 |
设计哲学
在深入细节之前,先看 Claude Code 的设计哲学:
1. AsyncGenerator 为核心
async function* query({ messages, ... }): AsyncGenerator<Message> {
for await (const event of streamEvents) {
if (event.type === 'content_block_start') { ... }
if (event.type === 'content_block_delta') { ... }
if (event.type === 'message_stop') { ... }
yield message
}
}
不是一次性返回结果,而是流式生成消息。这让 UI 可以实时更新。
2. 工具是独立的 Agent 能力单元
type Tool = {
name: string
call(args, context): Promise<ToolResult>
checkPermissions(input): Promise<PermissionResult>
isConcurrencySafe(input): boolean
isReadOnly(input): boolean
}
每个工具封装一个能力,有自己的权限检查、并发声明。
3. 上下文是共享状态容器
type ToolUseContext = {
abortController: AbortController
readFileState: FileStateCache
getAppState(): AppState
messages: Message[]
options: { tools, commands, mcpClients, ... }
}
所有执行状态在 Context 中——文件读取状态、消息历史、工具列表。
4. Hooks 是生命周期注入点
type HookEvent =
| 'PreToolUse' | 'PostToolUse'
| 'SessionStart' | 'SessionEnd'
| 'PreCompact' | 'PostCompact'
关键事件可以注入自定义逻辑——验证、日志、通知。
5. 安全是分层防御
// 第一层:工具自身检查
tool.checkPermissions(input, context)
// 第二层:规则匹配
checkPermissionRules(toolName, input)
// 第三层:模式检查
checkPermissionMode(mode)
// 第四层:AI 分类器
classifyBashCommand(command)
不是单一检查点,而是层层把关。
核心架构图
用户输入
│
▼
QueryEngine (会话生命周期管理)
│
▼
query() (核心循环 AsyncGenerator)
│
├─► API 调用 (Anthropic/Bedrock/Vertex)
│ │
│ ▼
│ 流式事件处理
│ │
│ ├─► 文本块 → yield Message
│ │
│ ├─► 工具调用 → 工具执行
│ │ │
│ │ ├─► 权限检查
│ │ ├─► 执行 call()
│ │ ├─► Hook 触发
│ │ └─► yield ToolResult
│ │
│ └─► 消息结束 → 检查继续
│
└─► 对话压缩 (Token 超限)
│
└─► 子 Agent (AgentTool)
│
├─► Fork 模式
├─► 独立 Context
└─► 独立 query() 循环
与传统 CLI 的区别
传统 CLI:
用户输入 → 解析 → 执行 → 输出 → 结束
Claude Code:
用户输入 → Agent 思考 → 可能多次执行 → 可能多个工具 → 可能多个子Agent → 最终响应 → 可能继续...
这是一个开放式循环,结束条件由 Agent 决定,不是用户命令决定。
本系列读者
如果你是:
- AI Agent 开发者:想了解生产级 Agent 的设计
- CLI 开发者:想设计更智能的 CLI 工具
- 安全工程师:想理解 AI Agent 的安全边界
- 产品设计师:想思考 AI 工具的用户体验
这个系列对你都有价值。
下篇预告
下一篇,我们将深入 Agent 生命周期——看看 QueryEngine 如何管理会话状态,Agent 如何启动、暂停、恢复、终止。