渐进式披露机制 (Progressive Disclosure) 🎯
"从元数据到完整内容 —— Claude Code 如何通过分层加载实现上下文优化"
1. 什么是渐进式披露
1.1 核心概念
渐进式披露 是一种上下文管理策略,按需分层加载内容:
传统方式: 启动时加载所有内容 → 53,000 tokens
渐进式披露:
Layer 1 (启动): 元数据 → ~2,000 tokens
Layer 2 (触发): 摘要 → ~5,000 tokens
Layer 3 (使用): 完整内容 → 按需加载1.2 收益对比
| 指标 | 传统方式 | 渐进式披露 | 改进 |
|---|---|---|---|
| 启动 tokens | 100,000 | 5,000 | 95% ↓ |
| 首次响应 | 5-10s | <1s | 90% ↓ |
| 平均 tokens/对话 | 120,000 | 15,000 | 87% ↓ |
| 成本/1000 对话 | $360 | $45 | 87% ↓ |
2. 三层架构
2.1 Layer 1: 元数据层
目标: 让 Agent 知道"有什么可用"
typescript
interface ToolMetadata {
name: string;
description: string; // 1 句话描述
category?: string;
}
// 示例
const toolsMetadata = [
{ name: "Read", description: "读取文件内容" },
{ name: "Edit", description: "编辑文件" },
{ name: "Bash", description: "执行 shell 命令" }
];Skills 元数据:
typescript
interface SkillMetadata {
name: string;
trigger: string; // 触发条件
description: string; // 简短描述
}
const skillsMetadata = [
{
name: "commit",
trigger: "用户输入 /commit",
description: "创建 git commit"
},
{
name: "code-review",
trigger: "用户输入 /code-review",
description: "代码审查"
}
];2.2 Layer 2: 摘要层
触发时机: Agent 决定使用某个工具/Skill
typescript
interface ToolSummary extends ToolMetadata {
parameters: {
name: string;
type: string;
required: boolean;
description: string;
}[];
examples?: string[]; // 简短示例
}
// 示例
const readToolSummary = {
name: "Read",
description: "读取文件内容",
parameters: [
{ name: "file_path", type: "string", required: true, description: "文件路径" },
{ name: "offset", type: "number", required: false, description: "起始行" },
{ name: "limit", type: "number", required: false, description: "读取行数" }
],
examples: ["Read('src/App.tsx')", "Read('README.md', 100, 50)"]
};Skills 摘要:
typescript
interface SkillSummary extends SkillMetadata {
instructions: string; // 核心指令(200-300 tokens)
tools: string[]; // 可用工具列表
}2.3 Layer 3: 完整内容层
触发时机: 需要详细文档或复杂逻辑
typescript
interface ToolFull extends ToolSummary {
implementation?: string; // 实现细节
edgeCases?: string[]; // 边界情况
bestPractices?: string[]; // 最佳实践
}
interface SkillFull extends SkillSummary {
fullInstructions: string; // 完整指令
references?: string[]; // 引用文档
examples?: string[]; // 详细示例
}3. 实现机制
3.1 工具懒加载
typescript
class ToolRegistry {
private metadata: Map<string, ToolMetadata> = new Map();
private summaries: Map<string, ToolSummary> = new Map();
private full: Map<string, ToolFull> = new Map();
// 启动时加载元数据
async initialize() {
const tools = await loadToolsMetadata();
tools.forEach(t => this.metadata.set(t.name, t));
}
// 按需加载摘要
async getSummary(name: string): Promise<ToolSummary> {
if (!this.summaries.has(name)) {
this.summaries.set(name, await loadToolSummary(name));
}
return this.summaries.get(name)!;
}
// 按需加载完整内容
async getFull(name: string): Promise<ToolFull> {
if (!this.full.has(name)) {
this.full.set(name, await loadToolFull(name));
}
return this.full.get(name)!;
}
}3.2 Skills 懒加载
typescript
class SkillRegistry {
private metadata: SkillMetadata[] = [];
private loaded: Map<string, SkillFull> = new Map();
async initialize() {
this.metadata = await loadSkillsMetadata();
}
// 检测触发
detectTrigger(userInput: string): string | null {
for (const skill of this.metadata) {
if (this.matchesTrigger(userInput, skill.trigger)) {
return skill.name;
}
}
return null;
}
// 加载完整 Skill
async load(name: string): Promise<SkillFull> {
if (!this.loaded.has(name)) {
this.loaded.set(name, await loadSkillFull(name));
}
return this.loaded.get(name)!;
}
private matchesTrigger(input: string, trigger: string): boolean {
// 简化的触发匹配逻辑
return input.includes(trigger) || input.startsWith(`/${trigger}`);
}
}3.3 记忆懒加载
typescript
class MemorySystem {
private metadata: { id: string; summary: string; timestamp: Date }[] = [];
async initialize() {
this.metadata = await loadMemoryMetadata();
}
// 语义搜索相关记忆
async search(query: string, limit: number = 5) {
const embedding = await getEmbedding(query);
const relevant = await vectorSearch(embedding, this.metadata, limit);
// 加载完整记忆内容
return Promise.all(relevant.map(m => loadMemoryFull(m.id)));
}
}4. 系统提示词注入
4.1 启动时注入(Layer 1)
typescript
function buildInitialPrompt() {
return `
You are Claude Code, an AI coding assistant.
Available tools (${tools.length}):
${tools.map(t => `- ${t.name}: ${t.description}`).join('\n')}
Available skills (${skills.length}):
${skills.map(s => `- /${s.name}: ${s.description}`).join('\n')}
Use tools by calling them with parameters.
Skills are triggered when user types /${skillName}.
`.trim();
}4.2 触发时注入(Layer 2)
typescript
async function injectToolSummary(toolName: string) {
const summary = await toolRegistry.getSummary(toolName);
return `
Tool: ${summary.name}
${summary.description}
Parameters:
${summary.parameters.map(p =>
`- ${p.name} (${p.type}${p.required ? ', required' : ''}): ${p.description}`
).join('\n')}
Examples:
${summary.examples?.join('\n') || 'N/A'}
`.trim();
}4.3 使用时注入(Layer 3)
typescript
async function injectSkillFull(skillName: string) {
const skill = await skillRegistry.load(skillName);
return `
# Skill: ${skill.name}
${skill.fullInstructions}
Available tools: ${skill.tools.join(', ')}
${skill.references ? `\nReferences:\n${skill.references.join('\n')}` : ''}
`.trim();
}5. 实战案例
5.1 场景:用户请求 /commit
typescript
async function handleUserInput(input: string) {
// 1. 检测 Skill 触发
const skillName = skillRegistry.detectTrigger(input);
if (skillName) {
// 2. 加载 Skill 完整内容
const skill = await skillRegistry.load(skillName);
// 3. 注入到上下文
const prompt = buildPromptWithSkill(skill);
// 4. 调用 LLM
return await llm.chat({ messages: [{ role: 'system', content: prompt }] });
}
}
// Token 消耗:
// - 启动: 5,000 tokens (元数据)
// - 触发 /commit: +3,000 tokens (Skill 完整内容)
// - 总计: 8,000 tokens (vs 传统方式的 100,000 tokens)5.2 场景:使用 Read 工具
typescript
async function handleToolCall(toolName: string, args: any) {
// 1. 首次使用时加载摘要
if (!toolRegistry.hasSummary(toolName)) {
const summary = await toolRegistry.getSummary(toolName);
injectToContext(summary);
}
// 2. 执行工具
return await executeTool(toolName, args);
}
// Token 消耗:
// - 启动: 5,000 tokens
// - 首次使用 Read: +500 tokens (摘要)
// - 后续使用: 0 tokens (已缓存)6. 优化策略
6.1 预加载热门内容
typescript
class SmartRegistry {
private hotSkills = ['commit', 'code-review', 'feature-dev'];
async initialize() {
await this.loadMetadata();
// 预加载热门 Skills 的摘要
await Promise.all(
this.hotSkills.map(name => this.loadSummary(name))
);
}
}6.2 缓存策略
typescript
class CachedRegistry {
private cache = new LRUCache<string, any>({ max: 50 });
async load(id: string) {
if (this.cache.has(id)) {
return this.cache.get(id);
}
const content = await loadFromDisk(id);
this.cache.set(id, content);
return content;
}
}6.3 压缩元数据
typescript
// 优化前
const metadata = {
name: "Read",
description: "Reads a file from the local filesystem. You can access any file directly by using this tool.",
category: "filesystem"
};
// 优化后
const metadata = {
name: "Read",
description: "读取文件",
category: "fs"
};7. 性能监控
typescript
class PerformanceMonitor {
trackLoading(layer: string, name: string, tokens: number) {
console.log(`[${layer}] Loaded ${name}: ${tokens} tokens`);
}
getStats() {
return {
totalTokens: this.totalTokens,
layerBreakdown: {
metadata: this.metadataTokens,
summary: this.summaryTokens,
full: this.fullTokens
}
};
}
}8. 最佳实践
- 元数据极简: 每个工具/Skill 描述控制在 10 词以内
- 摘要精准: 包含核心参数和 1-2 个示例
- 按需加载: 只在真正需要时加载完整内容
- 预加载热门: 对高频使用的内容提前加载摘要
- 缓存复用: 使用 LRU 缓存避免重复加载
- 监控优化: 持续跟踪 token 消耗,优化加载策略
9. 与其他机制的协同
9.1 与自动压缩协同
typescript
class HybridSystem {
async handleConversation(messages: Message[]) {
// 1. 渐进式披露控制初始上下文
const initialContext = await this.buildMinimalContext();
// 2. 对话过程中按需加载
const additionalContext = await this.loadOnDemand(messages);
// 3. 接近上下文限制时自动压缩
if (this.contextSize > this.threshold) {
await this.compressHistory(messages);
}
}
}9.2 与语义检索协同
typescript
class SemanticDisclosure {
async loadRelevant(query: string) {
// 1. 语义搜索相关 Skills
const relevantSkills = await this.semanticSearch(query, this.skillsMetadata);
// 2. 加载摘要
return Promise.all(relevantSkills.map(s => this.loadSummary(s.name)));
}
}参考资源
- Claude Skills Progressive Disclosure Architecture
- Lazy-Loading Architecture for Token Optimization
- Building Persistent Memory for Claude Code
本文基于 Claude Code 2026 年最新实现。