Progressive Disclosure in AI Agents: How OpenClaw Manages Context Budget
Problem
I kept hitting context limits when building AI agents. Every time I added more capabilities—more skills, more memory, more tools—the context window filled up faster. The model would run out of space before completing tasks.
The naive approach is to load everything upfront. But that’s wasteful. Most information isn’t needed for most tasks. I needed a way to show minimal information first, then expand on demand.
This pattern is called progressive disclosure, and OpenClaw implements it through two key mechanisms: skills and memory.
Context Is Budget, Not Warehouse
The fundamental shift in thinking is treating context as a budget to be spent wisely, not a warehouse to fill up.
Warehouse mindset: Load everything, hope it fitsBudget mindset: Spend context only on what's needed
Context budget allocation:- System prompt: Fixed cost- Available skills catalog: Minimal overhead- Skill content: Pay on demand- Memory snippets: Pay for relevanceWhen I adopt the budget mindset, the architecture decisions become clear. Every piece of information should justify its context cost.
Two-Stage Disclosure
Progressive disclosure works in two stages across both skills and memory systems.
Stage 1: Minimal Viable Information
The goal is to enable the model to identify what’s relevant without loading everything.
Skills: Inject a compact catalog with just name and description.
// Stage 1: Catalog injection (not full content)const availableSkills = skills.map(s => ({ name: s.name, description: s.description.slice(0, 100) // Compact}));
// System prompt gets compact versionsystemPrompt += `<available_skills>${availableSkills.map(s => `<skill name="${s.name}">${s.description}</skill>`).join('\n')}</available_skills>`;The catalog might look like this in the system prompt:
<available_skills><skill name="commit">Create well-formatted git commits following conventional commits format</skill><skill name="review-pr">Review pull requests for issues and improvements</skill><skill name="planner">Create implementation plans for features</skill></available_skills>Memory: Return short snippets with a hard character limit.
const SNIPPET_MAX_CHARS = 700;
// Stage 1: Search returns snippetsfunction memorySearch(query) { const results = vectorSearch(query); return results.map(r => ({ snippet: r.content.slice(0, SNIPPET_MAX_CHARS), path: r.path, lineRange: r.lines }));}The 700-character limit is enforced strictly. This keeps search results lean even when the source files are large.
Stage 2: On-Demand Expansion
When the model identifies relevant information, it can load the full content.
Skills: Read the complete SKILL.md file.
// Stage 2: On-demand readconst skillContent = await readFile(selectedSkillPath);
// Now the model has full instructionsThe model uses the standard Read tool to access skill content. This means skill content enters the conversation as a tool result, not as part of the initial context.
Memory: Fetch specific line ranges.
// Stage 2: Read specific linesfunction memoryGet(path, fromLine, toLine) { return readLines(path, fromLine, toLine);}The search result includes the path and line range, so the model can request exactly what it needs.
System Prompt Enforcement
The system prompt includes rules that enforce progressive disclosure:
When using skills:- Only read skill when explicitly matched one- Maximum one skill can be active at a time- Never assume a skill exists without checking the catalog- Use the Read tool to access skill content
When using memory:- Search first to find relevant snippets- Then read specific line ranges if needed- Don't load entire files unless necessaryThese rules prevent context bloat from accidental overloading. The “maximum one skill” rule is particularly important—it forces the model to be selective.
Degradation Strategy
What happens when even the compact format overflows the budget? OpenClaw degrades gracefully.
// Degradation strategy when skills overflowif (totalSkillDescriptions > budget) { // Level 1: Compact format skills = skills.map(compactDescription);}
if (stillOverBudget) { // Level 2: Truncate with warning skills = skills.slice(0, maxSkills); systemPrompt += '\n[skills truncated due to context limits]';}This multi-level approach ensures the agent keeps working even under extreme context pressure. The user gets a warning that skills were truncated, so they understand why some capabilities might be unavailable.
Memory Progressive Disclosure in Practice
Let me trace through a real memory search scenario.
Step 1: User asks about a function
User: "How does the authentication middleware work?"Step 2: Model searches memory
memorySearch("authentication middleware")Step 3: Search returns snippets
[ { snippet: "export function authMiddleware(req, res, next) {\n const token = req.headers.authorization?.split(' ')[1];\n if (!token) {\n return res.status(401).json({ error: 'No token provided' });\n }\n try {\n const decoded = jwt.verify(token, process.env.JWT_SECRET);\n req.user = decoded;\n next();\n } catch (err) {\n return res.status(401).json({ error: 'Invalid token' });\n }\n}", path: "/src/middleware/auth.ts", lineRange: { start: 15, end: 28 } }, // ... more snippets]Each snippet is capped at 700 characters. The model can see what’s relevant without loading entire files.
Step 4: Model reads full context if needed
memoryGet("/src/middleware/auth.ts", 1, 50)This fetches lines 1-50 of the auth middleware file, giving the model full context while respecting the context budget.
Skills Progressive Disclosure in Practice
Now let me trace through a skill usage scenario.
Step 1: Model sees available skills
<available_skills><skill name="commit">Create well-formatted git commits</skill><skill name="review-pr">Review pull requests</skill><skill name="planner">Create implementation plans</skill></available_skills>This catalog is maybe 200 characters. Very cheap in context budget.
Step 2: User requests a commit
User: "Commit these changes"Step 3: Model matches the skill
Model: “The user wants to commit. The ‘commit’ skill matches.”
Step 4: Model reads the skill
Tool Call: Read("/workspace/.claude/skills/commit/SKILL.md")Step 5: Skill content enters conversation
# Commit Skill
Create well-formatted git commits following conventional commits format.
## Steps1. Run git status to see changes2. Run git diff to understand changes3. Draft commit message following format4. Verify message meets standards5. Create commit with message...Now the model has the full skill instructions. The cost was paid only when needed.
Why This Matters
Without progressive disclosure, I’d face constant context pressure:
Without progressive disclosure:- Load all skill content upfront: ~50,000 tokens- Load all relevant memory: ~30,000 tokens- Context window: 128,000 tokens- Available for task: ~48,000 tokens
With progressive disclosure:- Skills catalog: ~500 tokens- Memory search snippets: ~2,000 tokens- Context window: 128,000 tokens- Available for task: ~125,500 tokensThat’s a dramatic difference in available context for the actual task.
Common Pitfalls
Pitfall 1: Overloading the Catalog
Even the skill catalog can overflow if there are too many skills. The degradation strategy handles this, but it’s better to keep the skill set focused.
Pitfall 2: Snippet Blindness
The 700-character snippet limit might cut off crucial context. Always design code so the most important information is at the beginning of functions and files.
Pitfall 3: Premature Loading
Don’t read skill content or memory lines until you’re certain they’re needed. The system prompt rules help prevent this, but the model can still make mistakes.
Summary
In this post, I explained how OpenClaw implements progressive disclosure to manage context budget efficiently. The two-stage approach—minimal viable information first, on-demand expansion second—applies to both skills and memory.
For skills, the <available_skills> catalog provides just names and descriptions. The model reads full SKILL.md content only when matched. The system prompt enforces “maximum one skill” to prevent overloading.
For memory, search returns 700-character snippets with paths and line ranges. The model fetches specific lines only when needed. This keeps search results lean regardless of source file size.
The degradation strategy—compact format, then truncate with warning—ensures the agent keeps working under context pressure. This design reflects the core philosophy: context is budget, not warehouse.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments