Introducing pydantic-ai-skills: Composable Agent Skills for the Pydantic AI Ecosystem

Give your AI agents superpowers — without bloating their context window.

The Agentic AI landscape is evolving fast. We went from simple chatbots to autonomous systems that plan, reason, and execute multi-step workflows. But as agents grow more capable, a familiar engineering problem emerges: how do you add new capabilities without turning your system prompt into an unmanageable monolith?

That’s the problem pydantic-ai-skills solves. It’s a standardized, composable framework for building and managing Agent Skills within the Pydantic AI ecosystem. Inspired by Anthropic’s Agent Skills open standard — released in December 2025 as a vendor-neutral specification for portable AI capabilities — this library brings the same progressive disclosure pattern to any Pydantic AI agent.

The Problem: Context Window Bloat

If you’ve built production agents, you know the pain. You start with a clean system prompt, then add instructions for searching the web, then database queries, then report generation, then… suddenly your agent is consuming thousands of tokens before it even reads the user’s message.

Every new capability means more instructions stuffed into the prompt. Agents get confused. Token costs skyrocket. Maintenance becomes a nightmare.

pydantic-ai-skills takes a different approach: progressive disclosure. Skills are discovered and loaded on demand, keeping your agent’s context lean and focused. The agent only loads the full instructions for a skill when it actually needs it.

How It Works

The library implements a tool-based approach that gives agents structured access to skills using 4 tools:

  • list_skills()Discover all available skills (names + descriptions).
  • load_skill(name)Load complete instructions for a specific skill.
  • read_skill_resource(skill_name, resource_name)Access additional documentation, templates, or data files.
  • run_skill_script(skill_name, script_name, args)Execute Python scripts defined within a skill.

This progressive approach means an agent with 50 skills doesn’t need to load all 50 sets of instructions upfront. It sees the menu, picks what it needs, and dives deeper only when required.

Getting Started

You can quickly install it using the command below.

pip install pydantic-ai-skills

Your First Skill

Every file-based skill is just a directory with a SKILL.md file. The frontmatter contains metadata, and the markdown body contains instructions for the agent.[1]

Create a file at ./skills/pydanticai-docs/SKILL.md:

---
name: pydanticai-docs
description: Quick reference for Pydantic AI framework
---

# Pydantic AI Docs

Quick reference for building agents with Pydantic AI.

## Instructions

For detailed information, fetch the full docs at:
https://ai.pydantic.dev/llms-full.txt

## Quick Examples

**Basic Agent:**
```python
from pydantic_ai import Agent

agent = Agent('openai:gpt-4o')
result = agent.run_sync('Your question')

### Wiring Skills to an Agent

Now create your agent with the `SkillsToolset`:

```python
import asyncio
from pydantic_ai import Agent, RunContext
from pydantic_ai_skills import SkillsToolset

async def main():
# Initialize skills from a directory
skills_toolset = SkillsToolset(directories=["./skills"])

# Create agent with skills as a toolset
agent = Agent(
model='openai:gpt-4o',
instructions='You are a helpful assistant.',
toolsets=[skills_toolset]
)

# Inject skill descriptions into the agent's instructions
@agent.instructions
async def add_skills(ctx: RunContext) -> str | None:
"""Add skills instructions to the agent's context."""
return await skills_toolset.get_instructions(ctx)

# Run — the agent will discover and use skills automatically
result = await agent.run(
"How do I create a Pydantic AI agent with tools?"
)
print(result.output)

if __name__ == "__main__":
asyncio.run(main())

That’s it. The agent now automatically discovers the pydanticai-docs skill, loads it when relevant, and uses its instructions to answer questions about Pydantic AI.

Script-Based Skills: Going Beyond Instructions

Skills aren’t limited to text instructions. You can bundle executable Python scripts that agents can run on demand. Here’s a calculator skill with a script:

./skills/
└── calculator/
├── SKILL.md
└── scripts/
└── calculate.py

SKILL.md:

---
name: calculator
description: Perform calculations using Python
---

# Calculator Skill

Use the `calculate` script to perform mathematical operations.

scripts/calculate.py:

"""Evaluate a Python expression and return the result as JSON."""

import argparse
import json
import sys

parser = argparse.ArgumentParser()
parser.add_argument('--expression', required=True, help='Python expression to evaluate')
args = parser.parse_args()

try:
result = eval(args.expression)
print(json.dumps({'result': result}))
except Exception as e:
print(f'Error: {e}', file=sys.stderr)
sys.exit(1)

When the agent encounters a math problem, it can call run_skill_script(skill_name=”calculator”, script_name=”calculate”, args={“expression”: “2**10”}) and get {“result”: 1024} back.

Programmatic Skills: Dynamic Capabilities in Code

File-based skills are great for stable, shareable capabilities. But sometimes you need skills that are generated at runtime, depend on live configuration, or require dependency injection. That’s where programmatic skills come in.

from pydantic_ai import Agent, RunContext
from pydantic_ai_skills import Skill, SkillsToolset, SkillResource

# Create a skill object directly in Python
my_skill = Skill(
name='data-processor',
description='Process and analyze data',
content='Use this skill for data analysis tasks.',
resources=[
SkillResource(
name='reference',
content='## ReferencennStatic reference documentation here...'
)
]
)

