← Documentation index Architecture › skills & backends

Metnos

skillbackend — two orthogonal axes
Architecture of the skill-versus-backend boundary
Audience: anyone who wants to know where a provider ends and a skill begins.

Reading time: 12 minutes.

Table of contents

  1. Two orthogonal axes
  2. The three skill tiers
  3. From one provider to many
  4. On/off lives on the backend
  5. Promotion: the mechanism
  6. Why MCP stays at the boundary
  7. Going deeper
  8. What this means for you, in practice

1. Two orthogonal axes

In Metnos «skill» and «backend» answer two different questions. The backend says HOW a verb_object runs against a service. The skill says WHETHER and WHICH capabilities are unlocked, trusted and shipped. Conflating them leads to splitting executors apart; keeping them separate is what lets you add a provider without touching the planner.

 Backend / providerSkill
AnswersHOW I run verb_object against a serviceWHETHER / WHICH capabilities are unlocked, trusted, shipped
Axisobject × providerexternal dependency (credential / backend / hardware)
Visibilityinvisible to the LLM, resolved from configuration by the backend resolveruser-facing (enable / disable, dormancy, sandbox, packaging)

The two axes touch only when a skill has a single provider: in that case github, geo, mail are in practice the user-facing name of that provider's backend. They diverge as soon as a skill has several backends (a calendar is served over local ICS, Google or CalDAV) or has no external provider at all (photos, the core). The map is many-to-many: one provider (Google Workspace) serves several skills — mail, calendar, drive, sheets, docs.

Anti-duplication rule. The external dependency (credential, service endpoint, hardware) is declared once, at the backend. The skill aggregates it — the union of its backends' requirements — and does not re-declare it. The skill's dormancy is derived from its backends, not hand-written.
execution axis — HOW (invisible to the LLM) skill axis — WHETHER PLANNER (local model) always sees only find_issues canonical EXECUTOR provider-agnostic (object issues) BACKEND RESOLVER picks the provider from configuration github backend gitlab backend SKILL = activation / dormancy github skill (PAT) turns the github backend on/off gitlab skill (token) turns the gitlab backend on/off independent dormancy per provider does not change the planner pool
Figure 1 — The two axes. On the left, execution (planner → canonical executor → resolver → backend): invisible to the LLM, resolved from configuration. On the right, skills: they turn backends on and off, but never change the planner's pool, which always sees find_issues.

2. The three skill tiers

«Skill» ended up meaning three different things: a classification of executors already in the repository, real packages in the repository, and imported third-party code. The tier field unifies them under a single model. It lives in skills_catalog.py (function skill_tier()) and in the SKILL.md front matter.

TierWhat it isTrustWhere it livesActivation
1 — coreplanner and engine, local files, dirs, processes, time, local scheduler, persons, credentials, signatures, proposals, the scratchpad helpers (filter / sort / group / compute / describe / extract)maximumrepository, signed, multilingualalways on
2 — first_partycapabilities shipped with Metnos at the same standard as the core, but dormant until the dependency is present: github, photos, mail, web, geo, calendar, generic data store (sqldatabase), frontier, Google Workspacemaximumrepository (versioned bundle + signed executors)automatic, dormant if not configured
3 — importedthird-party code, not audited nor vendored (from agentskills.io and the like)lowuser data, with tracked provenanceopt-in, sandbox + 7-layer net
What gets shipped publicly. The release carries only tier 1 and 2, inside the signed repository. Tier 3 is not shipped: the user installs it, and it is precisely there that the README's security thesis applies («do not trust the package»). Promotion from tier 3 to tier 2 takes four joint yeses: generally useful, compatible license, willingness to maintain it (undo, i18n, re-sign), and support for a capability already in the catalog.

3. From one provider to many

Tomorrow GitLab might arrive alongside GitHub. The question is: how do you add a second provider for the same issues? Two paths.

Option (a): split the executor — REJECTED

Generate find_issues_github and find_issues_gitlab and let the planner choose. This works where a frontier model sits at the center and disambiguates by reading prose. In Metnos the planner is a local model, which faced with two nearly identical names develops a provider bias: it always picks the same one, or gets it wrong. Splitting breaks routing.

Option (b): abstract — CHOSEN

Cost of a new provider: +1 backend file, +1 skill (if it introduces a new credential), 0 new executors. It is the path calendar and files have already taken.
A backend does not grant itself authority. The provider:access capability declares the skill binding and may be narrowed with when to the final client selector value. Only the effective binding governs network access, credentials, and the server pin together; neither the executor name nor the argument value is a source of permission.
An example already in the house: the sqldatabase skill. The abstract shape is not a promise for the future: the sqldatabase skill already embodies it. It offers three canonical executors — find_entries, write_entries, delete_entries — that read, write and delete records in named stores (find_entries(store="expenses", …)), while the query never knows where the data actually lives. Underneath sit two interchangeable backends built on a shared base (SqlDatabaseBackend): one persistent on SQLite, one ephemeral in memory; tomorrow PostgreSQL joins as a sibling without touching the executors. Which backend serves a given store is decided in a registry, when the store is declared — never from the user's request. The skill stays dormant until a store is registered.
«baked-in» (debt) abstracted local PLANNER — confused find_issues _github find_issues _gitlab two near-identical names → provider bias local PLANNER — sees 1 tool find_issues (canonical) backend resolver github backend gitlab backend promotion one-off frontier + human review
Figure 2 — Mono→multi provider. On the left the «baked-in» state (find_issues_github + find_issues_gitlab confuse the local planner). On the right the abstracted state: a single find_issues, the resolver, two backends. The arrow is promotion: refactoring with a one-off frontier, then human review. GitHub is currently in the «baked-in» state.
Known debt. Today GitHub is «baked-in»: the sixteen *_github executors (issues, PRs, tasks, comments and — since 25/6 — repo files: find/read/list) carry the provider in the name. It works while the provider stays unique; the moment a second one arrives it must be abstracted. General rule: a provider that plausibly will have siblings (github→gitlab/gitea, IMAP mail, calendar) should be abstracted from the start; one that will stay unique may remain baked-in.

