jeevesagent.skills.registry
===========================

.. py:module:: jeevesagent.skills.registry

.. autoapi-nested-parse::

   SkillRegistry — manages a collection of available skills.

   Built once when an :class:`Agent` is constructed. Holds every
   :class:`Skill` discovered from the user's sources, applies
   last-source-wins override semantics by name, and provides the two
   hooks the framework needs to surface skills to the model:

   * :meth:`catalog_section` — the markdown bullet list injected into
     the system prompt at startup (the cheap "metadata" tier of
     progressive disclosure)
   * :meth:`load` — return a skill's full body when the model calls
     the ``load_skill`` tool

   Override semantics matches LangChain DeepAgents: when two sources
   ship a skill with the same ``name``, the LATER source wins. This
   lets users layer system → user → project skills and override at
   any level::

       skills=[
           "~/.jeeves/skills/system/",      # base
           "~/.jeeves/skills/user/",        # user override
           "./.jeeves-skills/",             # project override
       ]



Attributes
----------

.. autoapisummary::

   jeevesagent.skills.registry.SkillSpec


Classes
-------

.. autoapisummary::

   jeevesagent.skills.registry.SkillRegistry


Module Contents
---------------

.. py:class:: SkillRegistry(items: collections.abc.Iterable[SkillSpec] | None = None)

   A keyed collection of :class:`Skill` instances.


   .. py:method:: add(skill: jeevesagent.skills.skill.Skill) -> None

      Append (or override) a single skill after construction.



   .. py:method:: catalog_section() -> str

      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).



   .. py:method:: get(name: str) -> jeevesagent.skills.skill.Skill | None


   .. py:method:: is_loaded(name: str) -> bool

      Whether the skill's pending tools have been registered.



   .. py:method:: load(name: str) -> str

      Return the full body of a skill (the load_skill tool's
      result). Raises :class:`SkillError` for 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 :meth:`load_with_tools`.



   .. py:method:: load_with_tools(name: str) -> tuple[str, list[jeevesagent.tools.registry.Tool]]

      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.



   .. py:method:: metadata_map() -> collections.abc.Mapping[str, jeevesagent.skills.skill.SkillMetadata]

      All currently-registered skills' metadata, keyed by name.
      Cheap to compute — used to build the catalog section.



   .. py:method:: names() -> list[str]


   .. py:method:: remove(name: str) -> jeevesagent.skills.skill.Skill | None

      Drop a skill by name. Returns the removed instance or
      ``None`` if no such skill was registered.



.. py:data:: SkillSpec

   Anything an :class:`Agent`'s ``skills=`` argument accepts.

