Skills Discovery
Agent Skills provides three ways to load skills into a toolset, plus a search API for runtime discovery. The three mechanisms can be combined freely.
Loading Skills into a Toolset
1. Path-based loading
Point AgentSkillsToolset at one or more local directories. Every
sub-directory containing a SKILL.md file is discovered automatically when
the toolset is first used.
When to use: skills checked into the same repository, or mounted at a well-known path at runtime (e.g. a Kubernetes shared volume).
from agent_skills import AgentSkillsToolset, SandboxExecutor
from code_sandboxes import CodeSandboxClient
toolset = AgentSkillsToolset(
directories=["./skills"], # scanned recursively for SKILL.md
executor=SandboxExecutor(CodeSandboxClient.create(variant="eval")),
)
Expected directory layout:
skills/
├── pdf-extractor/
│ ├── SKILL.md
│ └── scripts/
│ └── extract.py
└── data-analyzer/
├── SKILL.md
└── scripts/
└── analyze.py
2. Module-based loading
Use AgentSkill.from_module() to load skills that are packaged inside an
installed Python library. Works for both regular packages (with
__init__.py) and namespace packages (directories without
__init__.py, where __file__ is None).
When to use: skills distributed as part of a pip-installable package,
such as the built-in skills in agent-skills itself.
from agent_skills import AgentSkill, AgentSkillsToolset, SandboxExecutor
from code_sandboxes import CodeSandboxClient
toolset = AgentSkillsToolset(
skills=[
AgentSkill.from_module("agent_skills.skills.crawl"),
AgentSkill.from_module("agent_skills.skills.github"),
AgentSkill.from_module("agent_skills.skills.pdf"),
AgentSkill.from_module("agent_skills.skills.events"),
],
executor=SandboxExecutor(CodeSandboxClient.create(variant="eval")),
)
from_module() imports the module, resolves its directory, and delegates
to AgentSkill.from_skill_md() — no extra configuration needed.
3. Entrypoint-based loading (automatic)
Installed Python packages that declare entrypoints in the
agent_skills.skills group are discovered automatically when the
toolset initialises. No explicit configuration is required — just install
the package and the skills appear.
When to use: distributing skills as standalone pip-installable packages that consumers can install independently. This is the recommended approach for sharing skills across teams or publishing them on PyPI.
from agent_skills import AgentSkillsToolset, SandboxExecutor
from code_sandboxes import CodeSandboxClient
# Entrypoint skills are found automatically — no skills= or directories= needed
toolset = AgentSkillsToolset(
executor=SandboxExecutor(CodeSandboxClient.create(variant="eval")),
)
The package registers its skills in pyproject.toml:
[project.entry-points."agent_skills.skills"]
whoami = "datalayer_skills.skills.whoami"
Each key is a skill name and each value is a dotted Python module path
that contains a SKILL.md file (the same layout used by
AgentSkill.from_module()).
To disable entrypoint scanning (e.g. for testing), set
discover_entrypoints=False:
toolset = AgentSkillsToolset(
discover_entrypoints=False,
executor=SandboxExecutor(CodeSandboxClient.create(variant="eval")),
)
You can also call the discovery function directly:
from agent_skills import discover_entrypoint_skills
for skill in discover_entrypoint_skills():
print(f"{skill.name}: {skill.description}")
Combining all three
The three approaches stack freely. Skills loaded via skills= are merged
with any skills discovered from directories= and from entrypoints:
toolset = AgentSkillsToolset(
directories=["./skills"], # local / custom skills
skills=[
AgentSkill.from_module("agent_skills.skills.crawl"),
],
# discover_entrypoints=True (default) — finds installed packages too
executor=SandboxExecutor(CodeSandboxClient.create(variant="eval")),
)
In a Kubernetes / SaaS pod
In the Datalayer SaaS deployment the agent-runtimes container runs alongside a Jupyter container in the same pod. The two loading patterns map to the two-container architecture as follows:
┌─────────────────────────────── Pod ────────────────────────────────────┐
│ │
│ agent-runtimes :8765 jupyter :2300 │
│ ┌──────────────────────────┐ ┌────────────────────────────┐ │
│ │ AgentSkillsToolset │ │ Jupyter Kernel │ │
│ │ │ │ ┌──────────────────────┐ │ │
│ │ Module-based ──────────►│──reads────► │ skill script code │ │ │
│ │ (agent_skills pip pkg) │ script │ │ (sent as string via │ │ │
│ │ │ content │ │ SandboxExecutor) │ │ │
│ │ Path-based ────────────►│──reads────► └──────────────────────┘ │ │
│ │ (/mnt/shared-agent/ │ SKILL.md │ │ │
│ │ skills/) │ │ Shared Volume: │ │
│ └──────────────────────────┘ │ /mnt/shared-agent/ │ │
│ │ └── skills/ ◄── also │ │
│ │ accessible here │ │
│ └────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
-
Module-based —
agent-skillsis pip-installed in the image → the agent usesAgentSkill.from_module()to get skill metadata. Script code is read from the installed package and sent as a string to the Jupyter kernel viaSandboxExecutor. -
Path-based — the container entrypoint copies
/opt/datalayer/skills/→/mnt/shared-agent/skills/(a KubernetesemptyDirshared by both containers). SetAGENT_RUNTIMES_SKILLS_FOLDER=/mnt/shared-agent/skillsso agent-runtimes scans the shared volume for any additional or custom skills.
Regardless of how a skill is loaded, script execution always happens
inside the Jupyter kernel — the SandboxExecutor reads the script file
content from the agent-runtimes side and sends it as Python source code to
the kernel over the Jupyter HTTP API.
Runtime Discovery via the Agent
When AgentSkillsToolset is attached to an agent, the agent can discover
skills dynamically through two built-in tools.
list_skills
Lists all available skills with summaries:
# Agent calls: list_skills()
# Returns:
[
{
"name": "data-analyzer",
"description": "Analyzes datasets and provides insights",
"tags": ["data", "analysis"],
"scripts": ["analyze", "summarize"],
"resources": ["reference"]
},
{
"name": "file-processor",
"description": "Process files in batches",
"tags": ["files", "batch"],
"scripts": ["process", "validate"],
"resources": []
}
]
load_skill
Get full details for a specific skill:
# Agent calls: load_skill(skill_name="data-analyzer")
# Returns:
{
"name": "data-analyzer",
"description": "Analyzes datasets and provides insights",
"content": "# Data Analyzer\n\nUse this skill to analyze...",
"scripts": [
{"name": "analyze", "description": "Analyze a data file"},
{"name": "summarize", "description": "Summarize analysis results"}
],
"resources": [
{"name": "reference", "description": "Reference documentation"}
],
"tags": ["data", "analysis"],
"allowed_tools": ["filesystem__read_file"],
"version": "1.0.0"
}
The agent calls list_skills to browse what is available, then
load_skill to get the full instructions before executing a skill script.