4. On/off lives on the backend

In the multi-provider model the skill does not turn the executor on and off: it turns the backend on and off. This changes who sees what.

Desired effect: turning a provider on or off does not change the planner's tool pool — it always sees find_issues — it only changes routing. Disable one of the two: the other keeps serving. Disable both: the executor goes dormant.

Today gating is by pattern on the executor name (skills_catalog): it works only while the provider is unique. The new piece to build is a skill→backend map plus the rule «executor dormant = AND over all its backends being off». It is the first brick: needed as soon as the first multi-backend executor exists.

5. Promotion: the mechanism

Merging a baked-in, mono-provider skill (*_github) into find_issues + backends is an extraordinary operation. A one-off frontier LLM is allowed ONLY for the refactoring; detection and apply stay deterministic and human-gated — auto-signing frontier-generated code would break the trust model.

PhaseWhoWhat
WHEN (trigger)deterministicon the 2nd provider's arrival — typically the import of a skill that maps onto an object already covered only by provider-suffixed executors (*_github, recognized by the naming authority). Object overlap + provider mismatch → «promotion candidate». No LLM needed to spot it.
WHERE (seam)reused infrastructuredetection in the importer admission layer; refactoring via an escalation to a frontier model in agentic mode; landing in the admin changes page as a change of kind promote_provider, no auto-apply; apply writes the files, re-signs (§7.10), registers skill↔backend and per-backend gating (§4).
HOW (pipeline)frontier only in the middledetect (det.) → the frontier generates {canonical executor + backends/<obj>/{p1,p2}.py + skill→backend map} → the change is proposed → human review → apply + sign + verify with the 7-layer admission + smoke.
Deterministic edges, creative center. The frontier sits only in the middle: it drafts the refactoring. The edges — noticing it is needed, and applying with a signature — are deterministic code and human hands. Three new, independent, incremental pieces: (1) a promotion-candidate detector; (2) the promotion prompt for the frontier escalation; (3) the per-backend gating of §4 — which is needed anyway and is the one to build first.

6. Why MCP stays at the boundary

MCP and the executor contract solve different problems. MCP lets a client discover and invoke tools exposed by a server while negotiating protocol versions and capabilities. Metnos must instead decide what a capability means to the planner, what authority it has, and how its outcome is verified.

The contract referenced here is not an implicit convention: it is the versioned Metnos Executor Standard. An MCP backend must satisfy it just like a local or remote backend.

ConcernMCP providesMetnos must preserve
identitya tool name within one servera provider-independent canonical verb_object name
contracta JSON argument schema; an optional result schemavector shape, error semantics, and an observable postcondition
authorityconnection and authorization to the servercapabilities, sandbox, credential mandate, and consent for the action
lifecyclenegotiation, calls, cancellation, and shutdownlimits, audit, idempotency, reverse operation, and recovery
catalognotifications when tools are added or changedexplicit admission and suspension when a schema changes
Proposed integration constraint, not an available feature. An internal MCP broker may become a transport behind the resolver. The planner will see only a canonical executor, or it will not see the capability at all. A generic mcp_executor(server, tool, args) would introduce a second command language and bypass per-action controls, so it does not belong in the public contract.

An external tool may become the backend of an existing executor, a narrow proxy executor, or remain quarantined. Turning it into a native executor would be a verified, reviewed promotion rather than an automatic rewrite of remote code.

7. Going deeper

To understand…Read
how a third-party skill is imported and turned into signed executorsskill importer
the layered sandbox imported executors run insandbox
the checks before every risky actionvaglio
what an executor is and how it is builtexecutor
the other axis of swappability: how the model (LLM, embedding, VLM) behind the capabilities is chosen and changed, by editing a TOML instead of the codemodel virtualization

8. What this means for you, in practice

What this means for you, in practice. From your point of view, what does all this change? Not much. This complexity lives under the hood. You'll only run into it when you use functions that do the same thing but are offered by different providers — and in fact, only the moment you add the second provider for the same capability: at that point you just ask to «merge» the two skills, and Metnos creates a new backend. Honestly: how often will that happen in everyday use of a tool like Metnos? How often will you use GitLab and GitHub at the same time?
The upside. Metnos is built to stay as local as possible, at no added cost: the brain you use every day runs on your own machine. That abstraction complexity — merging two skills into a backend — is the only moment where, and only if needed, Metnos turns once to a frontier model (presumably paid) to generate the new backend's code. An occasional, explicit, rare cost — not a continuous dependency on the cloud. The rest of the time you are, and stay, local.

Metnos — skill ↔ backend, two orthogonal axes