Skills
A skill is a block of instructions the agent loads on demand. You write the skill, a SKILL.md
and the files beside it; the SDK puts its files in the sandbox and lists only its name and
description in the system prompt. The agent reads the body with the built-in skill.read tool when it
decides the skill applies.
Use a skill for a procedure too long to keep in instructions= and needed in only some turns. The
API reference lists every kind of skill and its options.
Add a skill
skills= on the Agent takes every skill of the agent, in one list: local skill bundles and
registry skills.
From a directory
Write each skill as its own directory under a skills/ directory in your project, named after the
skill, the layout every coding agent uses:
hello_agent/
├── main.py
└── skills/
└── refund-policy/
└── SKILL.mdSKILL.md is YAML frontmatter and then the body:
---
name: refund-policy
description: The refund rules. Use when a customer asks for a refund.
---
Refund a customer only when the order is under 30 days old.description is what the model sees in the system prompt, so write it as what this is, and when
to use it. LocalSkillBundle.from_directory() reads one such directory into a bundle. The example uses
MistralSandbox. It needs the cloud_user role (Requirements)
and the sandbox extra: uv add "mistralai-agents[koyeb]".
import asyncio
from pathlib import Path
from mistralai import agents
SKILLS = Path(__file__).with_name("skills") # resolve against __file__, not the working directory
agent = agents.Agent(
model="mistral-large-4",
name="refund-agent",
environment=agents.MistralSandbox(),
skills=[
agents.LocalSkillBundle.from_directory(SKILLS / "refund-policy"),
],
)
async def main() -> None:
result = await agent.run("My order is 45 days old. Can I get a refund? Answer in one sentence.")
if isinstance(result, agents.Completed):
print(result.text)
print([call.name for call in result.tool_calls])
if __name__ == "__main__":
asyncio.run(main())The model saw the skill's description, loaded its body with skill.read, and applied the rule.
When the body has no directory, such as in a test, build the bundle from
agents.LocalSkillFile objects instead.
Skill files in the sandbox
A skill needs a sandbox that can hold its files, such as MistralSandbox or a local sandbox: each
skill is a folder there, with SKILL.md and every file beside it, and the model reads and runs
those files as any other. The default NoSandbox() cannot hold files, so the SDK refuses skills
on it before any model call.
Skills from the AI Registry
A registry skill is a skill stored in the Mistral AI Registry and named by its UUID. Pass it in
skills=, in the same list as your local skills:
import uuid
from pathlib import Path
from mistralai import agents
SKILLS = Path(__file__).with_name("skills")
agent = agents.Agent(
model="mistral-large-4",
environment=agents.MistralSandbox(),
skills=[
agents.LocalSkillBundle.from_directory(SKILLS / "refund-policy"),
agents.RegistrySkill(id=uuid.UUID("0199c5e1-8a3b-7d42-9f10-3c5e7a2b1d84"), version=3),
],
)Set version=: the session refuses a registry skill without one, so every session runs the exact version you name. If the SDK cannot fetch
the skill, the session fails to open. A deployed agent sees only the skills shared with its
workspace: share each registry skill with the workspace before you deploy.
To serve every registry skill the session's user can access, add agents.all_registry_skills() to
skills=. Each skill adds prompt tokens, so name the ones you need as RegistrySkill entries when
there are many. Its options are in the
API reference.
Ship a skill with a deploy
agents deploy builds the commit you pushed, so a committed skills/ directory ships with it and
needs no COPY of its own. If you exclude it in .dockerignore, or leave it uncommitted,
from_directory() raises when the deployed agent starts.
Common issues
| You see | Fix |
|---|---|
Unsupported Agents SDK feature 'skills': ... NoSandbox() cannot hold files | Pass a sandbox, such as environment=agents.MistralSandbox(). |
Unsupported Agents SDK feature 'skills': registry skill <id> has no version | Set version= on the RegistrySkill. |
The deployed agent fails to start, and from_directory() raised | Commit the skills/ directory, and remove it from .dockerignore. |
Next
Structured output: get the agent's answer back as a Pydantic model.