Using Skills With LangGraph Deep Agents

Building a deep research agent is not only about connecting a model to search tools, MCP servers, document readers, and summarizers. The hardest problem is deciding which instructions the agent should carry at each step.

A research agent may need different capabilities during the same task. It may need to search the web, inspect documents, compare sources, extract evidence, write a report, or check citations. If every workflow is placed in one large system prompt, the agent becomes harder to maintain and the context window fills up quickly.

LangGraph Deep Agents address this problem with Skills.

A Skill is an on-demand capability packaged as a small folder. Each skill contains a SKILL.md file that explains when the skill should be used and how the agent should perform that workflow. The agent reads lightweight metadata from each skill at startup, then loads the full skill content only when the task requires it.

In this tutorial, we will build a small SRE-style Deep Agent that uses Skills as runbooks. The same pattern can be used for a deep research agent, documentation agent, coding agent, incident assistant, or any agent that needs multiple specialized workflows without loading all instructions upfront.

What you will build

You will create a simple LangGraph Deep Agent with two skills:

Skill Purpose
triage-alert Used when the user wants to triage an alert or decide whether to page someone.
write-postmortem Used when the user wants to write a postmortem for a resolved incident.

The goal is to demonstrate how the agent discovers skills, selects the relevant one, loads its full instructions, and uses those instructions to complete the task.

Conceptual workflow

The loading model is similar to how an on-call engineer uses runbooks.

An engineer does not memorize every runbook. They know the index: one line per incident type saying which runbook applies. When an alert fires, they match the alert to the index and open the right runbook.

Skills work the same way for the agent context window.

flowchart TD A["πŸ§‘β€πŸ’» User request"] --> B["πŸ“„ Skill metadata"] B --> C["πŸ—‚οΈ Skill index"] C --> D{"🎯 Relevant skill?"} D -- "❌ No" --> E["🧰 Use base flow"] D -- "βœ… Yes" --> F["πŸ“˜ Load skill"] F --> G["πŸͺœ Run workflow"] G --> H["βœ… Response"] classDef blue fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e; classDef gray fill:#f1f5f9,stroke:#64748b,stroke-width:1.5px,color:#0f172a; classDef orange fill:#fff7ed,stroke:#f97316,stroke-width:2px,color:#7c2d12; classDef red fill:#fef2f2,stroke:#ef4444,stroke-width:1.5px,color:#7f1d1d; classDef green fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b; class A blue; class B,C gray; class D orange; class E red; class F,G,H green;

The important part is progressive disclosure. The agent knows what skills exist, but it does not load every procedure into context upfront. It loads only the skill that matches the current request.

How a Skill is structured

Each skill is a directory. The main file is always SKILL.md. The directory name and skill name should match.

A typical skill looks like this:

skills/
└── triage-alert/
    β”œβ”€β”€ SKILL.md
    β”œβ”€β”€ reference.md
    └── scripts/
        └── build_timeline.py

The SKILL.md file has two parts:

  1. Frontmatter: metadata used for discovery and routing.
  2. Body: the detailed procedure loaded only when the skill is activated.

Example:

---
name: triage-alert
description: Use when the user wants to triage an alert or decide how to respond to one.
---

# Triage an Alert

Follow these steps when investigating an alert.

1. Classify severity based on user-facing impact.
2. Identify the blast radius.
3. Check recent deploys, config changes, and feature-flag changes.
4. Decide whether to page, create a ticket, or monitor.

The description is the routing signal. It should describe when the skill applies, not the full procedure.

The body can be longer because it is not loaded until the skill is selected.

Why frontmatter matters

At startup, the agent reads the frontmatter from registered skills and creates a skill index. Conceptually, that index looks like this:

## Skills System

Available skills:
- **triage-alert**: Use when the user wants to triage an alert or decide how to respond to one.
  -> Read skills/triage-alert/SKILL.md for full instructions.
- **write-postmortem**: Use when the user wants to write a postmortem for a resolved incident.
  -> Read skills/write-postmortem/SKILL.md for full instructions.

This index is small. Only the skill names, descriptions, and file paths are placed in the initial context. The full instructions remain on disk until the agent needs them.

The token-saving effect is straightforward:

