Skip to content

SkillsCapability API Reference

SkillsCapability integrates pydantic-ai-skills with Pydantic AI's capabilities API.

This is the preferred integration path. Use it when your agent uses capabilities=[...].

Bases: AbstractCapability[Any]

Capability wrapper for SkillsToolset.

Use this class with the agent capabilities=[...] API.

Example
from pydantic_ai import Agent
from pydantic_ai_skills import SkillsCapability

agent = Agent(
    model='openai:gpt-5.2',
    capabilities=[SkillsCapability(directories=['./skills'])],
)

Set defer_loading=True (with a stable id) to hide the skills tools and instructions behind the agent's load_capability tool until the model explicitly loads them:

```python
agent = Agent(
    model='openai:gpt-5.2',
    capabilities=[
        SkillsCapability(id='skills', directories=['./skills'], defer_loading=True),
    ],
)
```

The capability is usable in declarative agent specs (Agent.from_spec / Agent.from_file) by passing it via custom_capability_types:

```yaml
capabilities:
  - SkillsCapability:
      directories: ['./skills']
      defer_loading: true
      id: skills
```

```python
agent = Agent.from_file('agent.yaml', custom_capability_types=[SkillsCapability])
```

Only serializable arguments are spec-expressible (see [from_spec][pydantic_ai_skills.SkillsCapability.from_spec]); programmatic skills, registries, and SkillsDirectory instances require Python construction.

Source code in pydantic_ai_skills/capability.py
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
@dataclass
class SkillsCapability(AbstractCapability[Any]):
    """Capability wrapper for `SkillsToolset`.

    Use this class with the agent `capabilities=[...]` API.

    Example:
        ```python
        from pydantic_ai import Agent
        from pydantic_ai_skills import SkillsCapability

        agent = Agent(
            model='openai:gpt-5.2',
            capabilities=[SkillsCapability(directories=['./skills'])],
        )
        ```

    Set `defer_loading=True` (with a stable `id`) to hide the skills tools and
    instructions behind the agent's `load_capability` tool until the model
    explicitly loads them:

        ```python
        agent = Agent(
            model='openai:gpt-5.2',
            capabilities=[
                SkillsCapability(id='skills', directories=['./skills'], defer_loading=True),
            ],
        )
        ```

    The capability is usable in declarative agent specs (`Agent.from_spec` /
    `Agent.from_file`) by passing it via `custom_capability_types`:

        ```yaml
        capabilities:
          - SkillsCapability:
              directories: ['./skills']
              defer_loading: true
              id: skills
        ```

        ```python
        agent = Agent.from_file('agent.yaml', custom_capability_types=[SkillsCapability])
        ```

    Only serializable arguments are spec-expressible (see
    [`from_spec`][pydantic_ai_skills.SkillsCapability.from_spec]); programmatic
    `skills`, `registries`, and `SkillsDirectory` instances require Python construction.
    """

    _: KW_ONLY

    skills: list[Skill] | None = None
    """Pre-loaded skills."""

    directories: list[str | Path | SkillsDirectory] | None = None
    """Skill directories to discover."""

    registries: list[SkillRegistry] | None = None
    """Remote registries to discover."""

    validate: bool = True
    """Validate skill structure during discovery."""

    max_depth: int | None = 3
    """Maximum discovery depth."""

    instruction_template: str | None = None
    """Optional custom instructions template."""

    exclude_tools: set[str] | list[str] | None = None
    """Tool names to exclude."""

    auto_reload: bool = False
    """Re-scan directories before each run."""

    _toolset: SkillsToolset = field(init=False, repr=False, compare=False)

    def __post_init__(self) -> None:
        """Validate deferred configuration and build the underlying toolset.

        Raises:
            ValueError: If ``defer_loading`` is True but no ``id`` is provided.
        """
        if self.defer_loading and self.id is None:
            raise ValueError("SkillsCapability requires a stable 'id' when defer_loading=True.")

        self._toolset = SkillsToolset(
            skills=self.skills,
            directories=self.directories,
            registries=self.registries,
            validate=self.validate,
            max_depth=self.max_depth,
            id=self.id,
            instruction_template=self.instruction_template,
            exclude_tools=self.exclude_tools,
            auto_reload=self.auto_reload,
        )

    @classmethod
    def get_serialization_name(cls) -> str | None:
        """Return the name used to reference this capability in agent specs."""
        return 'SkillsCapability'

    @classmethod
    def from_spec(
        cls,
        *,
        directories: list[str] | None = None,
        validate: bool = True,
        max_depth: int | None = 3,
        id: str | None = None,
        instruction_template: str | None = None,
        exclude_tools: list[str] | None = None,
        auto_reload: bool = False,
        description: str | None = None,
        defer_loading: bool = False,
    ) -> SkillsCapability:
        """Create from a YAML/JSON agent spec.

        Only serializable arguments are supported. Programmatic `skills`, `registries`,
        and `SkillsDirectory` instances cannot be expressed in a spec; construct the
        capability in Python for those.

        Args:
            directories: Skill directories to discover, as path strings.
            validate: Validate skill structure during discovery.
            max_depth: Maximum discovery depth.
            id: Stable identifier shared by the capability and its toolset. Required when
                ``defer_loading`` is True.
            instruction_template: Optional custom instructions template.
            exclude_tools: Tool names to exclude.
            auto_reload: Re-scan directories before each run.
            description: Optional catalog description surfaced when ``defer_loading`` is True.
            defer_loading: If True, the skills tools and instructions stay hidden until the
                model loads this capability via the agent's ``load_capability`` tool.
        """
        return cls(
            directories=list(directories) if directories is not None else None,
            validate=validate,
            max_depth=max_depth,
            id=id,
            instruction_template=instruction_template,
            exclude_tools=exclude_tools,
            auto_reload=auto_reload,
            description=description,
            defer_loading=defer_loading,
        )

    def get_toolset(self) -> SkillsToolset | None:
        """Return the underlying skills toolset."""
        return self._toolset

    def get_instructions(self) -> AgentInstructions[AgentDepsT] | None:
        """Return None — instructions are pulled natively from the toolset by the agent."""
        return None

    def get_description(self) -> str | None:
        """Return the catalog description shown when this capability is deferred.

        Falls back to a summary of the available skill names when no explicit
        ``description`` was provided.
        """
        if self.description is not None:
            return self.description
        names = sorted(self._toolset.skills)
        if not names:
            return None
        return 'Provides specialized skills: ' + ', '.join(names) + '.'

    @property
    def toolset(self) -> SkillsToolset:
        """Expose the underlying `SkillsToolset` instance."""
        return self._toolset

