ADR-214 historical consequences
This appendix preserves the decision and its amendments. For present use, follow ADR-214: Approved skill versions instruct, load on demand and run processes and its current guide links.
Considered alternatives
Keep the untrusted frame for every skill and add a separate "tour" record. A new record type would hold the steps and be composed as instructions. Rejected: it creates a second kind of reusable prose next to skills, with its own source, review and audit, and it still needs the approval, loading and pinning of this decision for that record.
A trust flag without version binding. Mark a skill or a source as trusted once. Rejected: the next sync or the next backend edit would turn new text into instructions without anyone reading it. ADR-035 already disables an enabled skill whose body changed, for the same reason; an instruction is a stronger privilege than being enabled.
A checksum over the body alone. Today's value. Rejected: the frontmatter carries the tool allow-list, the section heading and the catalogue text, and an upstream change to it would keep a skill approved and enabled.
A versioned value in the existing checksum column. Rejected: the column is
varchar, and the manifest fingerprint and the legacy check still need the
body-only hash. A separate column keeps both meanings.
A revision table with every version. Rejected in favour of the approval
snapshot: only approved versions are ever composed as instructions or pinned,
and the snapshot holds exactly those. Backend edits are in sys_.
Unapproved synced versions are not kept, as today.
Checking the provenance threshold once, at approval. Simpler on paper. Rejected: a source downgraded after approval would keep instructing, and the check at compose and resume is one comparison per source.
Limiting revocation to new runs. Rejected; see item 6.
Pins carried in the request. The continuation request listing the pins
it holds, as the second version of this record had it. Rejected: an @api
caller could hand in any approved version, unattached, disabled, a process
without its invocation, or an older digest. nr_llm derives the pins from the
predecessor run instead.
Releasing a process run in the Agent Runs inbox. The earlier versions of this record let an inbox release reach the chat through a hand-back, and every review round since found a new defect in that path: the hand-back missed new messages, a cancel raced with the release, several approvals in one run were told apart wrongly, and open points under four-eyes never closed. Rejected: process runs are decided only on the chat card, and four-eyes tours are left to a later decision.
Progress and highlight only in an earlier turn. Keeping ADR-084's suspend-before-any-call rule and asking the process skill to report progress in a turn of its own. Rejected: it depends on the model following prose, and the decision moves process state into tools precisely to avoid that.
Loads that last one turn. Defining a load as valid for the run that made it, so the model loads again on every chat turn. Rejected: the model would re-load at whatever digest is current, so a tour could change version mid-conversation, and every turn would pay the load again.
Admitting a section only with every current turn kept. The first version
of this record. Rejected: every chat turn is a new run carrying the whole
history, so a long tour would fail permanently once its history passed the
headroom, although fit could still send it.
A denial reason per call. Letting one card carry a reason for each of several write calls. Rejected for process runs: an approval decides the whole turn (ADR-132), and one proposal per card is also what the editor reads. One write per turn keeps the existing turn semantics.
Let the model load any skill, trusted or not. Simpler, and the usual shape of skill systems. Rejected: the model reads page content, and a page could ask it to load a skill the editor never chose. For an untrusted skill that is fenced text and mostly cost; for a process it would start a flow by content injection.
Deferring model loading, the catalogue and load modes. Suggested to keep the first version small. Rejected by the product requirement: a skill must be reachable both by slash command and by the model matching its description.
Reply buttons as an input pause, followed by the write approval. Rejected: two pauses for one decision, and the variant that collects the answer in the approval pause is what ADR-134 bans. Approve-means-apply with an enumerated denial reason is one pause.
Admin-only TCA for snippets, or a mark on the record. Rejected; see item 8.
A workflow engine. Steps, transitions and state as data, with the model filling in the text. Rejected: it is a new runtime next to the agent loop, and every process would need a schema change rather than a text change, which is what the product owner asked to avoid. The run's existing suspensions (ADR-105, ADR-134) cover the interaction points.
One extension per process. Rejected by the product owner: every process would need a release and a deployment, and editors could not adjust one.
Processes as prompt snippets. Snippets are always on, unversioned and unapproved. Rejected for processes; kept for shared context (item 8).
Consequences
● Editors and administrators write a process as a skill in the backend, see
its history in sys_ and the diff against the last approved
version, and an approved version guides the chat without a release.
● The instruction privilege is bound to a digest over everything the model reads of a version and to the source that vouches for it. A changed body or frontmatter, from a sync or an edit, or a move to another source, loses it until someone with the approval permission approves again, and every approval and revocation is in the append-only audit.
● A conversation cannot silently continue with an instruction that was revoked, detached or replaced: every instruction section is pinned, derived by nr_llm from the predecessor run, and checked at start, pickup, resume and continuation. No caller can hand a pin in.
● A loaded skill cannot widen the tool allow-list, a backend author cannot widen it without an approval, and a resumed run cannot gain tools through the skill allow-list.
● Instruction sections are no longer cut from the tail and are admitted
against the smallest send fit can reach, so a section that does not fit
is refused visibly and a long tour does not strand on the budget. A tour
whose last run was purged by retention cannot be continued; the editor is
told to start a new conversation.
● Marked snippets, such as an editorial profile, reach the chat on configurations that opt in, and only in the text an administrator marked.
◐ The governance profiles gain an expectation for the new threshold. Proposed:
verified for local_, controlled_ and development,
first_ for enterprise_. skills. keeps its
default and its profile values.
◐ Upgrade note. What changes on an existing installation, and what does not:
- No approval exists after the upgrade, so every skill keeps the fenced frame.
Existing attachments migrate to
always, so no catalogue and no load tool appear on existing configurations. - The snippet path changes nothing until an administrator marks a snippet and opts a configuration in.
- Legacy rows keep verifying against
body_until the sync or the upgrade wizard writeschecksum version_. The first sync compares the new-form digest of the stored fields with the incoming one, so an unchanged skill is not disabled and a frontmatter change is caught. The wizard disables and audits a synced row whose storeddigest name,descriptionorallowed_no longer match itstools raw_.frontmatter - After the migration, an upstream change to a skill's frontmatter alone disables an enabled skill, which today it does not. Expect more re-reviews for sources that change their frontmatter.
- Forced skills'
allowed-now count for the run they are forced onto; today they count for nothing. The change goes both ways: when the configuration's skills declare nothing, a declaring forced skill narrows the run from every tool to its list; when they declare a list, the forced skill's tools are added to it. Forcing is an administrator's act in the playground, so the widening follows the rule that attachment grants tools.tools - A backend edit of a synced skill's
nameordescriptionnow fails the integrity check, like a body edit; FormEngine shows those fields read-only for synced sources. - Eight fields gain
exclude => true(item 3). A non-admin group that was grantedtables_on the skill tables loses write access to them until an administrator grants the fields; the extension ships those tables in an admin-only module (ADR-035 item 7), so no shipped surface changes.modify - A process run that requests two approval-bound calls in one turn gets an error for the second; its reads execute before the card appears, and any other call gets an error and does not run. Outside process runs nothing changes.
- In a process tour, a new chat message while a card or an input pause waits withdraws it: the waiting run is cancelled and the proposal shown as discarded, with no open point. Only "Überspringen" on the card records an open point. Runs of ordinary chats, without a process pin, are not cancelled and stay releasable in the inbox, as today.
- Process runs appear in the Agent Runs inbox read-only and cannot be decided there, by administrators neither.
- A process skill cannot be started on a configuration with
require_set.second_ approver - A backend skill that was never approved contributes a declared empty tool list. Attached to a configuration whose other skills declare nothing, it turns off every tool except the load tool until a version is approved. That is the price of never letting unreviewed text grant or lift a restriction.
✕ An approved skill is an instruction with the acting user's reach. It can steer which tools the model calls and with what arguments, within the run's allow-list and the user's TYPO3 permissions. The controls that bound it are the approval of the digest, the allow-list fixed at run start and the global tool state, and the write approval of ADR-134, which no skill can switch off. Approving a version is therefore a privileged act and gets its own permission.
✕ Content can still ask the model to load a skill. The catalogue lists only approved instruction skills that are not processes, and the load tool re-checks each at load time, so the worst outcome is approved text in the wrong place, not foreign text as instructions, and no change to the tool allow-list. Message role remains defence in depth, not a trust boundary (ADR-036): an untrusted, fenced skill can still influence output, as today.
✕ Manifest fingerprints cover identifier/body pairs only. They are not upstream signatures. Frontmatter is covered by the version digest and approval; the expected manifest digest still needs a trusted delivery channel.
✕ The work spans nr_llm (digest column and migration, compose path, approval,
load tool, run-start allow-list, pins and continuation, budget charge,
snippet path, denial reason, one-approval rule, guarded cancel, the
process-run decider and four-eyes guards, pending, the write
completeness on every write tool and the loop-level hook-failure flag on the
write step, progress, highlight and choice builtins,
catalogue API, actor-scoped access check) and nr_mcp_agent (slash
commands, the approval card's three answers, the input pause, naming the
predecessor run, the withdraw order in queue, progress, highlight,
open-point table and listing tool). The process use case works only when
both ship.
Open questions
- The approval permission. ADR-117 withdrew nr_llm's own capability checkboxes, and ADR-169 routes record management through TYPO3's permission model. Which mechanism carries "may approve a skill version" is open; until it is decided, administrators only.
- Who may author backend skills. ADR-035 item 7 keeps skills in an
admin-only module, and ADR-169 keeps
tx_out of non-admin management because the sync writes it. Backend-authored skills are written by people, so that has to be revisited for the new source. The fields that must not travel withnrllm_ skill tables_— on the skill and on its source — are the eight that item 3 excludes; whether more belong there is part of that revisit.modify - Names.
skills.,instruction Trust Level version_, thedigest processfrontmatter key, the load modes, the snippet mark, the configuration opt-in,Approval,Denial Reason cancel,If Waiting () pending,Target () WriteandCompleteness hookare working names.Failed After Write - Catalogue size. Whether the catalogue needs its own byte cap, or the admission rule of item 7 covers it.
- Headroom. Whether 10 % of the budget is the right reserve, measured on the first processes that run.
- Flipping existing attachments to on_demand. Whether and when existing
alwaysattachments move toon_, which changes what an existing configuration sends.demand - Four-eyes tours. Whether and how a process can run on a configuration that requires a second approver: the second person would have to decide on a surface other than the chat card, which this decision forbids for process runs.
- Process completion without a report. A tour the model abandons without
a completion report keeps its process pin until the conversation ends or
the configuration changes. This original question was resolved by ADR-228:
Agentexplicitly ends the process pin.Runtime Interface:: end Process ()