How Deep Agents Implements Skills: Progressive Disclosure & Middleware Ordering

This article analyzes Deep Agents' Skills implementation, revealing a three-layer progressive disclosure loading pattern where metadata loads at startup, full instructions load on activation, and resources load on demand. It explains how before_agent and wrap_model_call hooks inject skill metadata into system prompts, and why SkillsMiddleware positioning differs between main agents (early for coordination) and sub-agents (late for separation of concerns).

Code Archaeology
Code Archaeology
Code Archaeology
How Deep Agents Implements Skills: Progressive Disclosure & Middleware Ordering

1. The Initial Question

Skills are implemented in SkillsMiddleware, initialized inside create_deep_agent(). A key observation: the middleware order differs between the main agent and sub-agents.

Main Agent Middleware Order

TodoListMiddleware

SkillsMiddleware <-- early position

FilesystemMiddleware

SubAgentMiddleware

SummarizationMiddleware

PatchToolCallsMiddleware

AnthropicPromptCachingMiddleware

MemoryMiddleware

HumanInTheLoopMiddleware

Sub-Agent Middleware Order

TodoListMiddleware

FilesystemMiddleware

SummarizationMiddleware

PatchToolCallsMiddleware

SkillsMiddleware <-- later position

Custom Middleware

AnthropicPromptCachingMiddleware

Since middleware order affects hook execution sequence ( before_agent, wrap_model_call), the article investigates SkillsMiddleware to understand the impact.

2. Skill Basic Structure

A skill directory contains at minimum a SKILL.md file:

skill-name/
├── SKILL.md          # Required: metadata + instructions
├── scripts/          # Optional: executable code
├── references/       # Optional: documentation
├── assets/           # Optional: templates, resources
└── ...               # Any additional files or directories
SKILL.md

must start with YAML frontmatter metadata followed by Markdown instructions. Example metadata:

---
name: pdf-processing
description: Extract PDF text, fill forms, merge files. Use when handling PDFs.
license: Apache-2.0
metadata:
  author: example-org
  version: "1.0"
---

In Deep Agents the metadata maps to a SkillMetadata TypedDict:

class SkillMetadata(TypedDict):
    """Metadata for a skill per Agent Skills specification (https://agentskills.io/specification)."""
    path: str
    name: str
    description: str
    license: str | None
    compatibility: str | None
    metadata: dict[str, str]
    allowed_tools: list[str]

3. Skill Loading Process

3.1 Progressive Disclosure

Skills use a "progressive disclosure" loading pattern to efficiently use context:

Metadata (~100 tokens) : name and description fields load for all skills at startup.

Instructions (recommended <5000 tokens) : Full SKILL.md body loads when the skill is activated.

Resources (on-demand) : Files in scripts/, references/, or assets/ load only when needed.

3.2 before_agent Hook

SkillsMiddleware

loads skills in its before_agent hook, writing the first progressive-disclosure layer ( SkillMetadata) to state.

def before_agent(self, state: SkillsState, runtime: Runtime, config: RunnableConfig):
    # Step 1: Check cache - skip if skills_metadata already present
    if "skills_metadata" in state:
        return None

    # Step 2: Resolve backend
    backend = self._get_backend(state, runtime, config)

    # Step 3: Initialize empty dict for merging skills (keyed by skill name)
    all_skills: dict[str, SkillMetadata] = {}

    # Step 4: Iterate all skill sources, load and merge in order
    for source_path in self.sources:
        # Load skill list from current source
        source_skills = _list_skills(backend, source_path)
        # Add to dict; same-name skills are overridden (later overrides earlier)
        for skill in source_skills:
            all_skills[skill["name"]] = skill

    # Step 5: Convert dict values to list
    skills = list(all_skills.values())

    # Step 6: Return state update object
    return SkillsStateUpdate(skills_metadata=skills)

This runs once at agent startup. Note that skills_metadata state is isolated between the main agent and each sub-agent.

