Questa pagina è la guida d’ingresso alla microprogettazione di Metnos. Non descrive il sistema dall’alto — quello lo fa l’Architettura — Introduzione — ma ne mostra i pezzi: come si chiamano, cosa fanno, come si parlano fra loro. Procediamo dal generale al particolare, fissando i termini prima di usarli.
L’architettura di Metnos vive su due piani.
Il piano alto — chiamato Livello 1 — descrive il sistema nel suo
insieme: i quattro strati, gli organi, le leggi, i fini. Lo trovate nel file
Metnos_Architettura_Intro_v1.html.
Questa cartella è il piano basso, il Livello 2: un documento HTML per ogni componente, con il dettaglio sufficiente a scriverne il codice senza inventare nulla. Le scelte qui non sono opinioni — sono contratti: schema dei dati, firme delle funzioni, flag di sandbox, condizioni di errore. Quando il codice e il documento divergono, vince il documento e il codice si adegua, oppure il documento viene corretto subito (mai «dopo»).
La regola di vita è semplice: nessun componente viene implementato prima che il suo HTML esista, sia approvato e parli la stessa lingua del codice già in casa.
Tutto Metnos gira intorno a quattro nomi. Definirli adesso vi risparmia mezz’ora di confusione fra trenta righe.
/opt/metnos/executors/ e sintetizzati al volo in
~/.local/share/metnos/executors/, più quelli importati da
skill esterne.Sono ventuno componenti documentati. Lo schema sotto li raggruppa per ruolo: il bordo nero spesso è il motore centrale, le forme verdi i «servizi» che il motore consulta, le forme azzurre i «tessuti» che memorizzano lo stato, le forme color bronzo gli organi periferici verso l’utente e verso l’ambiente. Le frecce indicano chi chiama chi.
Tre osservazioni utili per leggere lo schema.
Per fissare la mappa, seguiamo una richiesta semplice dall’ingresso
fino alla risposta: «sposta in ~/Archivio/2026 i PDF di
fatture arrivati questa settimana».
move;
oggetto: files; criterio: PDF allegati a fatture in finestra
«ultima settimana»), interroga il prefilter per ridurre il
catalogo agli executor pertinenti e prepara il primo passo del loop
ReAct.rm -rf e simili). Per le operazioni
che cadono in zona grigia, il giudice rule-based assegna un punteggio
e, se sopra soglia, chiede una conferma all’utente tramite
carta a 3 righe (cosa/dove/perché).read_messages dentro bwrap con i flag derivati
dal manifest. L’output torna come lista di entries; ogni
entry è un dizionario con il path del PDF e i metadati.move_files; riceve la lista del passo precedente con
from_step: N. La verità sui dati vive nello
scratchpad: il pianificatore non vede l’intera lista, ne vede una
vista sintetica che gli basta per decidere.read_messages → move_files rinforza una
traccia esistente nel grafo. Se non esiste, viene creata. L’ager
notturno farà manutenzione: decadimento, fusioni, scarti.
Sotto, i ventuno documenti raggruppati per ruolo. Tutti hanno la
controparte inglese in
/en/architecture/.
| Componente | Cosa copre |
|---|---|
Motore cognitivo |
Il motore a quattro strati che pianifica ed esegue (sostituisce il pianificatore passo-passo iterativo): Fastpath serve le scorciatoie approvate dall'utente (hash + coseno BGE-M3), Autopath riconosce e riusa le skill apprese dal feedback (sqlite, match semantico + intent), Validator controlla il piano prima di eseguirlo, e il blocco Engine propone l'intero piano in una sola chiamata LLM locale (Proposer), lo esegue deterministico (Executor), recupera classificando l'errore in 4 classi (Recovery) e, se non c'è via d'uscita, spiega onestamente cosa manca (Terminator). Una sola proposta invece di sei chiamate: più veloce, costo zero, e accelera ancora man mano che impara. |
agent_runtime |
Loop ReAct, mode router, data piping fra step (from_step: int per liste, {{stepN.field}} per scalari), scratchpad, hook su mnestoma. È il motore che chiama tutti gli altri. |
scratchpad |
Archivio temporaneo del turno: tiene le observation grandi senza occupare il contesto del pianificatore. Builtin scratchpad_read con head/tail/range. |
grammar |
Constrained generation via GBNF per il tool_call del PLANNER. Discriminated union nome+args, schema recursive, pool filter contestuale, validator post-decode. Risolve thinking-loop, mix-match args, escape-hatch arbitrari. Bench convergenza 50% → 100%. |
fast-path introvertivo |
Tre livelli di memoizzazione prima del pianificatore: L0 modelli letterali («che ora è»), L1 single-tool tramite canonical_matcher con match BGE-M3 sul canonical query log, L2 sequenze multi-step tramite multi_tool_paths con TTL in giorni di attività effettiva. Ponte L2→L3 verso la sintesi via proto-mnest. Estrattore di argomenti ibrido regex + memoria + LLM opzionale. Configurazione persistente in ~/.config/metnos/runtime.toml. |
lifecycle |
Lifecycle unificato dei cambiamenti al sistema: un solo oggetto change_intent, una sola macchina a stati (proposed→accepted→applied→observed→finalized, più staged/rejected/failed/rolled_back), una sola UI /admin/changes. Convoglia le sorgenti di proposta (telos, introvertiva, synt, fast-path, feedback) in un’unica coda. Pipeline notturna: materializzazione (dedup fra sorgenti via fingerprint), applicazione per tipo, osservazione con periodo di grazia e rollback fisico. |
| Componente | Cosa copre |
|---|---|
executor |
Introduzione didattica: cos'è un executor, anatomia in cinque file, manifesto firmato, recinto di esecuzione, ciclo di vita, tre origini (a mano / generato / di sistema). Tre esempi concreti. Per chi vuole capire, non per chi deve implementare. Pool corrente: 79 executor. |
synt |
Come nascono nuovi executor: pipeline a cinque stadi (naming, signature, tests, description, code), cascata reattiva (compose → generate) e introvertiva (dedupe, generalize, specialize). |
skill_importer |
Importa skill di terzi da agentskills.io e ne ricava executor Metnos: pipeline a cinque stadi (fetch, parse, map, wrap, register), tabella di mapping verbi skill_vocab_map.json, helper di wrapping con confine del verbo e CLI metnos-skills import|list|uninstall|status|evaluate. |
skills & backends |
Perché skill e backend sono due assi ortogonali: il backend dice COME esegui un verbo_oggetto (configurazione, backend_resolver, invisibile all'LLM), la skill dice SE/QUALI capacità sono sbloccate (attivazione, dormienza, recinto). Tre tier (core / first_party / imported), architettura multi-provider trasparente al planner, promozione con frontier una-tantum. |
| Componente | Cosa copre |
|---|---|
mnest |
La traccia di co-attivazione fra due executor: anatomia, lifecycle, decadimento, persistenza, proto-mnest. |
mnestoma |
Il grafo emergente di tutti i mnest: schema dati SQLite, operazioni atomiche, ager notturno, snapshot. In EN il termine è mnestome. |
| Componente | Cosa copre |
|---|---|
vaglio |
Guardia binaria (forbidden paths, comandi shell quasi-irrecuperabili) e giudice graduato rule-based con soglia configurabile. Giudice LLM probabilistico rinviato. |
policy |
Capability registry: tredici capability canoniche, tabella autonomy × capability (ReadOnly / Supervised / Full), grants per_target persistenti, effective_outcome combinato. |
sandbox |
Profilo bwrap derivato dal manifest: read-only del codice, isolamento di rete se nessuna capability lo richiede, fallback graceful se bwrap manca. Landlock rinviato. |
| Componente | Cosa copre |
|---|---|
channel |
Adattatore canale (Protocol con send / poll) e prima implementazione concreta: TelegramChannel con long-poll, persistenza last_update_id, daemon e systemd user unit. Multi-user: send_to(chat_id, OutboundMessage) + /start <token> per pairing guest. |
http_api |
Secondo server HTTP (porta 8770): canale agent uniforme su POST /agent/turn (SSE + JSON), dashboard /admin in htmx + Jinja2 + uPlot, gestione utenti, proposte introvertiva, scheduler runs. Auth via admin key (cookie 7g) o Bearer device. |
pairing |
Due percorsi: /pair con codici Ed25519 firmati per device tecnici e /start <token> a vita breve per familiari/guest (multi-utente). Registro users.db con host + guest, user_channels, resolve_recipients. Bootstrap automatico del host al primo avvio. |
approval_ux |
Carta a 3 righe per le richieste di conferma: render_approval_card, ApprovalRequest, modulazione full / medium / short per ricorrenza, dispatcher Telegram approve:<tok> / reject:<tok>. |
| Componente | Cosa copre |
|---|---|
multilang |
Tre layer multilingua: prompt LLM (runtime/prompts/<lang>/<role>.j2), description executor (manifest TOML + companion JSON), messaggi user-facing (i18n.sqlite). Source-of-truth latest-wins: nessuna lingua canonica per costruzione, vince chi viene editato per ultimo. Comando admin metnos-prompts add-language <code>. Tier frontier opt-in per qualità superiore. |
| Componente | Cosa copre |
|---|---|
observability |
Dashboard statica HTML che aggrega le sorgenti dati di Metnos (mnestoma, pairing, turni, decisioni del Vaglio, scheduler). Generata su richiesta: nessun server live, niente JavaScript. |
telos |
Fini ultimi dell’utente, funzione di allineamento, bother budget con quote di scheduler, telos di non-rinuncia (t.coltivazione_strumenti) e clausola di stop. Il file TELOS.md vive nel workspace. |
Il vocabolario chiuso conta 23 azioni
(read, write, move, delete, create, find, list, filter, sort,
group, classify, get, set, send, describe, render, extract, compress,
compute, compare, change, order, share) e 22 oggetti
(files, dirs, packages, messages, events, calendars, contacts, places,
processes, urls, numbers, images, signatures, texts, proposals, inputs,
credentials, entries, persons, tasks, issues, pulls). I qualifier sono divisi in
quattro famiglie: formato (codifica del dato), modalità (come
agisce l’executor), criterio di sicurezza, provider (per indicare
un backend diverso da quello predefinito, ad esempio
_google_workspace). Tutto centralizzato in
runtime/vocab.py.
Le liste di entries che il turno produce passo per passo si manipolano
con tre primitive. filter_entries riduce una lista
applicando un predicato a un campo (where_starts_with,
where_contains, where_glob,
where_regex). filter_lists opera fra due
liste: intersezione, unione, differenza, differenza simmetrica e
sovrapposizione temporale. compute_entries calcola un
numero a partire da una lista (somma, media, minimo, massimo, conteggio).
Esempio reale: la domanda «c’è un appuntamento HLT che
si sovrappone a uno MNM nei prossimi tre mesi?» viene risolta in
sei passi: read_events → due filter_entries
(uno per HLT, uno per MNM) →
filter_lists(op=overlap) → risposta finale.
Il pool di executor conta 79 unità fra scritti a
mano e sintetizzati, più gli executor importati da
skill esterne (Google Workspace, ecc.). Verbi-produttori ortogonali a 5
(find per pattern, get per id/stato,
read per blob da sorgente, list per container,
filter per riduzione).
Ogni file di microprogettazione segue lo stesso template dell’Architettura — Introduzione:
id stabili;DEVI / NON DEVI / OK / ERRORE,
quattro righe massimo;