skill ↔ backend — due assi ortogonali
In Metnos «skill» e «backend» rispondono a due domande
diverse. Il backend dice COME si esegue un
verbo_oggetto contro un servizio. La skill dice
SE e QUALI capacità sono sbloccate, fidate e spedite.
Confonderli porta a sdoppiare gli executor; tenerli separati è quel che
permette di aggiungere un provider senza toccare il pianificatore.
| Backend / provider | Skill | |
|---|---|---|
| Risponde a | COME eseguo verbo_oggetto contro un servizio | SE / QUALI capacità sono sbloccate, fidate, spedite |
| Asse | oggetto × provider | dipendenza esterna (credenziale / backend / hardware) |
| Visibilità | invisibile all'LLM, risolto da configurazione dal resolver dei backend | visibile all'utente (abilita / disabilita, dormienza, recinto, impacchettamento) |
I due assi si toccano solo quando una skill ha un solo
provider: in quel caso github, geo, mail
sono di fatto il nome user-facing del backend di quel provider.
Divergono appena la skill ha più backend (il calendario
si serve su ICS locale, Google o CalDAV) o non ha
alcun provider esterno (le foto, il nucleo). La mappa è
molti-a-molti: un solo provider (Google Workspace) serve più
skill — posta, calendario, drive, fogli, documenti.
find_issues.
«Skill» ha finito per indicare tre cose diverse: una
classificazione di executor già nel repository, dei pacchetti veri in
repository, e codice di terzi importato. Il campo tier le unifica
sotto un modello solo. Vive in skills_catalog.py (funzione
skill_tier()) e nell'intestazione di SKILL.md.
| Tier | Cos'è | Fiducia | Dove vive | Attivazione |
|---|---|---|---|---|
| 1 — core | planner ed engine, file locali, cartelle, processi, tempo, scheduler locale, persone, credenziali, firme, proposte, gli helper dello scratchpad (filtra / ordina / raggruppa / calcola / descrivi / estrai) | massima | repository, firmato, multilingua | sempre attiva |
| 2 — first_party | capacità spedite con Metnos allo stesso standard del nucleo, ma dormienti finché manca la dipendenza: github, foto, posta, web, geo, calendario, frontier, Google Workspace | massima | repository (pacchetto versionato + executor firmati) | automatica, dormiente se non configurata |
| 3 — imported | codice di terzi non auditato né vendorizzato (da agentskills.io e simili) | bassa | dati utente, con provenienza tracciata | opt-in, recinto + rete a 7 strati |
Domani potrebbe arrivare GitLab accanto a GitHub. La domanda è: come si aggiunge un secondo provider per le stesse issue? Due strade.
Generare find_issues_github e find_issues_gitlab
e lasciare che il pianificatore scelga. Funziona dove al centro c'è un
modello frontier che disambigua leggendo la prosa. In Metnos il pianificatore
è un modello locale, che davanti a due nomi quasi
identici sviluppa un pregiudizio sul provider:
sceglie sempre lo stesso, o sbaglia. Lo
sdoppiamento rompe il routing.
find_issues, read_issues, find_pulls.
L'oggetto (issues, pulls) è l'astrazione
stabile.runtime/backends/{issues,pulls}/{github,gitlab}.py.github (PAT) e
skill gitlab (token), con dormienza indipendente — perché
la credenziale è il confine dove serve granularità («abilita
gitlab» senza toccare github)._github / _gitlab
resta per il pin esplicito dell'utente («apri la issue
su gitlab»); il default è agnostico.+1 file backend,
+1 skill (se introduce una credenziale nuova),
0 nuovi executor. È il percorso che calendario e file
hanno già preso.
find_issues_github + find_issues_gitlab confondono il planner locale). A destra lo stato astratto: un solo find_issues, il resolver, due backend. La freccia è la promozione: refactoring con frontier una-tantum, poi vaglio umano.*_github portano il provider nel nome. Funziona
finché il provider resta unico; appena ne arriva un secondo va astratto.
Regola generale: un provider che plausibilmente avrà fratelli
(github→gitlab/gitea, posta IMAP, calendario) va astratto da subito; uno che
resterà unico può restare cotto.
Nel modello a più provider la skill non accende e spegne l'executor: accende e spegne il backend. Questo cambia chi vede cosa.
find_issues è disponibile se
almeno uno dei suoi backend è abilitato e configurato;
diventa dormiente solo se sono spenti tutti (un AND su tutti i
backend).find_issues — cambia solo il routing. Disabilitare uno
dei due: l'altro continua a servire. Disabilitarli entrambi: l'executor diventa
dormiente.
Oggi il gating è per pattern sul nome dell'executor
(skills_catalog): funziona solo finché il provider è
unico. Il pezzo nuovo da costruire è una mappa
skill→backend più la regola «executor dormiente = AND su
tutti i suoi backend spenti». È il primo mattone: serve appena
esiste il primo executor a più backend.
Fondere una skill mono-provider cotta (*_github) in
find_issues + backend è un'operazione
straordinaria. È ammesso un LLM frontier
una-tantum SOLO per il refactoring; rilevamento e
applicazione restano deterministici e con vaglio umano — firmare
in automatico del codice generato da un frontier romperebbe la fiducia.
| Fase | Chi | Cosa |
|---|---|---|
| QUANDO (trigger) | deterministico | all'arrivo del 2° provider — tipicamente l'import di una skill che mappa su un oggetto già coperto solo da executor provider-suffissati (*_github, riconosciuti dall'autorità di naming). Sovrapposizione di oggetto + provider diverso → «candidato a promozione». Nessun LLM per accorgersene. |
| DOVE (seam) | infrastruttura riusata | rilevamento nel layer di ammissione dell'importer; refactoring tramite l'escalation a un modello frontier in modo agentico; atterraggio nella pagina admin delle modifiche come modifica di tipo promote_provider, niente auto-apply; applicazione che scrive i file, ri-firma (§7.10), registra skill↔backend e gating per-backend (§4). |
| COME (pipeline) | frontier solo in mezzo | rileva (det.) → il frontier genera {executor canonico + backends/<obj>/{p1,p2}.py + mappa skill→backend} → la modifica viene proposta → vaglio umano → applica + firma + verifica con i 7 strati di ammissione + smoke. |
Per capire perché Metnos separa skill e backend mentre gli altri li fondono, conviene guardare chi sta al centro a scegliere il provider.
| Hermes / skill drop-in | Claude-Code + famiglia MCP | Metnos | |
|---|---|---|---|
| chi sceglie il provider | frontier (legge SKILL.md, disambigua) | frontier (legge le descrizioni dei tool) | modello locale medio (Gemma): ha un pregiudizio sul provider |
| skill vs backend | fusi (skill = cartella di script = provider) | fusi (tool / server MCP = provider) | separati (backend = esecuzione, skill = attivazione) |
| multi-provider | skill parallele per provider, l'agente sceglie | tool / server paralleli, il modello sceglie | un executor canonico + un backend per provider (resolver) |
| credenziale / dormienza | required_credential_files + setup | implicita (server connesso o no) | dormienza formalizzata |
| fiducia | esegue il codice della skill coi propri privilegi | esegue tool / server | vocabolario chiuso + recinto a 7 strati |
| Per capire… | Leggi |
|---|---|
| come si importa una skill di terzi e la si trasforma in executor firmati | skill importer |
| il recinto a strati in cui gli executor importati eseguono | sandbox |
| i controlli prima di ogni azione rischiosa | vaglio |
| cos'è un executor e com'è fatto | executor |
Metnos — skill ↔ backend, due assi ortogonali