.. include:: /Includes.rst.txt .. _administration-skills: =============== Managing skills =============== *Skills* are GitHub-hosted ``SKILL.md`` files — a YAML front-matter block with a ``name`` and ``description`` plus a markdown body — that nr-llm can ingest, review, and (from Plan 1b) inject into prompts. You add a **skill source** that points at GitHub, sync it, and then enable the individual skills you want. Skill management is **admin-only**. It lives in :guilabel:`Admin Tools > LLM > Skills` and is not delegated to other backend groups: a skill body becomes prompt context, so the two skill tables are treated as a privilege-escalation surface. .. note:: Ingest — adding sources, syncing and reviewing — is described by :ref:`ADR-035 `. Attaching enabled skills to tasks and configurations and injecting them into text-generation prompts is described by :ref:`ADR-036 ` and the :ref:`Attaching skills ` section below. .. _administration-skills-source-types: Source types ============ A source has one of three types: ``single_file`` One ``SKILL.md`` at a fixed path in a repository. A single, explicit admin act — its skill may default to enabled. ``repo`` A whole repository. Every ``SKILL.md`` under the repo root, ``skills//``, ``.claude/skills//`` or ``/skills//`` is discovered. Discovered skills arrive **disabled** for review. ``marketplace`` An Anthropic ``marketplace.json`` index that lists plugins pointing at further repositories. Each entry is expanded with the ``repo`` flow. All discovered skills arrive **disabled**. .. _administration-skills-add: Adding a source =============== 1. Navigate to :guilabel:`Admin Tools > LLM > Skills`. 2. Click :guilabel:`New Skill Source`. 3. Fill in the fields: :guilabel:`Title` Display name for the source list. :guilabel:`Type` ``single_file``, ``repo`` or ``marketplace`` (see above). :guilabel:`URL` The GitHub URL the type expects (the ``SKILL.md`` URL, the repository URL, or the ``marketplace.json`` URL). :guilabel:`Ref` A branch or tag (for example ``main`` or ``v1.2.0``). It is resolved **once** to an immutable commit SHA at sync time; all bodies are then fetched by that SHA, never by the moving branch. 4. Click :guilabel:`Save`. The ``pinned_sha``, ``sync_status``, ``sync_error`` and ``last_synced`` fields are managed by the sync run and shown read-only. .. _administration-skills-token: GitHub token and rate limits ============================ Unauthenticated GitHub API access is limited to **60 requests per hour**, which is quickly exhausted by a ``repo`` or ``marketplace`` sync. Add a personal access token (a read-only, public-repo token is enough) to raise the limit and to read private repositories. - The token is set through the :guilabel:`Set token` action on a source, **not** typed into a FormEngine field. It is stored as an nr-vault UUID (envelope-encrypted), mirroring provider API-key storage — never as plaintext in TCA, YAML or the database. - When a sync hits the rate limit (HTTP 403 with no remaining quota), the source is set to ``sync_status = error`` carrying the reset time; state is not partially corrupted. Add a token and re-sync. .. _administration-skills-allowlist: Host-allowlist prerequisite =========================== nr-llm enforces an **app-level GitHub allowlist** on every skill request: the scheme must be ``https`` and the host must be one of ``github.com``, ``raw.githubusercontent.com``, ``api.github.com`` or ``codeload.github.com``. This is separate from, and in addition to, the nr-vault SSRF guard. On hardened instances that restrict outbound HTTP through the global ``HTTP/allowed_hosts`` SSRF setting, those four GitHub hosts **must be on that list**, otherwise every sync fails closed. This is a deliberate prerequisite — nr-llm never silently bypasses the SSRF guard. .. _administration-skills-review: Syncing and the review flow =========================== 1. On a source, click :guilabel:`Sync`. The source moves through ``never_synced`` → ``syncing`` → ``ok`` / ``partial`` / ``error``. The ``syncing`` state also acts as a lock: a second concurrent sync on the same source is refused. 2. ``partial`` means the per-sync file-count or wall-time bound was reached (large marketplaces); the skills fetched so far are stored. 3. Discovered skills from ``repo`` and ``marketplace`` sources are created **disabled by default**. Review each one, then toggle it on with :guilabel:`Enable`. 4. **Re-sync never silently changes an enabled skill.** If a re-sync recomputes a different ``body_checksum`` for an enabled skill, nr-llm **auto-disables it** and surfaces a diff (:guilabel:`Review changes`) so you re-confirm before it is used again. Accepting the diff re-pins the SHA atomically. 5. A skill that disappeared upstream is marked **orphaned and disabled**, never silently dropped, so attachments (Plan 1b) do not vanish. Deleting a source cascade-deletes its skills. .. _administration-skills-support-status: The ``partial`` support badge ============================= Each skill carries a support badge: ``full`` The skill is plain front-matter and prose. ``partial`` The body or front-matter references scripts, ``references/``, ``assets/`` or an ``allowed-tools`` declaration. .. warning:: ``partial`` is **not** a "safer content" badge. It only signals that the referenced scripts and assets are **not executed** by nr-llm (which is true for every skill in this release). The prose itself is fully untrusted regardless of the badge. Asset references are stripped from injected prose in a later release purely to avoid dangling instructions, not as a security control. See :ref:`ADR-035 ` for the full design and security rationale. .. _administration-skills-attach: Attaching skills and injecting them into prompts ================================================ Enabled, non-orphaned skills can be attached to a **Task** and/or an **LLM configuration** via the :guilabel:`Skills` field on those records (only enabled skills are offered). At execution time, for text-generation operations only — completion, translation and task execution; **never** embeddings, vision or speech — nr-llm composes the attached skills into a delimited block and prepends it to the *user* prompt. The configuration ``system_prompt`` is never modified. Composition rules: - **Precedence.** Configuration skills are the baseline, task skills are additive; the set is the union deduped by source + identifier (the configuration wins on a duplicate). The configuration block renders first. - **Budget.** The block is bounded by a conservative character budget; when it is exceeded, task-additive skills are dropped before configuration-baseline skills and each drop is logged. - **Integrity.** Each skill's body checksum is re-verified at injection time; a mismatch (tampering or a stale row) drops that skill — it is never injected. - **Untrusted output.** Skill prose is third-party text; output produced under its influence is treated as untrusted and escaped/sanitized where it is stored or rendered. Message role is defense-in-depth, not a trust boundary. See :ref:`ADR-036 ` for the injection design.