ASK KNOX
beta
LESSON 372

Progressive Disclosure — Load-on-Demand Context

Load context at the last responsible moment — skills, deferred tools, and on-demand sub-docs that load only when the task actually needs them.

8 min read·Context Engineering & CLAUDE.md Architecture

Introduction

Progressive disclosure is the engineering pattern that lets you maintain a lean always-on context while still having access to the full depth of your knowledge and tooling. The core insight: most context is not needed on every turn — it is needed only when a specific task type arises.

The inverse — loading everything at session start just in case — is the most common context engineering mistake. It burns tokens on every turn for context that 80% of turns never touch.

Knox's stack implements progressive disclosure at four distinct layers, each with its own triggering mechanism.

The Four Disclosure Layers

Layer 1: Always-On (Constant)

The smallest, most important layer. Only what cannot be deferred:

  • CLAUDE.md (Tier 1 block) — non-negotiable rules, always active
  • MCP server instructions — tool registry, connection metadata
  • Active skill framework — the skill invocation contract

This layer should be under 5,000 tokens total. If it is larger, something that belongs in Layer 2 or 3 has leaked in.

Layer 2: Session-Triggered

Loaded once at session start — but only for relevant session types:

  • memory_query("project-name") — query-first habit, surfaces relevant Semantic Memory Layer context for this session
  • lessons.md read — project-specific anti-patterns and rules
  • design-system/MASTER.md — read by the agent when UI work begins (not on backend-only sessions)

A critical mechanical detail: @imports in CLAUDE.md resolve eagerly at load time — there is no conditional @import. If a doc should load on every session in the repo, @import it. If it should load only for certain task types, the mechanism is a lazy-read instruction that the agent executes when the task fires. The CLAUDE.md might contain:

@lessons.md   # an @import — always loads with CLAUDE.md for this project

## Design Rules
Read design-system/MASTER.md before any UI work.   # lazy read — loads only when a UI task fires

Layer 3: Task-Triggered (Skill-Based)

Loaded when a specific skill fires — not before:

  • /context-budget skill — loads token accounting tools only when the audit is needed
  • deferred tool schemas — ToolSearch fetches MCP schemas only for tools needed in this task
  • page-level sub-docs — design-system page overrides are read on demand for the specific page being worked on

This is where deferred tools live. The ToolSearch pattern is the canonical implementation.

Layer 4: On-Demand (Agent-Initiated)

The most targeted layer — the agent explicitly decides to fetch a specific piece of context:

  • memory_recall(memory_id) — single-hop fetch after memory_query surfaces the ID
  • Incident RCAs — fetched when the agent is diagnosing a class of bug
  • API signature docs — fetched by verify-deps skill for a specific library at a specific version

No pre-loading. No speculation. The agent knows it needs this specific fact and retrieves it precisely.

Deferred Tools: The Canonical Example

The deferred tool pattern is one of the clearest examples of progressive disclosure in practice. Knox's session has 50+ MCP tools available: Semantic Memory Layer (10 tools), mcp-bridge, agent-gateway, various disabled tools that appear in system-reminder messages.

If all 50+ tool schemas loaded in the system prompt, that is approximately 18,000 tokens of always-on overhead. In a 200K window, that is 9% of the budget consumed before the agent does anything.

The deferred pattern:

  1. Only universally-used tools (Read, Edit, Bash, Write, Skill) load by default — ~2,400 tokens
  2. When a skill fires that needs Semantic Memory Layer, ToolSearch("select:mcp__memory__memory_query") fetches that schema — ~400 tokens, once
  3. The schema is now available for the rest of the session without reloading
  4. Tools never used in this session: 0 tokens

The token savings are significant: from ~18,000 tokens of speculative overhead to ~2,400 + ~400 per actually-needed tool. For a session that uses 4 specialized tools, that is ~4,000 tokens versus ~18,000 — a 77% reduction in tool overhead.

@Imports vs Lazy Reads in Practice

Layer 2 has two distinct mechanisms, and choosing correctly between them is the key decision. @imports resolve eagerly when CLAUDE.md loads — use them for sub-docs every session in the repo needs. Lazy-read instructions defer the cost until the task fires — use them for task-conditional docs. Three real examples from Knox's stack:

Academy CLAUDE.md (@AGENTS.md): The @AGENTS.md at the top of academy's CLAUDE.md loads the AGENTS.md content — the critical note about Next.js 16 API breaking changes. An @import is correct here because it applies to every session in the academy repo. It is separate from CLAUDE.md so it can be updated independently.

Design system integration: design-system/MASTER.md is deliberately NOT @imported — an @import would resolve at load time and pay for the design tokens on backend-only sessions too. Instead, CLAUDE.md carries the instruction "Read design-system/MASTER.md before any UI work." The agent executes the read lazily, so a session writing an API route or updating exams.ts never loads the design tokens.

Project-specific lazy refs: ~/dev/design-intelligence.md is referenced (not inlined or @imported) in the global CLAUDE.md. The reference stays lean — the content loads only when the agent reads the file for a frontend design task.

Skill Files as Progressive Disclosure Units

Skills (~/.claude/skills/*.md) are the purest form of progressive disclosure: entire workflows that load into context only when invoked. The /academy-track skill, for example, contains the complete track-building workflow — authoring contract, diagram quality bar, registration steps, test verification.

That skill's content is maybe 800 tokens. If it were inlined into CLAUDE.md, it would consume 800 tokens on every session, even when Knox is fixing a trading bot bug and has no intention of building academy tracks. By keeping it in a skill file, those 800 tokens only load when the /academy-track trigger fires.

Multiply this by 60+ skills in Knox's stack, and the savings from skill file isolation versus CLAUDE.md inlining becomes thousands of tokens per session.

Common Progressive Disclosure Mistakes

Loading everything "just in case": The worst anti-pattern. Speculative loading is the opposite of progressive disclosure — it pays the cost of all context on every turn without the benefit.

Putting skills in CLAUDE.md: Skills belong in ~/.claude/skills/, not inlined. A CLAUDE.md with 10 skill workflows embedded is 8,000+ tokens of always-on overhead.

@importing large reference docs: @api-documentation.md in CLAUDE.md loads the doc on every turn — and remember, @imports cannot be conditional; they always resolve at load time. If a doc is only needed occasionally, it belongs in Semantic Memory Layer (query when needed) or behind a lazy-read instruction ("Read api-documentation.md before API work").

Summary

  • Four disclosure layers: always-on → session-triggered → task-triggered → on-demand
  • Load at the last responsible moment — speculative loading is budget waste
  • Deferred tools: ToolSearch fetches schemas only for tools actually needed, reducing 18K tokens to ~2-4K
  • Layer 2 uses two mechanisms: eager @imports for always-on sub-docs, lazy-read instructions for task-conditional docs — @imports cannot be conditional
  • Skill files are the purest progressive disclosure unit — load only when the trigger fires

What's Next

The next lesson moves from structural context to persistent state — MEMORY.md, the one-fact-per-file rule, frontmatter for traceability, and how persistent memory across sessions is different from in-session context.