Attaching and loading skills
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 anallowed-declaration.tools
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 purely to avoid dangling instructions, not as a
security control.
See ADR-035 for the full design and security rationale.
Whether a skill works on a page
The frontmatter key page tells a consumer of the skill, such as the
backend chat of nr_mcp_agent, whether a conversation with the skill needs a
page:
page: required- The skill works on one page and needs it. The chat asks for a page and keeps it.
page: optional- The skill may work on a page: the page the editor shows is passed along when there is one.
page: none- The skill does not work on a page. The chat neither asks for one nor passes one along.
---
name: Write a news article
description: Drafts a news article from a few key points.
page: none
---
A skill without the key, or with any other value, declares nothing and keeps
the behaviour it had before the key existed: a process skill behaves as
required, every other skill as optional. The value is read without
regard to case.
The key is not part of the skill's version (ADR-229). It decides no trust and no tool, so a change of it alone neither disables an enabled skill nor invalidates its approvals, and it is not shown in the approval form's diff. A synced skill shows it read-only as Works on a page; a skill written in the backend sets it there.
Attaching skills and injecting them into prompts
Enabled, non-orphaned skills can be attached to a Task and/or an
LLM configuration via the 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 unapproved attached skills into a
delimited block and prepends it to the user prompt. Approved instruction
versions use the system-message channel described below; the stored
configuration system_ is never modified.
A configuration has two skill fields:
- Skills loaded on demand. An agent run lists the attached skills
whose current version is approved as an instruction (and which are not
process skills) by uid, name and description in the description of the
builtin tool
load_. When the task matches, the model loads one: its section joins the run's system message before the next call, the tool result confirms the load without the body, and loading the same version again appends nothing. The load re-checks the attachment, the record and the approval at that moment, and refuses a section that would leave less than 10 % of the model's context budget. A skill attached here that is not approved is neither listed nor composed. Tasks, translation and the other one-shot paths never load on demand. A process skill is attached here and is started by invocation only, for example from the chat's slash-command menu; the model never loads it.skill - Skills loaded always. Composed into every run, as described below. Every attachment that existed before the load modes is one of these. Process skills cannot be attached here.
Both fields grant the skills' declared tools (allowed-) from the
start of a run; loading a skill grants nothing.
Note
An attachment loaded always is eager and complete. The whole skill
body — the entire SKILL. prose after the front-matter, not just
the name/description — is written into the prompt before the model
runs. Nothing loads a skill's references/ / scripts/ / assets/
(those lines are stripped from partial skills, and the files are never
executed). Such a skill therefore always costs its full body in tokens on
every run (subject to the budget below).
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 untrusted user-message block is bounded by a byte budget; when it is exceeded, task-additive skills are dropped before configuration-baseline skills and each drop is logged. Approved instruction sections are kept in full and count toward the context-window estimate. A request that does not fit even then is still sent, with a logged warning: the chat path first drops older turns, the completion path sends the prompt unchanged. No instruction section is dropped to make it fit.
- Integrity. Each skill's version digest — over the body and the frontmatter fields the model reads — is recomputed from the stored fields at injection time; a mismatch (tampering or a stale row) drops that skill — it is never injected. A row synced before the digest existed is checked against its body checksum until the upgrade wizard or a sync writes its digest. Name, description and body are therefore read-only in FormEngine.
- Process skills. A skill whose frontmatter sets
process: trueis never composed from an attachment; it is skipped with a warning. A run that invokes it composes its approved version as a system-message section of its own, Active process, ahead of the approved skills. The process governs the order of steps and the structure of answers; the approved skills keep applying to wording, terminology and safety (ADR-214). - 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 ADR-036 for the injection design.