--- tipo: entità --- # Scatola LLM wrapper — idea da pausa caffè (05/09/2026) **Stato: teoria, non decisa, non scoped.** Nata in conversazione (05/09/2026), non un'iniziativa avviata. Due facce della stessa idea, agli antipodi sull'asse costo/potenza: una scatola economica per compiti banali (sotto), e una scatola potente per reasoning/ricerca mirata (in fondo). Stesso tratto comune — sostituibile, nessuno stato proprio, input preciso dal chiamante — ma diverse nel trattamento dell'output: la prima vuole una risposta rigida a schema fisso, la seconda vuole un risultato ricco da valutare criticamente prima di usarlo. ## L'idea (faccia economica) Un wrapper Python sottile attorno a una singola chiamata LLM, pensato per essere facilmente sostituibile a livello di provider (Claude, GPT, Gemini, qualunque modello via es. OpenRouter). Non un agente: nessuno stato, nessuna memoria propria, nessun accesso a tool/filesystem — solo un contratto fisso (input tipizzato/schema → output tipizzato/schema). Il wrapper non incapsula mai le informazioni del dominio: quelle arrivano dal chiamante a ogni invocazione, precise e mirate. Tutta l'intelligenza su "cosa passargli e cosa farne del risultato" resta un livello sopra, in chi orchestra la chiamata — stesso principio "orologio vs giudizio" già usato per i `servizio` (vedi `CLAUDE.md`), applicato qui alla singola chiamata invece che a un intero processo. ## Caso d'uso proposto Sotto-compiti banali dentro sessioni secondarie (slave/servizio/sentinelle) che oggi pagano il costo pieno di una sessione Sonnet 5 intera per lavoro che non richiede quel livello — es. classificare/estrarre un campo ambiguo da un documento. Discutendo l'esempio concreto (PDF→testo) è emerso un confine più netto di quanto sembrasse all'inizio: la maggior parte di quel compito non è nemmeno lavoro da LLM — testo vero in un PDF è estrazione meccanica (`pdftotext`), una scansione è OCR (Tesseract). La scatola varrebbe solo per il pezzo residuo che è genuinamente giudizio (classificare, interpretare un'ambiguità), non per l'estrazione in sé. ## Motivazione economica Miglior rapporto qualità/prezzo: instradare compiti banali su un modello più economico (Haiku, o un provider terzo via OpenRouter) invece di Sonnet 5, pagando solo per la potenza che il compito richiede davvero. ## Punto aperto — visibilità del costo `scripts/monitor-consumo-istanze/report.py` vede solo sessioni Claude Code (legge i transcript `.jsonl` che il CLI `claude` scrive da solo). Una chiamata diretta a un'API esterna (bypassando il CLI) non genera quei file — sparirebbe da quel radar. Mitigato in parte se il provider ha un dashboard di spesa reale (es. OpenRouter, pay-per-use, mostra i dollari spesi direttamente) — risolve la visibilità economica aggregata, meglio di quanto faccia oggi il monitor (che stima da conteggio token, non da fattura vera). Resta scoperta solo l'**attribuzione**: sapere quale scatola/chiamante specifico ha generato quale spesa richiederebbe taggare le chiamate (header/ metadata supportati da OpenRouter) — rilevante solo se la spesa aggregata scala abbastanza da dover distinguere la fonte. ## Prossimi passi (se si decide di procedere) - Individuare un caso reale concreto (non ipotetico) dove il sotto-compito è genuinamente solo giudizio, non estrazione meccanica — punto di partenza candidato: il passaggio di `servizio-gate-watch` dove oggi si lancia una `slave` intera solo per leggere un log di fallimento già estratto e spiegarne la causa. - Decidere provider/canale (OpenRouter vs API diretta Anthropic per Haiku) e schema di input/output rigido (JSON strutturato, non prosa libera — altrimenti si perde la sostituibilità reale tra modelli). - Se si procede, definire un contatore/log separato per queste chiamate dirette, per non perdere la visibilità di attribuzione discussa sopra. Non richiedere approvazione implicita da questo file: resta un'idea da riprendere in conversazione con Mauro quando/se emerge un caso concreto da scoprire, non un piano da eseguire. ## Seconda faccia — scatola potente per reasoning mirato/ricerca complessa (05/09/2026) Stessa forma (lancio, aspetto il risultato, nessuno stato persistente), ma all'estremo opposto dell'asse: non un modello economico per compiti banali, un modello molto potente per un compito di reasoning mirato o una ricerca complessa in internet — dove il valore non è risparmiare, è la capacità grezza per un compito che non farei girare in una sessione normale (troppo lungo, troppo esplorativo, o semplicemente meglio isolato). **Trattamento dell'output, speculare rispetto alla faccia economica**: lì la scatola deve restituire qualcosa di rigido e fidabile a schema fisso; qui è l'opposto — il risultato è ricco, discorsivo, e va **valutato criticamente prima di usarlo**, mai accettato automaticamente. È esattamente lo stesso trattamento che la Costituzione impone già alle proposte esterne (Gemini, ChatGPT, documenti condivisi — vedi `CLAUDE.md`, sezione "Proposte da altri agenti"): arriva, Adrian valuta, poi eventualmente coinvolge Mauro. Qui la fonte è una chiamata lanciata da Adrian stesso invece che un agente esterno, ma il principio di non fidarsi ciecamente resta identico — se mai più pulito, perché non c'è nemmeno il dubbio sulla fonte. **Non è teoria pura — esiste già in due forme, solo non frame-ate così**: - `RemoteTrigger` (routine cloud claude.ai) — tool azionabile direttamente da Adrian (`action: run` lancia on-demand, `list_runs`/`get_run_log` leggono poi il risultato) — verificato 05/09/2026 che è davvero invocabile, non solo un meccanismo passivo. Le due routine esistenti oggi (report settimanale novità Claude Code, controllo coerenza SecondBrain) notificano però **Mauro**, non Adrian — scelta di destinazione fatta alla creazione di quelle due routine specifiche, non un limite del tool: una routine nuova/dedicata potrebbe restare visibile solo ad Adrian via `get_run_log`, se mai servisse una "scatola potente" di questo tipo con risultato da valutare prima di coinvolgere Mauro. - Tool `Agent` con `model: "opus"` — versione sincrona dentro la sessione: sotto-agente più potente su un compito mirato, resto io a giudicare cosa farne del risultato. Nessun caso concreto ancora individuato per aggiungere una terza forma dedicata — resta annotata come simmetria concettuale della prima faccia, da riprendere se emerge un compito reale che non è già coperto da `RemoteTrigger`/`Agent(model=opus)`. ## Candidati concreti per routine `RemoteTrigger` (05/09/2026) Emersi discutendo se una routine notificasse Adrian invece di Mauro (cambiando la scelta di destinazione di default delle due routine esistenti) — entrambi da configurare così se ripresi: - **Bibliotecario** ([[project_bibliotecario_memoria]]) — **riaperto come possibile candidato, 05/09/2026**: scartato in un primo momento perché il design deciso il 04/09 richiede lettura dei trascritti `.jsonl` grezzi locali (`~/.claude/projects/...`), un'istanza per macchina — dati che una routine cloud claude.ai non vede di default. Sincronizzarli via Dropbox/Drive per dargli accesso era stato scartato (stesso rischio già visto con Docker in cartella Dropbox, contenuto non filtrato che si propaga). **Ma esporli via un MCP server dedicato sulla Nave** (stesso pattern già in produzione con `mcp-query.service` per i dati di business — servito su richiesta, scoped, mai sincronizzato/duplicato) risolverebbe l'accesso senza quel rischio. **Non verificato**: se una routine `RemoteTrigger` può agganciare un connettore MCP custom come farebbe un progetto claude.ai interattivo — i connettori sembrano pensati a livello di progetto/account, non scontato che una routine schedulata ne erediti l'accesso. Se sì, tornerebbe un candidato valido (con un pezzo di lavoro in più: costruire quel server MCP). Se no, resta candidato solo per una `sentinella`/`esperto` locale. **Vincolo che conta più della scelta routine-vs-locale (05/09)**: qualunque implementazione, il rischio reale è il consumo di token per leggere contenuto grezzo pesante — stessa causa esatta che ha fatto esplodere `inbox-documenti` il 04/09 (PDF scansionati letti per intero, sessione mai ruotata, vedi [[project_servizi_meccanici]]). Se il server MCP rispondesse col dump intero di un trascritto a ogni query, si ricreerebbe lo stesso problema già diagnosticato e chiuso una volta — a prescindere da dove giri il chiamante. Il server deve esporre query mirate/incrementali (digest preaggregato, non il grezzo intero) perché il bibliotecario non torni al punto di partenza che ha già causato una conversione di massa il 4/09. **Verificato (05/09, pausa caffè)**: sì, una routine `RemoteTrigger` può agganciare un connettore MCP custom — testato con un routine one-shot reale (`test-mcp-query-cloud`, `trig_015Zop3KRMnPMPmskgPPs8Rf`) con `mcp_connections` puntato a `mcp-query` (`https://query.privcloud.dev/mcp`, stesso connettore già in uso da questa sessione): il routine ha visto entrambi gli strumenti (`list_tables`, `query_business_data`) e `list_tables` ha risposto correttamente con le 14 tabelle attese, nessun errore. Chiude il dubbio aperto sopra — il pezzo mancante per un futuro MCP server dedicato del bibliotecario non è più "se una routine può vederlo", ma solo "costruire il server". Dettaglio del test e delle scoperte collaterali (canale di ritorno, `PushNotification` da routine) nella sezione "Verifiche 05/09" in fondo. **Sintesi (05/09): la faccia economica della scatola è il pezzo che risolve questo vincolo.** Invece di far leggere il grezzo intero a una sessione Sonnet 5, o farlo dumpare intero dal server MCP, il digest per-sessione lo produrrebbe la scatola economica (faccia 1, sopra) — un modello leggero chiamato una volta per sessione chiusa, che comprime il `.jsonl` grezzo in un riassunto strutturato. Il bibliotecario lavorerebbe solo su quei digest, mai sul grezzo intero: il costo resta basso per costruzione, non per disciplina. Cascata completa: il server MCP fa da orologio (serve dati su richiesta), la scatola economica fa il giudizio minimo (comprimere), solo il risultato compresso arriva a chi deve ragionarci sopra — stesso principio "orologio vs giudizio" della Costituzione, applicato in due stadi invece di uno. Prima vera sintesi concreta tra le due facce di questo canvas. **Implicazione (05/09): la trasformazione grezzo→digest è a senso unico e permanente.** Una volta prodotto, il digest entra in `archivio/` (storico per sempre, sincronizzato Dropbox+git); il `.jsonl` grezzo locale può anche sparire dopo (rotazione, pulizia disco, cambio macchina) senza perdere sostanza — oggi invece la storia vive solo nel grezzo locale, che nessuno pulisce mai per paura di perdere qualcosa. Questo disaccoppia il problema in due parti indipendenti: (1) **produrre il digest** — fattibile da subito, offline, locale (un cron/futuro `servizio`), nessuna dipendenza dal resto; (2) **come interrogare poi i digest accumulati** (routine cloud, esperto locale, lettura diretta) — quella resta la domanda aperta discussa sopra, ma non blocca più la (1). La priorità pratica, se si riprende questa idea, è partire dalla (1). **Gap reale scoperto e chiuso (05/09) — poi allargato a tutta la home**: verificando "quanto possiamo andare indietro nel tempo con i raw" è emerso che `/home/mauro/.claude/projects/` (dove vivono i `.jsonl` grezzi) è sul disco di sistema (`nvme0n1p2`), fuori da `/mnt/ssd` — nessuno dei due backup esistenti lo copriva (`backup_completo.sh` restic e `pcloud_backup.sh` rclone hanno entrambi come sorgente solo `/mnt/ssd`). I 217MB di storico grezzo disponibili (dal 06/08/2026, non più indietro) non avevano alcuna protezione. Mauro ha poi chiesto se mancasse altro — controllato che **Timeshift esclude `/home` deliberatamente** (backup di sistema, non dati utente) e che il resto della home non era coperto affatto: dentro c'erano anche `~/.ssh/id_ed25519` (chiave privata, non rigenerabile), `~/Documenti`/`~/Immagini`/ `~/Scaricati` (contabili, documenti reali) e le sessioni di altri CLI AI (`.codex`, `.gemini`, `.qwen`, `.letta`) — stesso identico problema dei trascritti Claude. **Chiuso lo stesso giorno, scope allargato**: entrambi gli script ora hanno `/home/mauro` intero come sorgente aggiuntiva (non solo `.claude/projects`), con esclusioni dedicate per cache/stato rigenerabile (`scripts/backup_home_exclusions.txt` per restic, `..._rclone.txt` per pCloud — sintassi diversa, stesso contenuto). Nel dry-run è emerso un secondo problema reale: `~/Scrivania/ Dropbox` è un symlink verso `/mnt/ssd/data/Dropbox` — con `--copy-links` rclone lo attraversava duplicando 30GB già coperti dall'altra sorgente; escluso esplicitamente. Validato a 0 errori, ~371MB netti su entrambi i canali. - **Watchdog esterno sulla Nave** (idea nuova, nata qui): una routine che pinga la Nave da fuori a intervalli regolari e notifica se non risponde — varrebbe perché non condivide il punto di fallimento con la cosa che controlla (ogni check di salute oggi gira *sulla* Nave, inutile se la Nave stessa è giù). **Fattibilità tecnica non verificata, dubbio esplicito sollevato da Mauro il 05/09**: dipende da (1) se una routine claude.ai può fare una richiesta HTTP verso un endpoint arbitrario durante l'esecuzione, mai visto usato così — solo un'ipotesi; (2) se c'è un endpoint della Nave raggiungibile pubblicamente da pingare — `mcp-query.service` è già esposto su `https://query.privcloud.dev` (via Caddy), quindi la condizione favorevole esisterebbe già, ma dedurre "Nave viva" da "mcp-query risponde" resta un'inferenza indiretta (potrebbe essere giù solo quel servizio). Non scartata, ma non da trattare come soluzione pronta finché non si verifica il punto (1). - **Backstop resilienza `sentinella-gmail-personale`** (idea nuova, nata qui, 05/09): la finestra minima di una routine (~1h) non basta a sostituire il ciclo di 20 minuti del filtro continuo, ma è perfetta per un ruolo diverso — una rete di sicurezza esterna che non condivide il destino della Nave, sullo stesso principio del watchdog sopra. Si aggancia a un thread già aperto in `MEMORY.md` ("resilienza avvio automatico Nave dopo riavvio non presidiato"): se la Nave si riavvia senza supervisione e la sentinella non ripartisse da sola, nessun meccanismo *sulla* Nave potrebbe segnalarlo. Una routine oraria che controlla (via connettore Gmail cloud, già disponibile lato claude.ai) se ci sono email non filtrate da troppo tempo potrebbe notare l'anomalia dall'esterno. **Punto in più emerso in discussione**: la stessa routine potrebbe avere accesso anche al mirror Google Drive "SecondBrain" (proiezione read-only di `archivio/`, vedi `project_secondbrain_gdrive.md`) — quindi non partirebbe del tutto alla cieca, potrebbe leggere la base di conoscenza curata (anche se non lo stato più recente/`MEMORY.md` in tempo reale, dipende dalla cadenza del sync `rclone`) per capire cosa aspettarsi prima di segnalare un'anomalia. **Primo dei due punti verificato indirettamente il 05/09** (vedi sezione sotto): i connettori disponibili per un routine includono anche Google Drive, non solo Gmail/mcp-query — quindi l'accesso Drive da una routine è tecnicamente confermato. Cadenza effettiva del mirror ancora non verificata. ## Verifiche 05/09/2026 — test one-shot mcp-query da routine cloud (pausa caffè) Nato da una domanda leggera di Mauro ("le due schedulazioni Claude.ai potresti intercettarle tu direttamente?") allargata fino a un test reale. Tre scoperte concrete: 1. **Un routine `RemoteTrigger` può usare un connettore MCP custom** — verificato con `test-mcp-query-cloud` (vedi sopra, sezione Bibliotecario). Chiude quel dubbio per qualunque futura routine che debba leggere dati di business o un futuro MCP server dedicato. 2. **Gotcha: un routine cloud non ha modo di rispondere ad Adrian in tempo reale.** `SendMessage` da una sessione cloud verso una sessione interattiva non è (ancora) bidirezionale — l'unico canale di ritorno affidabile è `RemoteTrigger action: get_run_log`, letto da Adrian quando controlla. **Rischio scoperto nello stesso test**: senza un divieto esplicito nel prompt, il routine ha usato di propria iniziativa `PushNotification` per avvisare **direttamente Mauro** ("Test connettività mcp-query: OK...") — bypassando Adrian, la stessa violazione di principio che per slave/sentinelle/esperti è vietata per costruzione (vedi `feedback_slave_mai_bypass_adrian.md`), qui invece possibile perché nessuno gliel'ha vietato. **Implicazione per qualunque routine reale futura**: il prompt deve vietare esplicitamente `PushNotification` e istruire a lasciare solo il risultato nel testo finale della run, se si vuole mantenere Adrian come unico referente verso Mauro. (Nota a margine, non legata al routine: la `PushNotification` di test comunque non è arrivata sul telefono di Mauro — stesso bug piattaforma già noto in `MEMORY.md`, riprodotto qui anche da un routine cloud, non solo da Nave.) 3. **Idea nuova: mailbox su Google Drive come canale di ritorno durevole**, proposta da Mauro per non dipendere dal ricordarsi di controllare un `trigger_id` specifico via `get_run_log`. Il routine scriverebbe un file in una cartella Drive dedicata (connettore Drive già disponibile ai routine, confermato in questo stesso test — vedi elenco connettori); Adrian la leggerebbe con il proprio connettore Drive, già attivo in questa sessione, senza passare da `rclone`. **Va tenuta distinta dal mirror SecondBrain** (`project_secondbrain_gdrive.md`): quello è un flusso a senso unico Nave→Drive, sola lettura per chi guarda da Claude.ai; questa sarebbe una cartella separata con flusso opposto (routine→Drive→Adrian) — stessa infrastruttura Drive, due canali indipendenti. **Discusso anche chi dovrebbe controllarla**: non `sentinella-gmail- personale` (ruolo volutamente stretto, solo filtro email, mescolarci un compito diverso lo confonderebbe) — più coerente un futuro `servizio` meccanico dedicato, stesso pattern di `servizio-inbox-watch`/`servizio-gate-watch` (poll della cartella, reazione solo sui file nuovi). **Stato: idea, non costruita** — vale la pena solo quando avremo routine cloud reali in produzione che ne abbiano davvero bisogno, non per un singolo test one-off.