Skip to content

context.skills() – Centralized Registry for Structured Prompt Engineering

Skills are AetherGraph’s lightweight unit of instruction + metadata. They are used to:

  • Provide consistent prompts / rubrics for planning and chat.
  • Package domain knowledge (including examples) in a reusable, versioned format.
  • Power discovery and routing via tags, domains, and modes.

A skill can be created:

  • In code (a Skill object), or
  • From Markdown (.md) files (or folders of .md files) with a simple front-matter + section convention.

1. Skill Class

A Skill is a small container for:

  • id, title, description
  • tags, domain, modes (used for filtering and routing)
  • config (arbitrary metadata)
  • sections (named chunks of markdown used for prompts, examples, or notes)

Defining skills via Markdown

You can define a skill in a Markdown file. This is the recommended way to maintain prompt packs in a readable, reviewable format.

How sections work (skills().section)

context.skills().section(skill_id, section_key, default=...) returns the raw Markdown content stored under the H2 heading whose text matches section_key.

  • If your file has ## chat.system, then section_key="chat.system" returns everything under that heading.
  • Content before the first ## ... heading is stored under the special key "body".

(See the section format rules below.)

File format

Notes: - The file must start with a YAML front matter block delimited by --- lines. Example:

---
id: demo.prompts
title: Demo prompt pack
description: Shared prompts and examples for common interactions.
tags: [demo, prompts]
domain: general
modes: [planning, chat]
version: "0.1.0"
---
At minimum, id and title are required. Additional keys are stored in Skill.config.

  • The body of the file is divided into sections using H2 headings (##). Example:

    ## chat.system
    System-level prompts for chat interactions.
    
    ## planning.header
    Header content for planning workflows.
    
    The heading text is used as the section key (e.g., "chat.system").

  • Content before the first ## heading is stored in a special section "body".

  • Deeper headings (e.g., ###) are treated as content within the current section.

  • Empty sections are ignored, and section bodies are stored as raw markdown strings.

Minimal end-to-end example

---
id: demo.hello
title: Hello skill
description: Minimal skill example.
tags: [demo]
domain: general
modes: [chat]
---

## chat.system
You are a helpful assistant.

## chat.example
User: Say hello in one sentence.
Assistant: Hello! Nice to meet you.

Multiple .md files in a folder

You can organize skills as a folder of markdown files, typically one skill per file.

Common patterns:

  • Many independent skills (each file has its own id):

    skills/
      demo.hello.md
      demo.planning.md
      writing.email.md
    

  • Topic packs (group related skills in a directory, load all at once):

    skills/writing/
      email.md
      summarize.md
      tone.md
    

Loading behavior: - Use SkillRegistry.load_path(...) (or the runtime convenience wrapper) to scan a directory. - Recommended convention: each file contains its own YAML front matter with a unique id.

Skill

Skill represents a reusable prompt "skill" that can be loaded from markdown or defined inline. It includes metadata, configuration, and sections of content that can be used to generate prompts.

Attributes:

Name Type Description
id str

Unique identifier for the skill.

title str

Title of the skill.

description str

Description of the skill. Defaults to an empty string.

tags list[str]

Tags associated with the skill. Defaults to an empty list.

domain str | None

Domain or category of the skill. Defaults to None.

modes list[str]

Modes in which the skill can be used (e.g., 'chat', 'planning', 'coding'). Defaults to an empty list.

version str | None

Version of the skill. Defaults to None.

config dict[str, Any]

Additional configuration for the skill. Defaults to an empty dictionary.

sections dict[str, str]

Parsed sections of the skill, keyed by dot-paths.

raw_markdown str | None

Raw markdown content of the skill. Defaults to None.

path Path | None

File path of the skill, if loaded from a file. Defaults to None.

Methods:

Name Description
section

str, default: str = "") -> str: Retrieve a specific section by its dot-path key. Returns the default value if the section is missing.

has_section

str) -> bool: Check if a specific section exists in the skill.

compile_prompt

str, separator: str, fallback_keys: Iterable[str] | None = None) -> str: Compile a prompt by concatenating specified sections. If no sections are specified, compiles the entire skill.

from_dict

Mapping[str, Any], sections: Mapping[str, str], *, raw_markdown: str | None = None, path: Path | None = None) -> Skill: Class method to create a Skill instance from metadata and sections. Useful for programmatically defining skills.

Skill represents a reusable prompt "skill" that can be loaded from markdown or defined inline. It includes metadata, configuration, and sections of content that can be used to generate prompts.

Attributes:

Name Type Description
id str

Unique identifier for the skill.

title str

Title of the skill.

description str

Description of the skill. Defaults to an empty string.

tags list[str]