# Add a dynamic resource via decorator
@my_skill.resource
def get_schema() -> str:
"""Get current data schema."""
return "Available fields: id, name, value, timestamp"

# Add an executable script via decorator
@my_skill.script
async def process_data(ctx: RunContext, query: str) -> str:
"""Process data based on query."""
results = await ctx.deps.process(query)
return f"Processed {len(results)} records"

# Wire it up
skills_toolset = SkillsToolset(skills=[my_skill])

Programmatic skills support full RunContext dependency injection, allowing your scripts and resources to access databases, APIs, and any other runtime dependencies your agent needs.

The Decorator Pattern: Inline Skill Definitions

For skills tightly coupled with agent initialization, the @toolset.skill() decorator offers the most concise syntax:

from pydantic_ai import Agent, RunContext
from pydantic_ai_skills import SkillsToolset

skills_toolset = SkillsToolset()

@skills_toolset.skill()
def data_analyzer() -> str:
"""Analyze data from various sources."""
return """
# Data Analysis Skill

Use this skill to analyze datasets and generate insights.
"""

@data_analyzer.resource
async def get_schema(ctx: RunContext) -> str:
"""Get database schema from live connection."""
schema = await ctx.deps.database.get_schema()
return f"## Current Scheman{schema}"

agent = Agent(
model='openai:gpt-4o',
toolsets=[skills_toolset]
)

@agent.instructions
async def add_skills(ctx: RunContext) -> str | None:
"""Add skills instructions to the agent's context."""
return await skills_toolset.get_instructions(ctx)

Mixing File-Based and Programmatic Skills

One of the most powerful patterns is combining both approaches — stable, reusable skills from files alongside dynamic, runtime-specific skills defined in code:

from pydantic_ai_skills import SkillsToolset

# Load file-based skills AND add programmatic ones
skills_toolset = SkillsToolset(
directories=[
"./skills/research", # Shared research skills
"./skills/data", # Data processing skills
],
validate=True,
)

# Add a runtime-specific skill inline
@skills_toolset.skill(name='runtime-monitor', metadata={'version': '1.0.0'})
def monitoring() -> str:
return "Monitor application runtime metrics"

agentskills.io Compatibility

The library implements the agentskills.io specification, which was released by Anthropic as an open standard in December 2025 and adopted by Microsoft, OpenAI, Atlassian, Figma, Cursor, and GitHub. Skills created with pydantic-ai-skills are structurally compatible with Anthropic’s skill format — including the SKILL.md file structure, naming conventions (lowercase, hyphens, ≤64 chars), and the progressive disclosure loading pattern.

This means skills built for this library can potentially be reused across different platforms that support the Agent Skills standard.

Security Considerations

Since skills provide agents with new capabilities through instructions and executable code, security is critical. The library implements several safeguards:

  1. Path traversal prevention — Scripts and resources must be within the skill directory
  2. Script timeout — Scripts are killed after a configurable timeout
  3. Safe subprocess execution — Scripts run in subprocesses with limited privileges
  4. Validation — Automatic validation of skill metadata and structure

The documentation strongly recommends using only skills from trusted sources — those created in-house or obtained from vetted providers.[1]

Why pydantic-ai-skills?

The library was inspired by the pydantic-deepagents project, which pioneered many of the skill patterns in the Pydantic AI ecosystem. Here’s what sets pydantic-ai-skills apart:

  1. Focused scope — It does one thing well: skill management. No planning loops, no filesystem toolsets, no subagent delegation. Just clean, composable skills.
  2. Drop-in integration — Works as a standard Pydantic AI Toolset, so it plugs into any existing agent without architectural changes.
  3. Type-safe — Built on Python dataclasses and type hints with full type annotation support.
  4. Agentskills.io spec — Structurally aligned with the Agent Skills open standard.
  5. Lightweight — Minimal dependencies; install and use in minutes.

Real-World Example: Research Assistant

Here’s a complete example of a research assistant that uses an ArXiv search skill:

import asyncio
from pydantic_ai import Agent, RunContext
from pydantic_ai_skills import SkillsToolset

async def main():
skills_toolset = SkillsToolset(directories=["./examples/skills"])

agent = Agent(
model='openai:gpt-4o',
instructions=(
"You are a research assistant specializing in "
"academic papers."
),
toolsets=[skills_toolset]
)

@agent.instructions
async def add_skills(ctx: RunContext) -> str | None:
return await skills_toolset.get_instructions(ctx)

result = await agent.run(
"Find the 5 most recent papers on transformer architectures"
)
print(result.output)

if __name__ == "__main__":
asyncio.run(main())

The agent discovers the arxiv-search skill, loads its instructions, and uses run_skill_script to execute the search — all without any ArXiv-specific code in the agent itself.

What’s Next

The library is at version 0.4.1 and actively maintained. The documentation includes guides on creating skills, programmatic skills, advanced features like custom script executors and dependency injection, implementation patterns, and security best practices.

See more on:

If you’re building Pydantic AI agents and want to keep them modular, maintainable, and efficient, give pydantic-ai-skills a try. Skills are the building blocks of capable agents, and progressive disclosure is how you scale without drowning in context.


Introducing pydantic-ai-skills: Composable Agent Skills for the Pydantic AI Ecosystem was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.

Liked Liked