flowchart LR A[Without Skills] --> B[Large system prompt] B --> C[All workflows loaded every time] C --> D[More context usage and more instruction noise] E[With Skills] --> F[Small skill index] F --> G[Load only matching workflow] G --> H[Lower context usage and cleaner instructions]

Project layout

Info
The example code for this post is available in GitHub repo langgraph-deepagent-skills-demo

Create a project directory called langgraph-deepagent-skills-demo:

langgraph-deepagent-skills-demo/
β”œβ”€β”€ sre_agent.py
└── skills/
    β”œβ”€β”€ triage-alert/
    β”‚   └── SKILL.md
    └── write-postmortem/
        └── SKILL.md

This gives the agent two skills to choose from.

Step 1: Create the alert triage skill

Create this file:

langgraph-deepagent-skills-demo/skills/triage-alert/SKILL.md

Add the following content:

---
name: triage-alert
description: Use when the user wants to triage an alert or decide how to respond to one.
---

# Triage an Alert

Decide fast, but show the reasoning. Every conclusion must name the signal it is based on.

## Step 1: Severity

Classify severity by user-facing impact, not by which metric fired.

A 2s p99 latency increase on checkout is more important than a crashed batch job with no customer impact.

State the trend:

- getting worse
- stable
- recovering

## Step 2: Blast radius

Identify which services and customer segments are affected.

Check dependencies in both directions:

- what this service calls
- what calls this service

## Step 3: Recent changes

Check deploys, config changes, and feature-flag flips in the last hour before considering exotic causes.

Most incidents follow a change.

## Step 4: Page or ticket

Page if user-facing impact is active or the trend is worsening.

Create a ticket if the impact is past, contained, or the alert is a known false positive.

Never page on a metric alone.

## Output

Return:

- **Severity**: level, with the one signal that decided it
- **Blast radius**: services and customer segments affected
- **Suspected cause**: the most recent correlated change, if any
- **Decision**: page or ticket, and the first status update to send

This skill focuses only on alert triage. It does not include postmortem writing, stakeholder communication, or incident review. Keeping the skill narrow makes routing easier.

Step 2: Create the postmortem skill

Create this file:

langgraph-deepagent-skills-demo/skills/write-postmortem/SKILL.md

Add the following content:

---
name: write-postmortem
description: Use when the user wants to write a postmortem for a resolved incident.
---

# Write a Postmortem

Write in a blameless style. Name systems and gaps, never people.

If a draft sentence contains a person's name next to a mistake, rewrite it.

## Step 1: Timeline from records

Build the timeline from logs, deploy history, and alert timestamps, not from memory.

Mark every entry that could not be confirmed from a record.

## Step 2: Contributing factors

List at least two contributing factors.

Single root causes are usually the last factor noticed, not the only factor involved.

For each factor, state which safeguard was missing or failed.

## Step 3: What limited the damage

Record what went well and what was luck.

Luck is a gap wearing a disguise.

## Step 4: Action items

Each action item needs an owner and a test.

For each item, state whether it would have:

- prevented the incident
- shortened the incident
- improved detection

Drop items that do none of these.

## Output

Return:

- **Summary**: impact, duration, detection method, one paragraph
- **Timeline**: timestamped entries, with unconfirmed entries marked
- **Contributing factors**: each with the missing safeguard
- **Action items**: owner, prevent-or-shorten label, due date

This skill sits at the other end of the incident lifecycle. Because the description is specific, the agent should not confuse it with alert triage.

Step 3: Wire the skills into the agent

Create the agent file:

langgraph-deepagent-skills-demo/sre_agent.py

Add the following code:

import os

from pathlib import Path
from langchain.chat_models import init_chat_model
from deepagents import create_deep_agent
from deepagents.backends.filesystem import FilesystemBackend

from dotenv import load_dotenv
load_dotenv()

model = init_chat_model("openai:gpt-4o")

sre_dir = Path(__file__).parent
    
backend = FilesystemBackend(
    root_dir=str(sre_dir),
    virtual_mode=True,
)

agent = create_deep_agent(
    model=model,
    name="SRE_Assistant",
    backend=backend,
    skills=["/skills"],
    system_prompt="You are an SRE assistant.",
)

result = agent.invoke(
    {
        "messages": [
            {
                "role": "user",
                "content": (
                    "Triage this alert: p99 latency on the checkout API jumped "
                    "from 180ms to 2.4s over the last 10 minutes. "
                    "Error rate is normal. A deploy to the pricing service "
                    "went out 15 minutes ago."
                ),
            }
        ]
    }
)