4. Skill System Prompt Injection

The wrap_model_call hook formats the loaded skill metadata and injects it into the system prompt so the LLM knows available skills.

def modify_request(self, request: ModelRequest[ContextT]) -> ModelRequest[ContextT]:
    # Step 1: Get skill metadata from request state
    skills_metadata = request.state.get("skills_metadata", [])

    # Step 2: Format skill source location info
    skills_locations = self._format_skills_locations()

    # Step 3: Format skill list (metadata to readable text)
    skills_list = self._format_skills_list(skills_metadata)

    # Step 4: Generate skill documentation section via template
    skills_section = self.system_prompt_template.format(
        skills_locations=skills_locations,
        skills_list=skills_list,
    )

    # Step 5: Append skill section to existing system message
    new_system_message = append_to_system_message(request.system_message, skills_section)

    # Step 6: Return request copy with new system message
    return request.override(system_message=new_system_message)

Step 2 produces entries like:

- **{skill['name']}**: {skill['description']}  -> Allowed tools: {', '.join(skill['allowed_tools'])}  -> Read `{skill['path']}` for full instructions

Step 4 uses the following template (condensed):

## Skills System

You have access to a skills library that provides specialized capabilities and domain knowledge.

{skills_locations}

**Available Skills:**

{skills_list}

**How to Use Skills (Progressive Disclosure):**

Skills follow a **progressive disclosure** pattern - you see their name and description above, but only read full instructions when needed:

1. **Recognize when a skill applies**: Check if the user's task matches a skill's description
2. **Read the skill's full instructions**: Use the path shown in the skill list above
3. **Follow the skill's instructions**: SKILL.md contains step-by-step workflows, best practices, and examples
4. **Access supporting files**: Skills may include helper scripts, configs, or reference docs - use absolute paths

**When to Use Skills:**
- User's request matches a skill's domain (e.g., "research X" -> web-research skill)
- You need specialized knowledge or structured workflows
- A skill provides proven patterns for complex tasks

**Executing Skill Scripts:**
Skills may contain Python scripts or other executable files. Always use absolute paths from the skill list.

**Example Workflow:**

User: "Can you research the latest developments in quantum computing?"

1. Check available skills -> See "web-research" skill with its path
2. Read the skill using the path shown
3. Follow the skill's research workflow (search -> organize -> synthesize)
4. Use any helper scripts with absolute paths

Remember: Skills make you more capable and consistent. When in doubt, check if a skill exists for the task!

This teaches the LLM the progressive-disclosure four-step workflow and usage scenarios (domain match, specialized knowledge, complex task patterns).

5. Revisiting the Initial Question

The difference in SkillsMiddleware position boils down to where the skill system prompt appears in the full system prompt.

Main Agent Prompt (Coordinator Role):

When the user asks you to do something:

1. **Understand first** — read relevant files, check existing patterns. Quick but thorough — gather enough evidence to start, then iterate.
2. **Act** — implement the solution. Work quickly but accurately.
3. **Verify** — check your work against what was asked, not against your own output. Your first attempt is rarely correct — iterate.

Keep working until the task is fully complete. Don't stop partway and explain what you would do — just do it. Only yield back to the user when the task is done or you're genuinely blocked.

Sub-Agent Prompt (Executor Role):

In order to complete the objective that the user asks of you, you have access to a number of standard tools.

Therefore, SkillsMiddleware placed before

SubAgentMiddleware in the main agent ensures the coordinator has full capability awareness <strong>before</strong> delegating to sub-agents. Sub-agents receive their own separate skills configuration, placing <code>SkillsMiddleware later to achieve <strong>separation of concerns and resource optimization</strong> at the execution layer.</code>
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

AI agentsMiddlewareAgent ArchitectureSkillsProgressive DisclosureLLM EngineeringSystem PromptDeep Agents
Code Archaeology
Written by

Code Archaeology

Learn from the past to understand the present

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.