jeevesagent.skills¶
Skills — packaged, on-demand instructions for agent tasks.
Anthropic Agent Skills (Oct 2025) plus the LangChain DeepAgents extensions, implemented over our existing primitives:
A Skill is a directory containing
SKILL.mdplus optional supporting files (additional markdown docs, scripts, templates).The agent sees every registered skill’s NAME + DESCRIPTION at startup (~50 tokens per skill in the system prompt).
When the user’s request matches a skill’s description, the model calls a
load_skill(name)tool to read the full body — the recipe — into context.Bundled supporting files are read via the standard
read_tool/bash_toolthe agent already has; we don’t need a new filesystem abstraction for skills.
Multi-source layering with last-source-wins override:
agent = Agent(
"...",
skills=[
"~/.jeeves/skills/system/", # base
"~/.jeeves/skills/user/", # user override
("./.jeeves-skills/", "Project"), # project, labelled
],
)
Inline skills (no folder needed):
agent = Agent(
"...",
skills=[
Skill.from_text('''---
name: standup-format
description: Format a daily standup update.
---
# Standup
Always 3 sections: Yesterday, Today, Blockers.
'''),
],
)
Public surface:
Skill— one loadable skillSkillSource— a directory of skills with optional labelSkillRegistry— collection with override semanticsSkillMetadata— startup-loaded descriptorSkillError— raised on bad SKILL.md or unknown skill namemake_load_skill_tool()— internal: builds theload_skilltool the framework injects into agents that have skills configured
Submodules¶
Attributes¶
Anything an |
Exceptions¶
Raised on invalid skill construction or frontmatter. |
Classes¶
A loadable agent skill. |
|
Lightweight skill descriptor — what loads at startup. |
|
A keyed collection of |
|
A folder of skills + an optional label. |
Functions¶
|
Build the |
Package Contents¶
- exception jeevesagent.skills.SkillError[source]¶
Bases:
ValueErrorRaised on invalid skill construction or frontmatter.
Initialize self. See help(type(self)) for accurate signature.
- class jeevesagent.skills.Skill(path: str | pathlib.Path, *, source_label: str | None = None)[source]¶
A loadable agent skill.
- classmethod from_text(text: str, *, source_label: str | None = None) Skill[source]¶
Build an inline skill from a SKILL.md-formatted string.
No filesystem path; bundled scripts and
tools.pyaren’t accessible. Useful for one-off skill definitions in code.
- list_files() list[pathlib.Path][source]¶
Enumerate every file bundled with this skill.
- metadata¶
- path¶
- property pending_tools: list[jeevesagent.tools.registry.Tool]¶
The Tool instances this skill will register on load.
Both Mode B (Python @tool from
tools.py) and Mode C (subprocess wrappers from frontmattertools:manifest) contribute to this list. Empty for pure markdown skills.
- class jeevesagent.skills.SkillMetadata[source]¶
Lightweight skill descriptor — what loads at startup.
The body is NOT in here; it’s read on demand via
Skill.load_body(). Keep this small — it lives in the system prompt for the entire agent’s lifetime.
- class jeevesagent.skills.SkillRegistry(items: collections.abc.Iterable[SkillSpec] | None = None)[source]¶
A keyed collection of
Skillinstances.- add(skill: jeevesagent.skills.skill.Skill) None[source]¶
Append (or override) a single skill after construction.
- catalog_section() str[source]¶
The markdown bullet list that gets appended to the agent’s system prompt.
Empty registry → empty string (so the constructor can unconditionally call this without polluting the system prompt with a blank “Available skills” header).
- get(name: str) jeevesagent.skills.skill.Skill | None[source]¶
- load(name: str) str[source]¶
Return the full body of a skill (the load_skill tool’s result). Raises
SkillErrorfor unknown names so the model gets a clear error in the tool result.Does NOT register pending Tools. For the full load-and- register flow, see
load_with_tools().
- load_with_tools(name: str) tuple[str, list[jeevesagent.tools.registry.Tool]][source]¶
Return
(body, newly_pending_tools)— the body of the skill plus the Tool instances the framework should register with the agent’s tool host on this load.Idempotent: subsequent calls for the same skill return the body and an empty tool list, since registration only needs to happen once.
- metadata_map() collections.abc.Mapping[str, jeevesagent.skills.skill.SkillMetadata][source]¶
All currently-registered skills’ metadata, keyed by name. Cheap to compute — used to build the catalog section.
- remove(name: str) jeevesagent.skills.skill.Skill | None[source]¶
Drop a skill by name. Returns the removed instance or
Noneif no such skill was registered.
- class jeevesagent.skills.SkillSource[source]¶
A folder of skills + an optional label.
- classmethod coerce(item: SkillSource | str | pathlib.Path | tuple[str | pathlib.Path, str]) SkillSource[source]¶
Normalize one user-supplied source spec.
Accepts: *
SkillSource(...)— used as-is *str/Path— bare path, no label *(path, label)— path with explicit label
- discover() list[jeevesagent.skills.skill.Skill][source]¶
Find every SKILL.md under this source directory.
Recurses one level (most common layout:
skills/<name>/SKILL.md) but also handles deeper nesting. Each SKILL.md becomes oneSkillinstance with this source’s label attached.
- path: pathlib.Path¶
- jeevesagent.skills.make_load_skill_tool(registry: jeevesagent.skills.registry.SkillRegistry, *, host: jeevesagent.core.protocols.ToolHost | None = None, tool_name: str = 'load_skill') jeevesagent.tools.registry.Tool[source]¶
Build the
load_skilltool for a given registry.When
hostis provided, the tool will register a skill’s pending Tools (from Mode B / Mode C) with the host on first load — making them callable on subsequent turns. Without a host,load_skillonly returns the body (skill brings no tools, or the framework integration handles registration elsewhere).
- jeevesagent.skills.SkillSpec¶
Anything an
Agent’sskills=argument accepts.