print(result["messages"][-1].content)

The important parameter is this one:

skills=["/skills"]

That tells the agent where to scan for skills inside the backend filesystem.

With this configuration, the agent expects these files to exist:

/skills/triage-alert/SKILL.md
/skills/write-postmortem/SKILL.md

The frontmatter from both files is read at startup. The bodies remain on disk until the agent calls read_file for the selected skill.

Step 4: Run the alert triage example

Run the script:

uv run sre_agent.py

The agent should select the triage-alert skill because the user is asking to triage an active alert.

A typical response should classify the incident based on user-facing impact, mention that the checkout API latency is the deciding signal, identify the pricing-service deploy as a likely correlated change, and recommend whether to page or create a ticket.

**Severity**: High, due to significant increase in latency from 180ms to 2.4s affecting the checkout process, which is critical for users.

**Blast radius**: The alert directly affects the checkout API. Given that error rates are normal, it indicates customers are experiencing slower response times but not failures. It’s vital to trace dependencies on what services the checkout API calls and which services call it to determine if others are indirectly affected.

**Suspected cause**: The deploy to the pricing service 15 minutes ago is a likely suspect, as it closely precedes the latency increase.

**Decision**: Page. The user-facing impact is active with worsening latency, necessitating immediate attention. The status update should include the observed latency increase, suspected linkage to the recent pricing service deploy, and the absence of elevated error rates.

Step 5: Run the postmortem example

Now test the second skill with this input:

Write a postmortem: yesterday the payment service was down for 43 minutes. 
A config change doubled the connection pool size, which exhausted database connections. 
Rolling back the config restored service.

The agent should select the write-postmortem skill because the user is asking for a postmortem after a resolved incident.

Expected behavior:

User request
   ↓
Skill index is available in context
   ↓
Agent matches request to write-postmortem description
   ↓
Agent reads /skills/write-postmortem/SKILL.md
   ↓
Agent follows the postmortem procedure
   ↓
Agent returns summary, timeline, contributing factors, and action items

The triage-alert body should not be loaded for this request. It remains available only as one line in the skill index.

Step 6: Chain skills across a workflow

Skills can also chain naturally across a conversation.

Start with triage:

Triage this alert: p99 latency on the checkout API jumped from 180ms to 2.4s over the last 10 minutes. 
Error rate is normal. A deploy to the pricing service went out 15 minutes ago.

Then follow up:

We rolled back the pricing deploy and latency recovered. Write the postmortem.

The agent should first load triage-alert, then later load write-postmortem. The second skill can reuse the triage findings already present in the conversation.

No custom orchestration code is needed for this transition. The model routes to the next skill using the same skill index and description matching.

sequenceDiagram participant User participant Agent participant Index as Skill Index participant Triage as triage-alert/SKILL.md participant PM as write-postmortem/SKILL.md User->>Agent: Triage this checkout latency alert Agent->>Index: Check available skill descriptions Index-->>Agent: triage-alert matches Agent->>Triage: read_file Triage-->>Agent: Return triage procedure Agent-->>User: Severity, blast radius, suspected cause, decision User->>Agent: Latency recovered. Write the postmortem. Agent->>Index: Check available skill descriptions Index-->>Agent: write-postmortem matches Agent->>PM: read_file PM-->>Agent: Return postmortem procedure Agent-->>User: Summary, timeline, contributing factors, action items

Summary

Skills give LangGraph Deep Agents a practical way to manage context.

Instead of putting every workflow into one large system prompt, you package each workflow as a focused SKILL.md file. The agent reads the frontmatter at startup, uses the description as a routing signal, and loads the full skill body only when needed.

The result is a cleaner agent architecture:

Memory
  Always-relevant conventions

System prompt
  Core role and boundaries

Skills
  On-demand workflows loaded when relevant

For deep research agents, this pattern is especially useful because research is naturally multi-stage. The agent may need to plan, search, compare, validate, and write, but it does not need all those instructions in context at the same time.

Start with two focused skills. Check the trace. Confirm that the right SKILL.md file is loaded. Then add more skills as your agent’s workflow becomes clearer.

Find more about Skills in LangGraph Documentation here

Posts in this series