Tags associated with the skill. Defaults to an empty list.

domain str | None

Domain or category of the skill. Defaults to None.

modes list[str]

Modes in which the skill can be used (e.g., 'chat', 'planning', 'coding'). Defaults to an empty list.

version str | None

Version of the skill. Defaults to None.

config dict[str, Any]

Additional configuration for the skill. Defaults to an empty dictionary.

sections dict[str, str]

Parsed sections of the skill, keyed by dot-paths.

raw_markdown str | None

Raw markdown content of the skill. Defaults to None.

path Path | None

File path of the skill, if loaded from a file. Defaults to None.

Methods:

Name Description
section

str, default: str = "") -> str: Retrieve a specific section by its dot-path key. Returns the default value if the section is missing.

has_section

str) -> bool: Check if a specific section exists in the skill.

compile_prompt

str, separator: str, fallback_keys: Iterable[str] | None = None) -> str: Compile a prompt by concatenating specified sections. If no sections are specified, compiles the entire skill.

from_dict

Mapping[str, Any], sections: Mapping[str, str], *, raw_markdown: str | None = None, path: Path | None = None) -> Skill: Class method to create a Skill instance from metadata and sections. Useful for programmatically defining skills.


2. SkillRegistry

Accessed from context.skills().

SkillRegistry is the primary API for:

  • Registering skills (objects, inline definitions, files, or whole directories)
  • Querying (get, require, all, ids)
  • Reading sections (section) and compiling prompts (compile_prompt)
  • Discovering skills by tag/domain/mode (find) and emitting summaries (describe)
register(skill, *, overwrite)

Register a Skill object.

This method allows you to add a Skill object to the registry. If a skill with the same ID already exists and overwrite is set to False, a ValueError will be raised.

Examples:

Registering a skill object:

skill = Skill(
    id="example.skill",
    title="Example Skill",
    description="An example skill for demonstration purposes.",
    tags=["example", "demo"],
    domain="general",
    modes=["chat"],
)
registry.register(skill)

Overwriting an existing skill:

registry.register(skill, overwrite=True)

Parameters:

Name Type Description Default
skill Skill

The Skill object to register. (Required)

required
overwrite bool

Whether to overwrite an existing skill with the same ID. (Optional)

False
register_inline(*, id, title, description, tags, ...)

Convenience for defining a Skill entirely in Python.

This method allows you to define and register a Skill inline, without needing to create a separate markdown file. It is useful for quick prototyping or defining simple skills directly in code.

Examples:

Registering a basic coding helper skill:

registry.register_inline(
    id="coding.generic",
    title="Generic coding helper",
    description="Helps with Python code generation and review.",
    tags=["coding"],
    modes=["chat", "coding"],
    sections={
        "chat.system": "You are a helpful coding assistant...",
        "coding.system": "You write code as JSON ...",
    },
)

Parameters:

Name Type Description Default
id str

The unique identifier for the skill. (Required)

required
title str

A short, descriptive title for the skill. (Required)

required
description str

A longer description of the skill's purpose. (Optional)

''
tags list[str] | None

A list of tags for categorization. (Optional)

None
domain str | None

The domain or category the skill belongs to. (Optional)

None
modes list[str] | None

A list of modes the skill supports (e.g., "chat", "coding"). (Optional)

None
version str | None

The version of the skill. (Optional)

None
config dict[str, Any] | None

A dictionary of additional configuration options. (Optional)

None
sections dict[str, str] | None

A dictionary mapping section keys to their content. (Optional)

None
overwrite bool

Whether to overwrite an existing skill with the same ID. (Optional)

False

Returns:

Name Type Description
Skill Skill

The registered Skill object.

load_file(path, *, overwrite)

Load a single .md skill file and register it.

This method reads the content of a markdown file, parses it into a Skill object, and registers it in the skill registry.

Examples:

Loading a skill from a file:

skill = registry.load_file("path/to/skill.md")

Parameters:

Name Type Description Default
path str | Path

The file path to the markdown skill file. (Required)

required
overwrite bool

Whether to overwrite an existing skill with the same ID. (Optional)

False

Returns:

Name Type Description
Skill Skill

The registered Skill object.

load_path(root, *, pattern, recursive, overwrite)

Load all skill markdown files under a directory.

This method scans the specified directory for markdown files matching the given pattern, parses them into Skill objects, and registers them in the skill registry.

Examples:

Loading all skills from a directory recursively:

skills = registry.load_path("path/to/skills", pattern="*.md", recursive=True)

Loading skills from a directory without recursion:

skills = registry.load_path("path/to/skills", recursive=False)

Parameters:

Name Type Description Default
root str | Path

The root directory to scan for markdown files. (Required)

required
pattern str

