Skip to content

Skills Pattern

Updated
17 Sept 2026
6 min read
0 sections
Page 9 of 18
Langgraph

The mental model: a Swiss Army knife, or a skilled contractor

A Swiss Army knife is a single tool with different implementations folded inside it: scissors, a saw blade, a nail file, a screwdriver. You pull out whichever blade fits the cut you need. That's the skills pattern: a multi-agent architecture that runs on a single agent, one that dynamically loads specialized instructions and tools based on what the current task actually needs.

A closer analogy: imagine hiring Frank, a general contractor. Frank went to technical school and picked up plumbing, electrical work, carpentry, and upholstery along the way. When you tell him "fix these broken sockets and install lights outside," Frank loads his electrical knowledge into working memory and gets to work. Later, when you ask him to fix a leaky pipe, he unloads electrical, loads plumbing, and switches gears. It's the same person, accessing different expertise, as needed.

This isn't the same thing as the handoffs pattern, even though both can dynamically swap an agent's prompt and tools. Handoffs are sequential and stateful, control passes from one stage of a journey to the next. Skills has no notion of sequence or "next stage": you ask for one thing, the agent loads the matching skill, finishes it, and is done. Ask for something unrelated, and it loads a different skill. Anthropic has described this as how Claude Code itself works, and it's the same idea behind writing "skills" for other agentic tools like OpenCode.


How a request flows through the pattern

  1. The agent ships with base instructions (general knowledge, e.g. how a house fits together) and a skill discovery tool.
  2. A user request comes in. The agent calls the discovery tool to see which skills are available.
  3. It identifies the relevant skill (say, plumbing) and calls a use_skill function to load it.
  4. That skill's instructions, tools, and any supporting context get injected into the agent's context.
  5. The agent uses the newly loaded skill to fulfill the request, and the skill stays loaded for follow-up questions. A new, unrelated request later can unload it and load a different skill instead.

Characteristics of the skills pattern

  1. Single agent - it's a multi-agent architecture built from exactly one agent that shape-shifts. No separate agent instances, no coordination between them.
  2. On-demand loading - skills load only when the task calls for them, not all up front.
  3. Additive context - loading a skill adds its instructions and tools on top of the agent's base instructions; it doesn't replace them.
  4. A skill discovery system is required - the agent needs a way to enumerate available skills and pick the right one for the job.
  5. Weak isolation - every loaded skill shares the same context window, so you don't get the clean separation a pattern like sub-agents gives you.
  6. Low communication overhead - there's no inter-agent messaging bus to build, no handoffs, no reporting back. It's one agent talking to itself.

What a skill is made of

Every skill package has three parts:

  • Instructions - sub-instructions specific to the skill (e.g., "always use parameterized queries," "limit results to 100 rows unless specified") that layer on top of the agent's base instructions.
  • Tools - the concrete actions the skill needs (a database skill needs execute_sql, list_tables, describe_table).
  • Metadata - name, description, and "when to use this" guidance that the discovery tool uses to match a skill to a request.

Implementing skills in LangGraph

python
SKILLS = {
    "sql_query": {
        "description": "Query and inspect SQL databases",
        "instructions": """You are now equipped to work with SQL databases.
            Guidelines:
            - Always use parameterized queries to prevent SQL injection
            - Limit results to 100 rows unless specified
            - Explain query logic before executing""",
        "tools": [execute_sql, list_tables, describe_table],
    },
    "data_viz": {
        "description": "Visualize tabular data",
        "instructions": "...",
        "tools": [plot_chart, render_table],
    },
}

@tool
def get_skills() -> str:
    """List all available skills and their descriptions."""
    return "\n".join(f"{name}: {s['description']}" for name, s in SKILLS.items())

@tool
def use_skill(skill_name: str) -> str:
    """Load a skill's instructions and tools into context."""
    if skill_name not in SKILLS:
        return f"Unknown skill: {skill_name}"
    skill = SKILLS[skill_name]
    return f"Loaded skill '{skill_name}'.\nInstructions: {skill['instructions']}"

get_skills lets the agent discover what's available; use_skill loads a chosen skill's instructions and tools into context, and the agent recognizes the newly relevant tools from the full tool list it was given at creation.

If you don't want every skill's tools loaded up front (10 skills × 10 tools each adds up fast), load tools dynamically via a wrap_model_call middleware instead:

python
@wrap_model_call
def inject_skill_tools(request, handler):
    loaded_skills = request.state.get("loaded_skills", [])
    new_tools = [t for name in loaded_skills for t in SKILLS[name]["tools"]]
    if new_tools:
        request = request.override(tools=request.tools + new_tools)
    return handler(request)

Benefits vs. trade-offs

Benefits:

  • Simplicity - one agent, no coordination logic, no communication bus, no handoffs.
  • Low latency - no routing overhead between separate agents; a single agent just loads what it needs.
  • Flexible composition - multiple skills can be loaded simultaneously when a task genuinely spans domains (plumbing + electrical knowledge at once), without any agentic gymnastics.
  • Easy to extend - add a new skill without restructuring anything; the agent discovers and uses it on its own.
  • Shared context - all loaded skills see the full conversation, so cross-domain conflicts (e.g., "don't run wiring near that pipe") can actually be caught.
  • Natural conversational flow - there's no "transferring you to..." moment; it feels like one continuous conversation with one agent.
  • Cost efficient - one agent, one context window, no extra calls spent on inter-agent communication.
  • Easier debugging - a single execution path to trace, instead of tracking handoffs or coordination across multiple agents.

Trade-offs:

  • Context window pressure - loaded skills consume tokens and get mixed together; the model needs to be sharp about which instructions apply when.
  • Weak isolation - skills aren't cleanly separated, so conflicting instructions between skills can produce confusing or contradictory behavior. Skill instructions must be written to coexist.
  • No parallelism - the agent can't run two skills at once; only one is active in a given moment.
  • Risk of tool overload - because everything loads additively, without a deliberate unloading strategy you can end up with too many skills and tools stacked in context, hurting tool selection.
  • Prompt complexity - the base prompt and every loaded skill's instructions all have to coexist without conflict, and that combined prompt only grows as more skills stack up.
  • No true specialization - it's still one model doing everything. Model-swapping middleware can help, but swapping models mid-conversation brings its own context-transfer complexity.

When to use this pattern

Reach for skills when a single agent needs to be multi-talented but only ever does one thing at a time, no sequencing, no handoff journey, just "load the right capability and go."

Common use cases

  • Coding assistants - load language-specific skills for Python, SQL, or JavaScript on demand (this is the pattern behind Claude Code and similar tools).
  • Knowledge bases - switch between domain expertise as the conversation's topic shifts.
  • Document processing - load different skills to handle different file types.
  • Data analysis - combine querying, visualization, and interpretation skills depending on what the task needs, one at a time, but composable.
  • Writing assistants - load a formal, casual, or technical tone skill depending on the type of document being written.
  • DevOps automation - load AWS, Azure, or GCP skills depending on which cloud platform the client uses.

As with any pattern, "use case" here means it fits a specific problem inside that domain, not that it's the only correct choice for the whole system. Often, a skills-based agent is one node inside a larger sub-agents or handoffs graph.