适用版本: OpenClaw v2026.3 阅读时间: 约 30 分钟 前置知识: 阅读前五篇文章,理解系统全貌 源码位置: 整体架构视角
开篇:为什么需要架构复盘?
前五篇文章,我们深入剖析了 OpenClaw 的各个组件。现在,是时候退后一步,审视整个架构:
OpenClaw 的架构设计有哪些亮点?有哪些不足?我们能从中学到什么?
架构复盘不是挑刺,而是:
flowchart TB
subgraph Review["架构复盘"]
R1["理解设计意图"]
R2["评估实现效果"]
R3["总结经验教训"]
end
subgraph Output["输出"]
O1["架构知识"]
O2["改进建议"]
O3["设计原则"]
end
Review --> Output
style Review fill:#e8f5e9
style Output fill:#fff3e0
本文将从以下维度审视 OpenClaw:
- 分层设计——架构是否合理?
- 设计模式——应用是否得当?
- 技术债务——哪些地方需要改进?
- 竞品对比——优劣势在哪里?
- 未来启示——AI Agent 平台的发展方向?
分层设计:四层架构的合理性
OpenClaw 的四层架构
flowchart TB
subgraph L4["第四层:渠道层 (Channels)"]
C1["WhatsApp"]
C2["Telegram"]
C3["Slack"]
C4["Web UI"]
end
subgraph L3["第三层:会话层 (Sessions)"]
S1["Session Manager"]
S2["Session Router"]
S3["Transcript Store"]
end
subgraph L2["第二层:Agent 层 (Agents)"]
A1["ACP Runtime"]
A2["Tool Executor"]
A3["Pi Agent"]
end
subgraph L1["第一层:Gateway 层 (Gateway)"]
G1["WebSocket Server"]
G2["Method Handler"]
G3["Event Bus"]
end
L4 --> L3 --> L2 --> L1
style L4 fill:#e3f2fd
style L3 fill:#fff3e0
style L2 fill:#e8f5e9
style L1 fill:#fce4ec
分层评估
| 层次 | 职责 | 耦合度 | 评价 |
|---|---|---|---|
| Gateway | 通信入口、协调调度 | 低 | ✅ 职责清晰 |
| Agents | AI 逻辑、工具执行 | 中 | ⚠️ 与 Session 有一定耦合 |
| Sessions | 会话管理、状态持久化 | 中 | ⚠️ 依赖较多 |
| Channels | 消息适配、平台集成 | 低 | ✅ 插件化设计好 |
设计亮点
1. 控制平面与数据平面分离
flowchart LR
subgraph Control["控制平面 (Gateway)"]
C1["路由决策"]
C2["状态协调"]
C3["生命周期管理"]
end
subgraph Data["数据平面 (Channels/Agents)"]
D1["消息传输"]
D2["内容处理"]
D3["LLM 调用"]
end
Control --> |控制指令| Data
Data --> |状态反馈| Control
style Control fill:#e8f5e9
style Data fill:#e3f2fd
这是现代分布式系统的经典设计:
- Kubernetes:API Server(控制面)+ Kubelet(数据面)
- Service Mesh:Control Plane + Data Plane
- SDN:Controller + Switch
好处: 控制逻辑集中管理,数据路径独立演进。
2. 插件化的 Channel 层
// 新增渠道只需实现接口
interface ChannelPlugin {
id: ChannelId;
start(context: ChannelContext): Promise<void>;
stop(): Promise<void>;
sendMessage(params: SendMessageParams): Promise<void>;
onMessage(callback: MessageCallback): void;
}
好处:
- 新增渠道不影响核心代码
- 每个渠道可以独立测试
- 社区可以贡献插件
3. ACP 协议的抽象层
// 统一不同 LLM 后端的接口
interface AcpRuntime {
ensureSession(input): Promise<AcpRuntimeHandle>;
runTurn(input): AsyncIterable<AcpRuntimeEvent>;
cancel(input): Promise<void>;
close(input): Promise<void>;
}
好处:
- 切换 LLM 提供商无需修改上层代码
- 支持"Bring Your Own Model"
- 未来可以接入更多 AI 服务
设计不足
1. Session 与 Agent 的边界模糊
flowchart TB
subgraph Problem["问题:职责重叠"]
S["Session Manager<br/>管理会话状态"]
A["Agent Runtime<br/>管理对话上下文"]
O["重叠:<br/>Transcript 既在 Session 也在 Agent"]
end
S --> O
A --> O
style Problem fill:#ffcdd2
问题: Transcript(对话历史)既在 Session 中持久化,又在 Agent 中作为上下文传递。两者职责有重叠。
改进建议: 明确分工:
- Session:身份、权限、配置
- Agent:对话上下文、工具状态
2. 配置管理过于分散
# 配置分布在多处
~/.openclaw/openclaw.yaml # 主配置
~/.openclaw/agents/*.yaml # Agent 配置
~/.openclaw/channels/*.yaml # Channel 配置
环境变量 # 敏感信息
命令行参数 # 运行时覆盖
问题: 配置来源多,优先级不清晰,调试困难。
改进建议: 统一配置模型,类似 Viper 的分层配置:
- 默认值
- 配置文件
- 环境变量
- 命令行参数
设计模式:实战中的应用
观察到的设计模式
flowchart TB
subgraph Patterns["设计模式"]
P1["策略模式<br/>认证策略"]
P2["插件模式<br/>Channel/Tool"]
P3["观察者模式<br/>事件系统"]
P4["工厂模式<br/>Agent 创建"]
P5["适配器模式<br/>LLM 后端"]
end
style Patterns fill:#e8f5e9
模式分析
1. 策略模式:认证系统
// 策略接口
interface AuthProvider {
validate(headers: Headers): Promise<AuthResult>;
}
// 具体策略
class TokenAuth implements AuthProvider { ... }
class PasswordAuth implements AuthProvider { ... }
class TailscaleAuth implements AuthProvider { ... }
// 策略选择
function createAuthProvider(config: Config): AuthProvider {
switch (config.auth.method) {
case "token": return new TokenAuth(config);
case "password": return new PasswordAuth(config);
case "tailscale": return new TailscaleAuth(config);
}
}
评价: ✅ 应用得当
- 新增认证方式无需修改 Gateway
- 认证策略可以独立测试
- 运行时可以切换策略
2. 插件模式:Channel 系统
// 插件接口
interface ChannelPlugin {
id: ChannelId;
start(context: ChannelContext): Promise<void>;
// ...
}
// 插件加载器
class PluginLoader {
async load(path: string): Promise<ChannelPlugin> {
const module = await import(path);
return new module.default();
}
}
// 插件注册表
class ChannelRegistry {
private channels = new Map<ChannelId, ChannelPlugin>();
register(channel: ChannelPlugin): void {
this.channels.set(channel.id, channel);
}
}
评价: ✅ 应用得当
- 支持动态加载
- 核心与插件解耦
- 社区可贡献
3. 观察者模式:事件系统
// 事件类型
type GatewayEvent =
| { type: "message:received"; message: NormalizedMessage }
| { type: "message:sent"; response: string }
| { type: "session:created"; sessionKey: string }
| { type: "agent:turn:complete"; tokens: TokenUsage };
// 事件发射器
class EventEmitter {
private listeners = new Map<string, Set<EventListener>>();
on(event: string, listener: EventListener): void {
if (!this.listeners.has(event)) {
this.listeners.set(event, new Set());
}
this.listeners.get(event)!.add(listener);
}
emit(event: string, data: any): void {
const listeners = this.listeners.get(event);
if (listeners) {
for (const listener of listeners) {
listener(data);
}
}
}
}
评价: ✅ 应用得当
- 组件间松耦合通信
- 支持多个订阅者
- 便于扩展(Hook 系统)
4. 适配器模式:LLM 后端
// 目标接口(ACP)
interface AcpRuntime {
runTurn(input): AsyncIterable<AcpRuntimeEvent>;
}
// 适配器
class OpenAIAdapter implements AcpRuntime {
private client: OpenAI;
async *runTurn(input): AsyncIterable<AcpRuntimeEvent> {
// 将 OpenAI API 响应转换为 ACP 事件
const stream = await this.client.chat.completions.create({
model: "gpt-4",
messages: this.convertMessages(input),
stream: true,
});
for await (const chunk of stream) {
yield {
type: "text_delta",
text: chunk.choices[0]?.delta?.content || "",
};
}
}
}
评价: ✅ 应用得当
- 统一不同 API
- 隔离外部变化
- 支持渐进式迁移
模式应用总结
| 模式 | 应用场景 | 效果 | 改进空间 |
|---|---|---|---|
| 策略模式 | 认证 | ✅ 好 | - |
| 插件模式 | Channel/Tool | ✅ 好 | 增加依赖注入 |
| 观察者模式 | 事件系统 | ✅ 好 | 增加事件溯源 |
| 工厂模式 | Agent 创建 | ⚠️ 一般 | 可用抽象工厂 |
| 适配器模式 | LLM 后端 | ✅ 好 | - |
技术债务:诚实的评估
识别的技术债务
flowchart TB
subgraph Debt["技术债务"]
D1["代码债务"]
D2["架构债务"]
D3["文档债务"]
D4["测试债务"]
end
subgraph Impact["影响"]
I1["维护成本高"]
I2["新人上手难"]
I3["功能迭代慢"]
end
Debt --> Impact
style Debt fill:#ffcdd2
style Impact fill:#fff9c4
具体分析
1. 代码债务
| 问题 | 位置 | 严重程度 | 偿还建议 |
|---|---|---|---|
| 类型断言过多 | src/gateway/*.ts |
中 | 使用类型守卫 |
| 错误处理不一致 | 多处 | 高 | 统一错误类型 |
| 魔法字符串 | sessionKey 解析 |
低 | 使用常量 |
| 日志格式不统一 | 全局 | 中 | 使用结构化日志 |
示例:类型断言问题
// 当前代码(有风险)
const config = params.config as OpenClawConfig;
// 改进:使用类型守卫
function isOpenClawConfig(obj: unknown): obj is OpenClawConfig {
return typeof obj === "object" &&
obj !== null &&
"server" in obj &&
"providers" in obj;
}
const config = isOpenClawConfig(params.config)
? params.config
: throw new ConfigError("Invalid config");
2. 架构债务
| 问题 | 影响 | 偿还建议 |
|---|---|---|
| Session 与 Agent 边界模糊 | 代码耦合 | 重构职责划分 |
| 配置管理分散 | 难以调试 | 统一配置模型 |
| 事件缺乏持久化 | 无法回放 | 增加事件存储 |
| 工具权限模型简单 | 安全风险 | 引入 RBAC |
3. 文档债务
| 缺失内容 | 影响 |
|---|---|
| API 规范文档 | 集成困难 |
| 架构决策记录(ADR) | 理解困难 |
| 贡献指南 | 社区参与低 |
| 故障排查手册 | 运维成本高 |
4. 测试债务
# 当前测试覆盖率(假设)
# src/gateway/ 45%
# src/agents/ 38%
# src/channels/ 25%
# src/sessions/ 52%
| 测试类型 | 现状 | 目标 |
|---|---|---|
| 单元测试 | 部分 | >80% |
| 集成测试 | 少量 | 覆盖核心流程 |
| E2E 测试 | 无 | 覆盖主要场景 |
| 性能测试 | 无 | 基准测试 |
偿还计划建议
gantt
title 技术债务偿还计划
dateFormat YYYY-MM-DD
section 高优先级
错误处理统一 :a1, 2026-04-01, 2w
测试覆盖率提升 :a2, 2026-04-01, 4w
section 中优先级
配置管理重构 :b1, 2026-04-15, 3w
类型安全改进 :b2, 2026-05-01, 2w
section 低优先级
文档完善 :c1, 2026-04-01, 8w
性能基准测试 :c2, 2026-05-15, 2w
竞品对比:OpenClaw vs 其他 Agent 平台
对比维度
radar-beta
title Agent 平台能力对比
axis 多渠道支持["多渠道支持"], 协议开放["协议开放"], 扩展性["扩展性"], 企业特性["企业特性"], 社区生态["社区生态"], 学习曲线["学习曲线"]
curve["OpenClaw"]: [9, 7, 8, 6, 5, 6]
curve["LangChain"]: [3, 8, 9, 5, 9, 4]
curve["AutoGPT"]: [2, 6, 7, 3, 7, 5]
curve["CrewAI"]: [2, 7, 8, 4, 6, 5]
详细对比
| 特性 | OpenClaw | LangChain | AutoGPT | CrewAI |
|---|---|---|---|---|
| 多渠道 | ✅ 20+ 渠道 | ❌ 需自建 | ❌ | ❌ |
| 流式响应 | ✅ 原生 | ⚠️ 部分 | ❌ | ⚠️ |
| 工具系统 | ✅ 插件 + 沙箱 | ✅ Python 函数 | ✅ 自定义 | ✅ 角色-任务 |
| 多 Agent | ✅ Subagent | ⚠️ 需编排 | ❌ 单 Agent | ✅ 原生 |
| 状态持久化 | ✅ SQLite | ⚠️ 可选 | ⚠️ JSON | ⚠️ 可选 |
| 生产就绪 | ✅ 认证/监控/备份 | ⚠️ 需补充 | ❌ | ⚠️ |
| 扩展性 | ✅ 插件系统 | ✅ 链式组合 | ⚠️ | ✅ 框架级 |
| 学习曲线 | 中等 | 陡峭 | 平缓 | 中等 |
| 文档质量 | ⚠️ 待改进 | ✅ 完善 | ⚠️ | ✅ |
| 社区规模 | 🌱 新兴 | 🌳 成熟 | 🌿 活跃 | 🌱 新兴 |
OpenClaw 的独特定位
flowchart TB
subgraph Niche["独特定位"]
N1["多渠道接入"]
N2["生产就绪"]
N3["实时通信"]
end
subgraph Gap["填补空白"]
G1["个人/小团队"]
G2["即时通讯场景"]
G3["快速部署"]
end
Niche --> Gap
style Niche fill:#e8f5e9
style Gap fill:#fff3e0
OpenClaw 的优势:
- 开箱即用的多渠道:无需自己对接 WhatsApp、Telegram 等
- 生产级特性:认证、监控、备份一应俱全
- 实时优先:流式响应、WebSocket 原生支持
OpenClaw 的不足:
- 灵活性较低:框架约束较多,不如 LangChain 自由
- 生态较小:社区插件、工具数量有限
- 企业特性缺失:缺少多租户、RBAC 等
适用场景建议
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 个人助手 | ✅ OpenClaw | 多渠道、易部署 |
| 客服机器人 | ✅ OpenClaw | 实时性好、生产就绪 |
| 复杂工作流 | LangChain | 编排灵活 |
| 自主任务 | AutoGPT | 自动化程度高 |
| 多 Agent 协作 | CrewAI | 原生支持 |
未来展望:AI Agent 平台的发展趋势
趋势分析
flowchart TB
subgraph Trends["发展趋势"]
T1["多模态"]
T2["长记忆"]
T3["自主性"]
T4["协作性"]
T5["可解释"]
end
subgraph Tech["技术方向"]
TE1["VLM/多模态模型"]
TE2["向量数据库/RAG"]
TE3["规划/反思"]
TE4["Multi-Agent 系统"]
TE5["思维链/推理透明"]
end
Trends --> Tech
style Trends fill:#e8f5e9
style Tech fill:#fff3e0
OpenClaw 的演进方向
1. 多模态支持
// 未来:支持图片、音频、视频
interface NormalizedMessage {
text?: string;
attachments?: Attachment[];
// 新增
images?: ImageContent[];
audio?: AudioContent[];
video?: VideoContent[];
}
2. 长期记忆
# 未来:集成向量数据库
memory:
type: "long-term"
backend: "pinecone" # 或 weaviate, milvus
embedding: "text-embedding-3-small"
# 记忆策略
retention:
shortTerm: 4000 # tokens
longTerm: true
3. 更强的 Agent 自主性
// 未来:Agent 自我反思和规划
interface AgentCapabilities {
planning: boolean; // 任务规划
reflection: boolean; // 自我反思
learning: boolean; // 从反馈学习
toolCreation: boolean; // 动态创建工具
}
4. 多 Agent 协作增强
flowchart TB
subgraph Current["当前"]
C1["Spawn Subagent"]
C2["简单委派"]
end
subgraph Future["未来"]
F1["Agent 市场"]
F2["动态组建团队"]
F3["知识共享"]
end
Current --> Future
style Current fill:#fff9c4
style Future fill:#c8e6c9
对开发者的启示
1. 架构启示
分层 + 插件化 = 可维护 + 可扩展
OpenClaw 的四层架构和插件系统值得借鉴:
- 明确的层次边界
- 核心稳定,边缘灵活
- 依赖注入而非硬编码
2. 设计启示
协议优先,实现其次
ACP 协议的设计思想:
- 定义稳定的接口
- 支持多种实现
- 隔离外部变化
3. 工程启示
从第一天就考虑生产
OpenClaw 的生产级特性:
- 认证从一开始就设计
- 监控指标内置
- 备份机制完善
4. 社区启示
降低门槛,扩大生态
- 清晰的插件开发文档
- 示例项目
- 贡献指南
常见陷阱
陷阱 1:误用单例模式
症状:
[WARN] Multiple Gateway instances detected
[ERROR] Session data conflict: concurrent modification detected
原因: OpenClaw 的设计是单进程架构,但用户尝试运行多个 Gateway 实例共享同一数据目录。
错误代码:
# 同时启动多个 Gateway 进程
openclaw gateway start &
openclaw gateway start --port 18790 &
正确代码:
# OpenClaw 设计为单进程,如果需要高可用:
# 方案一:使用进程管理器确保只有一个实例
pm2 start openclaw -- gateway start
# 方案二:使用锁文件防止多实例
openclaw gateway start --lock-file /var/run/openclaw.lock
# 方案三:如果需要多实例,使用不同的数据目录
openclaw gateway start --data-dir ~/.openclaw-instance1
openclaw gateway start --data-dir ~/.openclaw-instance2 --port 18790
调试方法:
# 检查是否有多个 Gateway 进程
ps aux | grep openclaw
# 查看端口占用
lsof -i :18789
# 检查锁文件
ls -la /var/run/openclaw.lock
源码位置: src/gateway/single-process.ts
陷阱 2:配置热更新误解
症状:
[WARN] Config file changed but not reloaded
[WARN] Restart required for changes to take effect
原因: 用户修改了配置文件后,期望立即生效,但某些配置项需要重启。
错误理解:
# 修改配置文件
vim ~/.openclaw/openclaw.yaml
# 期望立即生效,但发现没有变化
openclaw config get providers.openai.defaultModel
# 仍然显示旧值
正确理解:
# 查看哪些配置支持热更新
openclaw config reloadable
# 输出示例
# Reloadable configs:
# - logging.level
# - metrics.enabled
# - channels.*.enabled
#
# Require restart:
# - server.host
# - server.port
# - auth.method
# - providers.*
# 热更新支持的配置
openclaw config reload
# 需要重启的配置
openclaw gateway restart
调试方法:
# 查看当前加载的配置
openclaw config dump
# 比较配置文件和运行时配置
diff <(cat ~/.openclaw/openclaw.yaml) <(openclaw config dump)
# 查看配置来源
openclaw config sources
# 输出示例
# Config sources (priority: high to low):
# 1. CLI flags
# 2. Environment variables
# 3. ~/.openclaw/openclaw.yaml
# 4. Default values
源码位置: src/config/hot-reload.ts
陷阱 3:过度依赖 Transcript 持久化
症状:
[WARN] Transcript size exceeds limit: 50000 tokens
[WARN] Session performance degraded due to large transcript
原因: Transcript(对话历史)会随时间增长,但上下文窗口有限,过长的历史会影响性能和成本。
错误代码:
# 配置了无限保留的 Transcript
sessions:
transcriptRetention: unlimited # 会导致性能问题
正确代码:
# ~/.openclaw/openclaw.yaml
sessions:
# 使用滑动窗口策略
transcript:
strategy: sliding_window
maxTokens: 4000 # 限制上下文大小
# 或使用摘要策略
transcript:
strategy: summarize
summarizeThreshold: 10000 # 超过 10000 tokens 时摘要
# 定期清理
cleanup:
maxAge: 30d # 保留 30 天
maxMessages: 1000 # 最多 1000 条消息
调试方法:
# 查看会话的 Transcript 大小
openclaw session stats <sessionKey>
# 输出示例
# Session: whatsapp:+1234567890
# Messages: 523
# Tokens: 28456
# Oldest: 2026-02-01
# Newest: 2026-03-14
# 手动清理 Transcript
openclaw session prune <sessionKey> --keep-last 100
# 查看所有会话的 Transcript 大小
openclaw session list --sort-by size
源码位置: src/sessions/transcript-manager.ts
陷阱 4:忽视事件顺序依赖
症状:
[ERROR] Session not found when processing message
[ERROR] Message arrived before session creation completed
原因: 分布式系统中事件可能乱序到达,但代码假设事件按顺序处理。
错误代码:
// 假设 session 一定存在
async function handleMessage(msg: NormalizedMessage) {
const session = await getSession(msg.sessionKey);
// 如果 session 创建事件还没到达,这里会失败
await session.processMessage(msg);
}
正确代码:
// 处理可能的乱序
async function handleMessage(msg: NormalizedMessage) {
let session = await getSession(msg.sessionKey);
if (!session) {
// 等待 session 创建,或创建临时 session
session = await waitForSession(msg.sessionKey, { timeout: 5000 });
if (!session) {
// 如果超时,创建临时 session 或缓存消息
await cacheMessage(msg);
return;
}
}
await session.processMessage(msg);
}
// 使用幂等操作
async function ensureSession(sessionKey: string) {
// 使用 upsert 语义,无论执行多少次结果都一样
return await sessionStore.upsert(sessionKey, {
createdAt: new Date(),
status: "active",
});
}
调试方法:
# 查看事件处理顺序
LOG_LEVEL=debug LOG_INCLUDE="events,messages" openclaw gateway start
# 输出示例
# [DEBUG] events: session:created at 10:30:00.100
# [DEBUG] events: message:received at 10:30:00.050 # 消息在 session 创建之前!
# [DEBUG] events: Waiting for session...
# [DEBUG] events: Session found after 50ms
# 检查消息队列状态
openclaw queue status
# 输出示例
# Pending messages: 3
# Pending session creations: 1
# Average wait time: 120ms
源码位置: src/events/ordering.ts
给开发者的建议
如果你想学习 Agent 架构
- 从 Gateway 开始——理解控制平面设计
- 追踪消息流程——理解数据流设计
- 实现一个工具——理解 Agent 能力扩展
- 开发一个 Channel——理解插件系统
如果你想贡献 OpenClaw
高价值贡献方向:
| 方向 | 难度 | 价值 |
|---|---|---|
| 新 Channel 插件 | 中等 | 高 |
| 测试用例补充 | 低 | 高 |
| 文档改进 | 低 | 中 |
| 性能优化 | 高 | 中 |
| 新功能开发 | 高 | 高 |
如果你想构建自己的 Agent 平台
从 OpenClaw 学到的:
-
不要重新发明轮子
- 使用现有的 LLM SDK
- 借鉴成熟的协议设计
-
设计稳定的接口
- 核心接口要稳定
- 扩展点要灵活
-
生产特性要早考虑
- 认证、监控、备份
- 不要等到生产才发现问题
-
社区生态很重要
- 降低贡献门槛
- 提供清晰文档
系列总结
六篇文章,我们从 Gateway 的核心架构出发,追踪了消息的生命周期,深入了 Agent 的内部世界,探索了扩展机制,最后学习了生产部署。
flowchart LR
A["第一篇<br/>Gateway"] --> B["第二篇<br/>消息流程"]
B --> C["第三篇<br/>Agent"]
C --> D["第四篇<br/>扩展点"]
D --> E["第五篇<br/>部署安全"]
E --> F["第六篇<br/>架构复盘"]
style A fill:#e8f5e9
style B fill:#fff3e0
style C fill:#e3f2fd
style D fill:#fce4ec
style E fill:#f3e5f5
style F fill:#fff9c4
核心收获
| 文章 | 核心概念 | 设计启示 |
|---|---|---|
| Gateway | 控制平面 | 分离关注点 |
| 消息流程 | 管道模式 | 模块化处理 |
| Agent | ACP 协议 | 抽象层设计 |
| 扩展点 | 插件系统 | 开闭原则 |
| 部署安全 | 分层防护 | 安全纵深 |
| 架构复盘 | 技术债务 | 持续改进 |
OpenClaw 的本质
归根结底,OpenClaw 解决的问题是:
如何让不同的 LLM 在不同的渠道上,以一致的方式服务用户?
答案是一系列抽象:
- ACP 抽象了 LLM 差异
- Channel Plugin 抽象了渠道差异
- Gateway 协调了一切
这,就是架构设计的价值——通过抽象管理复杂性。
系列索引: OpenClaw 源码解析:目录索引