The glob pattern to match files (e.g., "*.md"). (Optional)

'*.md'
recursive bool

Whether to scan directories recursively. (Optional)

True
overwrite bool

Whether to overwrite existing skills with the same ID. (Optional)

False

Returns:

Type Description
list[Skill]

list[Skill]: A list of all successfully loaded and registered Skill objects.

get(skill_id)

Get a registered Skill by id.

This method retrieves a Skill object from the registry using its unique identifier. If the skill is not found, it returns None.

Examples:

Retrieving a skill by its ID:

skill = registry.get("coding.generic")
if skill:
print(skill.title)

Parameters:

Name Type Description Default
skill_id str

The unique identifier of the skill to retrieve. (Required)

required

Returns:

Type Description
Skill | None

Skill | None: The Skill object if found, otherwise None.

require(skill_id)

Retrieve a registered Skill by its unique identifier.

This method ensures that the requested Skill exists in the registry. If the Skill is not found, it raises a KeyError.

Examples:

Retrieving a skill by its ID:

skill = registry.require("coding.generic")
print(skill.title)

Parameters:

Name Type Description Default
skill_id str

The unique identifier of the skill to retrieve. (Required)

required

Returns:

Name Type Description
Skill Skill

The Skill object corresponding to the given ID.

Raises:

Type Description
KeyError

If the skill with the specified ID is not found.

all()

Return all registered Skills.

This method retrieves all Skill objects currently registered in the skill registry and returns them as a list.

Examples:

Retrieving all registered skills:

skills = registry.all()
for skill in skills:
print(skill.id, skill.title)

Returns:

Type Description
list[Skill]

list[Skill]: A list of all registered Skill objects.

ids(skill)

Return all registered Skill ids.

This method retrieves the unique identifiers of all Skill objects currently registered in the skill registry and returns them as a sorted list.

Examples:

Retrieving all skill IDs:

skill_ids = registry.ids()
print(skill_ids)

Returns:

Type Description
list[str]

list[str]: A sorted list of all registered skill IDs.

section(skill_id, section_key, default)

Return a section for a given skill, or default.

This method retrieves the content of a specific section within a skill by its unique identifier and section key. If the skill or section is not found, it returns the provided default value.

Examples:

Retrieving a section from a skill:

section_content = registry.section("coding.generic", "chat.system")
print(section_content)

Providing a default value if the section is missing:

section_content = registry.section("nonexistent.skill", "missing.section", default="Default content")

Parameters:

Name Type Description Default
skill_id str

The unique identifier of the skill. (Required)

required
section_key str

The key of the section to retrieve. (Required)

required
default str

The value to return if the skill or section is not found. (Optional)

''

Returns:

Name Type Description
str str

The content of the section if found, otherwise the default value.

compile_prompt(skill_id, *section_keys, separator, fallback_keys)

Shortcut for Skill.compile_prompt(...) by id.

This method compiles a prompt by combining multiple sections of a skill identified by its unique ID. It allows you to specify the sections to include, the separator to use between sections, and fallback keys for missing sections.

Examples:

Compiling a prompt with specific sections:

prompt = registry.compile_prompt(
    "coding.generic",
    "chat.system",
    "chat.user",
)

Using fallback keys for missing sections:

prompt = registry.compile_prompt(
    "coding.generic",
    "chat.system",
    "chat.user",
    fallback_keys=["default.system", "default.user"]
)

Parameters:

Name Type Description Default
skill_id str

The unique identifier of the skill. (Required)

required
*section_keys str

The keys of the sections to include in the prompt. (Required)

()
separator str

The string to use as a separator between sections. (Optional)

'\n\n'
fallback_keys list[str] | None

A list of fallback section keys to use if a section

None

Returns:

Name Type Description
str

The compiled prompt as a single string.

find(tag, domain, mode, predicate)

Filter skills by tag, domain, mode, and/or a custom predicate.

This method allows you to filter registered skills based on specific criteria such as tags, domain, mode, or a custom predicate function.

Examples:

Finding skills with a specific tag and mode:

skills = registry.find(tag="surrogate", mode="planning")

Using a custom predicate to filter skills:

skills = registry.find(predicate=lambda s: "example" in s.title)

Parameters:

Name Type Description Default
tag str | None

A string representing the tag to filter by. (Optional)

None
domain str | None

The domain or category to filter by. (Optional)

None
mode str | None

The mode (e.g., "chat", "coding") to filter by. (Optional)

None
predicate callable | None

A callable that takes a Skill object and returns a

None

Returns:

Type Description
list[Skill]

list[Skill]: A list of Skill objects that match the specified criteria.

describe()

Return a compact description of all registered skills.