__init__

__init__(*, skills: list[Skill] | None = None, directories: list[str | Path | SkillsDirectory] | None = None, registries: list[SkillRegistry] | None = None, validate: bool = True, max_depth: int | None = 3, instruction_template: str | None = None, exclude_tools: set[str] | list[str] | None = None, auto_reload: bool = False) -> None

from_spec classmethod

from_spec(*, directories: list[str] | None = None, validate: bool = True, max_depth: int | None = 3, id: str | None = None, instruction_template: str | None = None, exclude_tools: list[str] | None = None, auto_reload: bool = False, description: str | None = None, defer_loading: bool = False) -> SkillsCapability

Create from a YAML/JSON agent spec.

Only serializable arguments are supported. Programmatic skills, registries, and SkillsDirectory instances cannot be expressed in a spec; construct the capability in Python for those.

Parameters:

Name Type Description Default
directories list[str] | None

Skill directories to discover, as path strings.

None
validate bool

Validate skill structure during discovery.

True
max_depth int | None

Maximum discovery depth.

3
id str | None

Stable identifier shared by the capability and its toolset. Required when defer_loading is True.

None
instruction_template str | None

Optional custom instructions template.

None
exclude_tools list[str] | None

Tool names to exclude.

None
auto_reload bool

Re-scan directories before each run.

False
description str | None

Optional catalog description surfaced when defer_loading is True.

None
defer_loading bool

If True, the skills tools and instructions stay hidden until the model loads this capability via the agent's load_capability tool.

False
Source code in pydantic_ai_skills/capability.py
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
@classmethod
def from_spec(
    cls,
    *,
    directories: list[str] | None = None,
    validate: bool = True,
    max_depth: int | None = 3,
    id: str | None = None,
    instruction_template: str | None = None,
    exclude_tools: list[str] | None = None,
    auto_reload: bool = False,
    description: str | None = None,
    defer_loading: bool = False,
) -> SkillsCapability:
    """Create from a YAML/JSON agent spec.

    Only serializable arguments are supported. Programmatic `skills`, `registries`,
    and `SkillsDirectory` instances cannot be expressed in a spec; construct the
    capability in Python for those.

    Args:
        directories: Skill directories to discover, as path strings.
        validate: Validate skill structure during discovery.
        max_depth: Maximum discovery depth.
        id: Stable identifier shared by the capability and its toolset. Required when
            ``defer_loading`` is True.
        instruction_template: Optional custom instructions template.
        exclude_tools: Tool names to exclude.
        auto_reload: Re-scan directories before each run.
        description: Optional catalog description surfaced when ``defer_loading`` is True.
        defer_loading: If True, the skills tools and instructions stay hidden until the
            model loads this capability via the agent's ``load_capability`` tool.
    """
    return cls(
        directories=list(directories) if directories is not None else None,
        validate=validate,
        max_depth=max_depth,
        id=id,
        instruction_template=instruction_template,
        exclude_tools=exclude_tools,
        auto_reload=auto_reload,
        description=description,
        defer_loading=defer_loading,
    )