This method provides a summary of all skills currently registered in the registry, including their metadata such as ID, title, description, tags, domain, modes, version, and sections.

Examples:

Retrieving skill descriptions for debugging or UI purposes:

descriptions = registry.describe()
for skill in descriptions:
print(skill["id"], skill["title"])

Returns:

Type Description
list[dict[str, Any]]

list[dict[str, Any]]: A list of dictionaries, each containing the

list[dict[str, Any]]

metadata of a registered skill.


3. Global Registration

Access through aethergraph.runtime.

When starting a server (or wiring up an app bootstrap), prefer the runtime convenience methods for global registration. They’re ergonomic and keep startup scripts concise.

register_skill(skill, *, overwrite)

Register an existing Skill object into the global registry.

This method adds a Skill instance to the global SkillRegistry, making it available for use throughout the application. The overwrite flag determines whether an existing skill with the same ID will be replaced.

Examples:

Registering a skill object:

skill = Skill(id="example.skill", title="Example Skill")
register_skill(skill)

Overwriting an existing skill:

skill = Skill(id="example.skill", title="Updated Skill")
register_skill(skill, overwrite=True)

Parameters:

Name Type Description Default
skill Skill

The Skill object to register.

required
overwrite bool

Whether to overwrite an existing skill with the same ID. Default is False.

False

Returns:

Name Type Description
Skill Skill

The registered Skill instance.

register_skill_inline(id, title, description, tags, ...)

Define and register a Skill entirely in Python.

This method allows you to define a Skill inline with all its metadata and sections, and directly register it into the global Skill registry.

Examples:

Registering a skill with basic metadata and sections:

register_skill_inline(
    id="surrogate.workflow",
    title="Surrogate workflow planning",
    description="Prompts and patterns for surrogate planning.",
    tags=["surrogate", "planning"],
    modes=["planning"],
    sections={
        "planning.header": "...",
        "planning.binding_hints": "...",
        "chat.system": "...",
    },
)

Parameters:

Name Type Description Default
id str

The unique identifier for the Skill. (Required)

required
title str

A human-readable title for the Skill. (Required)

required
description str

A short description of the Skill's purpose. (Optional)

''
tags list[str]

A list of tags for categorization. (Optional)

None
domain str

The domain or namespace for the Skill. (Optional)

None
modes list[str]

The operational modes supported by the Skill. (Optional)

None
version str

The version string for the Skill. (Optional)

None
config dict[str, Any]

Additional configuration data. (Optional)

None
sections dict[str, str]

A dictionary mapping section names to their content. (Optional)

None
overwrite bool

Whether to overwrite an existing Skill with the same ID. (Optional)

False

Returns:

Name Type Description
Skill Skill

The registered Skill instance.

register_skill_file(path, *, overwrite)

Load a single markdown skill file and register it.

This function processes a markdown file containing skill definitions and registers it into the global skill registry. The file must adhere to the expected format for parsing skill metadata and sections.

Examples:

Registering a skill from a markdown file:

skill = register_skill_file("skills/surrogate-workflow.md")

Parameters:

Name Type Description Default
path str | Path

The path to the markdown file to load.

required
overwrite bool

Whether to overwrite an existing skill with the same ID. (Optional, default: False)

False

Returns:

Name Type Description
Skill Skill

The registered Skill instance.

Notes

To start the server and load all desired packages: 1. Open a terminal and navigate to the project directory. 2. Run the server using the appropriate command (e.g., python -m aethergraph.server). 3. Ensure all required dependencies are installed via pip install -r requirements.txt.

register_skills_from_path(root, *, pattern, recursive, overwrite)

Load and register all skill markdown files under a directory.

This method scans the specified directory for markdown files matching the given pattern, parses their content into Skill objects, and registers them into the global skill registry. The directory can have a flat or nested structure.

Examples:

Register all skills in a flat directory:

register_skills_from_path("skills/")

Register skills in a nested directory structure:

register_skills_from_path("skills/", recursive=True)

Use a custom file pattern to filter files:

register_skills_from_path("skills/", pattern="*.skill.md")

Parameters:

Name Type Description Default
root str | Path

The root directory to scan for skill files.

required
pattern str

A glob pattern to match skill files. Default is "*.md".

'*.md'
recursive bool

Whether to scan subdirectories recursively. Default is True.

True
overwrite bool

Whether to overwrite existing skills with the same ID. Default is False.

False

Returns:

Type Description
list[Skill]

list[Skill]: A list of all registered Skill objects.

Notes

To start the server and load all desired packages: 1. Open a terminal and navigate to the project directory. 2. Run the server using the appropriate command (e.g., python -m aethergraph.server). 3. Ensure all required dependencies are installed via pip install -r requirements.txt.