get_serialization_name classmethod

get_serialization_name() -> str | None

Return the name used to reference this capability in agent specs.

Source code in pydantic_ai_skills/capability.py
122
123
124
125
@classmethod
def get_serialization_name(cls) -> str | None:
    """Return the name used to reference this capability in agent specs."""
    return 'SkillsCapability'

get_toolset

get_toolset() -> SkillsToolset | None

Return the underlying skills toolset.

Source code in pydantic_ai_skills/capability.py
172
173
174
def get_toolset(self) -> SkillsToolset | None:
    """Return the underlying skills toolset."""
    return self._toolset

get_instructions

get_instructions() -> AgentInstructions[AgentDepsT] | None

Return None — instructions are pulled natively from the toolset by the agent.

Source code in pydantic_ai_skills/capability.py
176
177
178
def get_instructions(self) -> AgentInstructions[AgentDepsT] | None:
    """Return None — instructions are pulled natively from the toolset by the agent."""
    return None

get_description

get_description() -> str | None

Return the catalog description shown when this capability is deferred.

Falls back to a summary of the available skill names when no explicit description was provided.

Source code in pydantic_ai_skills/capability.py
180
181
182
183
184
185
186
187
188
189
190
191
def get_description(self) -> str | None:
    """Return the catalog description shown when this capability is deferred.

    Falls back to a summary of the available skill names when no explicit
    ``description`` was provided.
    """
    if self.description is not None:
        return self.description
    names = sorted(self._toolset.skills)
    if not names:
        return None
    return 'Provides specialized skills: ' + ', '.join(names) + '.'

toolset property

toolset: SkillsToolset

Expose the underlying SkillsToolset instance.

Constructor Parameters

SkillsCapability.__init__() accepts the same skill loading options as SkillsToolset:

Parameter Type Default Description
skills list[Skill] \| None None Pre-loaded Skill objects.
directories list[str \| Path \| SkillsDirectory] \| None None Local skill sources.
registries list[SkillRegistry] \| None None Remote skill sources.
validate bool True Validate discovered skills.
max_depth int \| None 3 Directory discovery depth.
id str \| None None Optional toolset id.
instruction_template str \| None None Optional custom instruction template.
exclude_tools set[str] \| list[str] \| None None Exclude one or more registered tools.
auto_reload bool False Re-scan local directories before each run.

Behavior Notes

  • Internally wraps a SkillsToolset for behavior parity.
  • get_toolset() and .toolset expose the wrapped SkillsToolset instance.
  • Bundles skill tools and skills instructions through the Capability API.
  • Avoids manual @agent.instructions wiring for get_instructions(ctx).
  • Raises RuntimeError at instantiation time if capabilities API is unavailable.

Example

from pydantic_ai import Agent
from pydantic_ai_skills import SkillsCapability

agent = Agent(
    model='openai:gpt-5.2',
    capabilities=[
        SkillsCapability(
            directories=['./skills'],
            auto_reload=True,
        )
    ],
)

Agent specs

SkillsCapability can be used in declarative agent specs loaded with Agent.from_spec or Agent.from_file. Register the class via custom_capability_types so the spec loader can resolve the SkillsCapability key:

# agent.yaml
model: openai:gpt-5.2
capabilities:
  - SkillsCapability:
      directories: ['./skills']
      id: skills
      defer_loading: true
from pydantic_ai import Agent
from pydantic_ai_skills import SkillsCapability

agent = Agent.from_file('agent.yaml', custom_capability_types=[SkillsCapability])

Only serializable arguments are spec-expressible: directories (as path strings), validate, max_depth, id, instruction_template, exclude_tools, auto_reload, description, and defer_loading. Programmatic skills, registries, and SkillsDirectory instances are not representable in a spec — construct the capability in Python for those. See from_spec.