andreapellizzari.it
Indice studio
Architetture AIv1.35353 parole · 20 min

Agentizzare un'azienda: timeline e flussi reali

Volume operativo dello studio sull'agentizzazione PMI. Timeline grafica che mostra quando entra ogni strumento; cinque flussi reali end-to-end (onboarding, chat tecnica, query cross-brand strutturata, generazione offerta, ETL notturno) con strumenti specifici per ogni passo; diagramma complessivo del sistema allineato all'architettura v2.0 a 5 livelli.

Creato: Aggiornato: In evoluzione

Questo studio e' il volume operativo di Agentizzare una PMI: stack, architettura, strumenti. Lo stack per i miei progetti l'ho descritto la'. Qui mostro come si applica nella pratica: in che ordine entrano gli strumenti nel tempo, e cinque flussi reali end-to-end con tutti i passi e gli strumenti coinvolti.

E' la differenza tra una mappa e un percorso effettivamente camminato.

Timeline grafica fase / strumento

Vista cronologica di quando ogni strumento entra nello stack. Ogni colonna e' una fase temporale; ogni riga e' un layer architetturale. La scelta consapevole di un colore indica priorita' e livello di urgenza.

Layer
Mese 1
Mese 2
Mese 3
Mese 4-6
Mese 6+
Agent runtime
Agent SDK
Agent SDKGuardian agent
Agent SDKSupervisor pattern
Orchestrator
Inngest
InngestApproval gates
Inngestpybreaker
MCP servers
FastMCPgestionale-mcp
gestionalecatalogo-mcp
gestionale, catalogocomm-mcp
tutti i precedentiproduzione-mcpmulti-vendor
tutti
Security
.env.localfail2ban
Infisical, PresidioJWT/API key per agente
tuttiAuthelia (SSO)RLS multi-tenant
tuttiAI Act risk assessment
Network / infra
Compose, CaddyCloudflare WAF
VPS upgradeCoolify (PaaS)
tuttiMulti-VPS / scaling
Human interface
Email manuale
AppriseApproval inbox custom
Le pillole tratteggiate sono strumenti gia' attivi dalle fasi precedenti.
P1 da adottare prestoP2 fase intermediaP3 opzionale o tardivocontinued attivo da fasi precedenti

Quattro flussi concreti

Quattro casi d'uso che potrei realisticamente avere. Per ognuno: trigger, step-by-step, chi chiama chi, cosa produce, quali strumenti. La somma di questi flussi da' l'immagine reale di come lo stack respira giorno per giorno.

Flusso 1: onboarding nuovo cliente

Onboarding nuovo cliente nel gestionale

Il commerciale registra un nuovo cliente nel gestionale. Il sistema arricchisce l'anagrafica, prepara un'email di benvenuto personalizzata, attende approvazione umana, invia.

PatternPipeline lineare deterministica
TriggerWebhook gestionale
Durata auto~30 sec + approval
Costo stimato~0.05 €/cliente
0

Trigger

Il gestionale invia webhook POST /webhook/erp al VPS quando un nuovo cliente viene salvato. Inngest riceve l'evento erp/cliente.creato con payload (cliente_id, ragione_sociale). Genera trace_id = uuid().

Strumenti:Gestionale ERP · Caddy · Inngest · Cloudflare WAF
1

Recupero anagrafica completa

L'agente principale (Claude Sonnet) chiama gestionale-mcp.cerca_cliente(cliente_id). L'MCP server fa GET, restituisce JSON con: ragione sociale, P.IVA, indirizzo, settore merceologico, contatto referente.

Strumenti:Inngest · Claude Agent SDK · gestionale-mcp · Langfuse · prompt caching
2

Classificazione e arricchimento

L'agente interpreta il settore merceologico. Cerca articoli pertinenti via catalogo-mcp.suggerisci_per_categoria. Restituisce 5 articoli piu' venduti per categoria.

Strumenti:Claude Sonnet · catalogo-mcp · pgvector
3

Generazione bozza email

L'agente compone email di benvenuto in italiano: presentazione azienda, richiamo a 3 articoli rilevanti per il settore, call-to-action soft. Output: bozza markdown + oggetto.

Strumenti:Claude Sonnet · prompt caching (system prompt 2k token cached, -90% costo) · Langfuse
4

Validazione Guardian agent

Guardian

Un secondo agente (Claude Haiku, modello piu' economico) riceve bozza + regole hardcoded: tono brand, no promesse di sconto, no claim non documentati, max 3 link. Output: {ok: bool, issues: [...]}. Se KO, lo step 3 ricomincia con feedback.

Strumenti:Claude Haiku · regole hardcoded (Layer C) · Langfuse
5

PII redaction prima dei log

Prima di scrivere il log finale su Langfuse, Presidio scansiona la bozza e maschera P.IVA, email del cliente, numero di telefono. La bozza completa va al cliente, ma il trace contiene [EMAIL_REDACTED].

6

Approval gate umano

Approval

step.waitForEvent("onboarding.approvato", timeout: "48h"). Apprise notifica il commerciale via Telegram con link all'approval inbox. Lui apre, vede la bozza, clicca "Approva" o "Modifica e approva". Se nessuna risposta in 48h, escalation a responsabile commerciale.

Strumenti:Inngest waitForEvent · Apprise · Telegram · Approval inbox custom (Next.js)
7

Invio email + audit immutabile

Invio via SMTP. Append su audit_log Postgres: (audit_id, trace_id, cliente_id, decisore_umano, timestamp, hash_email). Aggiorna campo cliente.onboarding_audit_id = trace_id tramite gestionale-mcp.

Strumenti:SMTP · Postgres audit_log · gestionale-mcp
8

Notifica conclusione

Apprise notifica al commerciale "Email inviata a [Cliente]" con link al trace Langfuse per audit immediato.

Strumenti:Apprise · Telegram

Flusso 2: domanda tecnica consulenziale via chat

Domanda tecnica consulenziale single-brand via Telegram

Un rivenditore scrive su Telegram una domanda consulenziale specifica su un brand (es. 'come scelgo cerniera Blum per anta da 18 kg con frontale in vetro?'). Il sistema risponde con ragionamento tecnico basato su regole + decision tree del Knowledge Tool brand.

PatternTyped Query -> Supervisor (intent=consult) -> Knowledge Tool brand
TriggerMessaggio Telegram
Durata5-12 secondi
Costo stimato~0.02 EUR/domanda
0

Ricezione messaggio

Telegram Bot API invia webhook al VPS. Il runtime conversazionale identifica l'utente via memoria persistente. Genera trace_id.

Strumenti:Telegram Bot API · Hermes Agent (o webhook custom) · Caddy · Postgres conversation_history
1

Typed Query Layer (slot filling)

Parsing slot deterministico pre-LLM. Estrae: {intent: "consult", categoria: "cerniera", filtri: {peso_anta_kg: 18, tipo_frontale: "vetro"}, testo_libero: "come scegliere", brand_hint: "blum"}. Latenza ~50ms a costo zero se i pattern matchano (caso comune); fallback a Haiku con tool_use forzato per i casi residui.

Strumenti:Parser Python: regex + dizionari + spaCy IT · fallback Claude Haiku · Langfuse
2

Supervisor classifica e instrada

Il Supervisor riceve il TypedQuery. Intent="consult" + categoria="cerniera" + brand_hint="blum" -> routing diretto al BlumKnowledge MCP. Niente PIM in questo caso (non e' filtro strutturato). Niente Mexal (non e' richiesta commerciale).

Strumenti:Claude Sonnet (Supervisor) · system prompt cached · routing deterministico · Langfuse
3

Knowledge Tool: cerca_knowledge hybrid

blum-knowledge.cerca_knowledge("come scelgo cerniera per anta vetro pesante", top_k=5, alpha=0.5). Hybrid retrieval: BM25 FTS5 nativo SQLite + cosine semantica via Reciprocal Rank Fusion. Ritorna chunks da G004 (decision tree cerniere), R007 (cerniere per ante in vetro), R009 (cerniere per ante pesanti). Match esatto su sigle KH/FH preservato dal BM25.

Strumenti:BlumKnowledge MCP · SQLite + FTS5 + cosine NumPy · RRF (k=60) · prompt caching
4

Rule Engine: applica regole tecniche

Hard rule

rule_engine.evaluate(brand="blum", prodotto={categoria: "cerniera", peso_anta_kg: 18, tipo_frontale: "vetro"}). Trigger di R009 (peso > 15 kg richiede cerniera high-load) e R007 (vetro richiede piastrina dedicata). Output strutturato con messaggi + fonte_pagina_fis.

Strumenti:Rule Engine Python · R*.md frontmatter eseguibile · Langfuse
5

Sintesi del Supervisor

Supervisor compone risposta italiana combinando: chunks narrativi del Knowledge Tool + vincoli tecnici dal Rule Engine + citazioni pagina manuale. Decision tree esplicito: "anta 18kg vetro -> serie 71B con piastrina vetro -> codice consigliato X". Niente "compatibile" generico, ragionamento consulenziale.

Strumenti:Claude Sonnet · Langfuse
6

Guardian valida output

Guardian

Il guardian verifica: codici articolo citati esistono davvero nel catalogo Blum (lookup esatto via dettaglio_codice), regole citate hanno fonte_pagina valida, no consigli di montaggio non documentati, disclaimer "in caso di dubbio consultare rivenditore" presente.

Strumenti:Claude Haiku · check codice articolo via blum-knowledge.dettaglio_codice · Langfuse
7

Aggiornamento Configuration Context (se attivo)

Se l'utente ha una sessione progetto attiva (es. configurazione cucina in corso), aggiorna ConfigurationContext aggiungendo il modulo cerniera con attributi e vincoli emessi. fonte_per_campo annotata: "moduli.cerniera.codice = BlumKnowledge.cerca_knowledge".

Strumenti:Postgres `config_context` · Langfuse
8

PII redaction + log + risposta

Presidio scansiona la conversazione e maschera PII nel trace. Conversazione salvata in conversation_history Postgres (scadenza 30 giorni). Risposta inviata via Telegram con citazioni manuale + disclaimer.

Strumenti:Presidio · Langfuse · Telegram

Flusso 3: generazione offerta commerciale

Generazione automatica di un'offerta commerciale

Il commerciale via internal tool clicca 'Genera offerta per [cliente]'. Sistema raccoglie storico, valuta credito, genera bozza con sconto, valida regole, eventualmente richiede approvazione umana per sconti alti, produce PDF, registra audit.

PatternPipeline + critic + conditional approval
TriggerClick su Appsmith
Durata auto~20 sec + eventuale approval
Costo stimato~0.10 €/offerta
0

Trigger da internal tool

Il commerciale apre l'internal tool, seleziona cliente, inserisce articoli desiderati e quantita', clicca "Genera offerta". Appsmith chiama webhook Inngest con evento commerciale/offerta.richiesta.

Strumenti:Appsmith · Inngest · Caddy · API key auth
1

Lookup cliente + storico

Workflow chiama in sequenza: gestionale-mcp.cerca_cliente(...)gestionale-mcp.storico_acquisti(cliente_id, mesi=24). Pattern visto: ordini medi, sconto medio storicamente applicato.

Strumenti:gestionale-mcp · pybreaker (circuit breaker)
2

Hard rule: verifica credito

Hard rule

Hard rule in codice: gestionale-mcp.verifica_credito(cliente_id). Fail safe: se esposizione superiore al 90% del fido, workflow si ferma e notifica responsabile credito. Nessun agente LLM puo' aggirare questa regola.

Strumenti:gestionale-mcp · regola if/else Python (Layer C) · Apprise
3

Generazione bozza offerta

L'agente compone offerta. Tool calling iterativo: lookup prezzi listino, calcolo sconto raccomandato basato su storico, calcolo totale, termini pagamento standard.

Strumenti:Claude Sonnet · prompt caching · gestionale-mcp (3-5 chiamate) · Langfuse
4

Guardian valida regole commerciali

Guardian

Il guardian verifica: sconto applicato dentro range storico (entro 5% del medio), termini pagamento standard, nessun articolo "da non vendere" (allowlist), totale corretto. Output: {ok, sconto_attuale, sconto_max_auto: 15%, richiede_approval: bool}.

Strumenti:Claude Haiku · regole hardcoded · Langfuse
5

Conditional approval gate

Approval

Branching deterministico: se sconto calcolato superiore al 15%, step.waitForEvent("offerta.approvata", timeout: "24h"). Apprise notifica responsabile commerciale via Telegram. Altrimenti auto-approve e prosegue.

Strumenti:Inngest waitForEvent · Apprise · Approval inbox custom
6

Generazione PDF offerta

gestionale-mcp.genera_pdf_offerta(dati). Genera PDF con template aziendale (WeasyPrint). Upload su MinIO bucket offerte/ con nome offerta_{trace_id}.pdf. Restituisce URL signed valido 30 giorni.

Strumenti:gestionale-mcp · WeasyPrint · MinIO · Postgres
7

Salvataggio in gestionale + audit

gestionale-mcp.salva_offerta(payload) crea record offerta nel gestionale con audit_id = trace_id. Append immutabile su audit_log: (audit_id, trace_id, decisore_umano, commerciale, sconto_applicato, totale).

Strumenti:gestionale-mcp · gestionale ERP · Postgres audit_log
8

Risposta a commerciale

Appsmith mostra "Offerta generata" con: link PDF su MinIO, link al trace Langfuse per audit, button "Invia al cliente" (che triggera flusso comm separato).

Strumenti:Appsmith · Langfuse

Flusso 4: ETL notturno catalogo prodotti

Sincronizzazione notturna del catalogo da feed produttore

Ogni notte il sistema scarica il feed BMEcat ufficiale di un produttore partner, fa parsing, diff vs DB locale, aggiorna catalogo + embeddings, valida retrieval, notifica risultato.

PatternCron deterministico (no LLM al timone)
TriggerInngest cron 0 3 * * *
Durata5-15 minuti
Costo stimato~0.30 €/notte
0

Trigger cron

Inngest scheduler fa partire il workflow alle 03:00 ogni notte. trace_id generato, batch_id univoco per il run.

Strumenti:Inngest cron
1

Download feed BMEcat

Script Python scarica il feed dal Productdata Service del produttore. Auth via API key in Infisical. Se 401/403/timeout, notifica admin via Apprise ed esce con stato failed. Se OK, file XML salvato temporaneamente.

Strumenti:Python (requests) · Infisical (secret) · Apprise · pybreaker
2

Parse XML BMEcat

Parser BMEcat estrae record articoli: codice, descrizione IT, dimensioni, immagine URL, scheda PDF URL, gerarchia categoria. Validazione schema. Statistiche del run.

Strumenti:Python (lxml) · jsonschema
3

Diff vs DB locale

Confronto sintetico hash-based con catalogo Postgres esistente. Output: (nuovi, modificati, rimossi).

Strumenti:Python · Postgres
4

Generazione embeddings

Per articoli nuovi e modificati: chiamata batch a Voyage AI (o Ollama+nomic-embed locale per privacy). Output: vettori 1024-dim. Upsert in articoli Postgres + articoli_vec pgvector.

5

Aggiornamento knowledge base

Re-indexing del wiki narrativo: per ogni articolo modificato, rigenera la "scheda narrativa" tramite agente (Claude Haiku, batch). Salva in kb con embedding aggiornato.

Strumenti:Claude Haiku · Anthropic Batch API (50% sconto) · pgvector
6

Eval automatico retrieval

Guardian

L'eval-agent campiona 10 articoli random tra quelli modificati. Per ognuno simula query tipica utente, verifica che l'articolo target sia nei top 5 risultati. Se score sotto soglia, notifica e apre issue automatico.

Strumenti:Promptfoo (o eval custom) · Langfuse · Apprise
7

Snapshot backup

WAL-G backup incrementale Postgres. Restic backup file su MinIO con retention policy 30gg locale + 90gg remoto.

Strumenti:WAL-G · Restic · MinIO (offsite copy)
8

Report giornaliero

Apprise notifica via Telegram al magazziniere e responsabile prodotto: "Catalogo aggiornato. +N articoli, ~M modifiche, -K deprecati. Eval retrieval: X%. Tempo totale: Y min."

Strumenti:Apprise · Telegram

Flusso 5: query strutturata cross-brand (Filter-then-Validate)

Query strutturata cross-brand: 'lavastoviglie 60 classe A per cliente Rossi'

Un commerciale via chat web chiede una lavastoviglie da 60 cm classe energetica A per il cliente Rossi (gia' identificato in sessione). Il sistema attiva il pattern Filter-then-Validate cross-brand: PIM filtra candidati su attributi tipizzati, Knowledge Tools dei brand validano per consulenza, Mexal arricchisce con prezzo/disponibilita' per il cliente, Promo verifica eventuali bundle attivi, Supervisor sintetizza in italiano con tre stati distinti.

PatternFilter-then-Validate cross-brand
TriggerMessaggio chat web
Durata8-15 secondi
Costo stimato~0.05 EUR/query
0

Ricezione messaggio + identificazione contesto

La chat web invia POST con cliente_id="rossi_srl" (gia' selezionato in sessione precedente). Genera trace_id propagato a tutti i livelli. Carica ConfigurationContext esistente se presente (sessione progetto cucina aperta).

Strumenti:Web app Next.js · Caddy · Postgres sessions · ConfigurationContext esistente
1

Typed Query Layer (slot filling deterministico)

Parsing slot pre-LLM. La query "lavastoviglie 60 classe A" matcha pattern noti (categoria + larghezza_cm + classe_energetica). Output tipizzato:

{
  "intent": "search",
  "categoria": "lavastoviglie",
  "filtri": {"larghezza_cm": 60, "classe_energetica": "A"},
  "contesto_progetto_ref": "sess_xyz789",
  "cliente_id": "rossi_srl"
}

Latenza ~30ms a costo zero (no LLM chiamato). Critico: "60" e' parsato come larghezza_cm, non puo' confondersi con "60 watt" o "60 db" altrove.

Strumenti:Parser Python: regex + dizionari + spaCy IT · Langfuse
2

Supervisor classifica e instrada

Supervisor riceve TypedQuery. Intent="search" + filtri tipizzati su categoria nota -> attiva pattern Filter-then-Validate cross-brand. Pianifica: PIM (filter) -> Knowledge Tools brand (validate, parallelo) -> Mexal (prezzo cliente) -> Promo (verifica). Niente sintesi LLM "intelligente": flusso deterministico.

Strumenti:Claude Sonnet (Supervisor) · routing deterministico · Langfuse
3

Filter: PIM lite cross-brand

pim.filtra_prodotti(categoria="lavastoviglie", attributi={larghezza_cm: 60, classe_energetica: "A"}, top_k=20). Query Postgres su tabella prodotti con filtro JSONB indicizzato. Schema validato contro C001 (larghezza_cm e' measurement; classe_energetica e' select con valori ammessi A-G). Output: 12 codici candidati cross-brand (5 Bosch, 4 Whirlpool, 3 BSH).

Strumenti:PIM MCP · Postgres JSONB · indici GIN · CategorySchema C001_lavastoviglie.md
4

Validate: Knowledge Tools brand in parallelo

Per ogni candidato (top 5 dopo ranking PIM), il Knowledge Tool brand corrispondente fa valida_compatibilita(prodotto, contesto) in parallelo. Il contesto include il ConfigurationContext (cucina con cassetti retrostanti). Trigger di vincolo cross-modulo X-COMPAT-001 ("lavastoviglie 60 con cassetti retrostanti -> verifica nicchia 560mm"). Output strutturato per candidato:

[
  {"codice": "SMV68N20EU", "brand": "bosch", "validation": {"status": "warn",
    "messaggio": "Richiede nicchia 560mm. Cassetti retrostanti 540mm: rischio."}},
  {"codice": "WTC36HK02EU", "brand": "whirlpool", "validation": {"status": "ok",
    "messaggio": "Profondita' 545mm, compatibile con cassetti retrostanti 540mm."}},
  ...
]
Strumenti:BoschKnowledge MCP · WhirlpoolKnowledge MCP · BSHKnowledge MCP · Rule Engine · ConfigurationContext lookup · Inngest step.run paralleli
5

Mexal lookup: prezzo cliente + disponibilita'

Per ogni candidato sopravvissuto: mexal.prezzo_per_cliente(codice, "rossi_srl") + mexal.disponibilita(codice). Ritorna prezzo netto cliente (con classe sconto applicata) + disponibilita' magazzino + lead time. Concurrency limitata ({ limit: 3 } per Mexal). Circuit breaker davanti.

Strumenti:Mexal MCP · pybreaker circuit breaker · classe sconto cliente
6

Promo MCP: bundle e target sconto

promo.promo_attive(codici=[...], cliente_id="rossi_srl") -> ritorna eventuali campagne attive sui codici candidati. promo.progresso_target_sconto("rossi_srl", codice) per ogni codice -> ritorna "il cliente Rossi ha fatturato Bosch 18.500 EUR sull'anno; prossimo target sconto a 20.000 EUR; aggiungere SMV68N20EU per 1.800 EUR lo porterebbe oltre soglia attivando +3% retroattivo".

Strumenti:Promo MCP · DB promo Arco · `progresso_target_sconto`
7

Sintesi Supervisor con tre stati distinti

Il Supervisor compone la risposta combinando: filter PIM + validate Knowledge Tools + prezzo Mexal + promo. Pattern: tre stati distinti, mai mescolati:

  • Consigliato: WhirlpoolKnowledge approva attivamente + prezzo cliente competitivo + nessun warning. Mostrato in primo piano.
  • Compatibile: PIM ok + Knowledge non ha warn ma non ha approvato attivamente. Secondario.
  • Sconsigliato: PIM ok ma Knowledge segnala problema cross-modulo. Mostrato comunque con motivazione esplicita: "compatibile per filtro, ma sconsigliato perche'...".

Plus suggerimento commerciale dal Promo: "se aggiungi SMV68N20EU sblocchi target sconto +3%".

Strumenti:Claude Sonnet · template Markdown · Langfuse
8

Guardian valida sintesi

Guardian

Il guardian verifica: codici citati esistono nel PIM (lookup esatto), vincoli citati hanno rule_id e fonte valida, distinzione tre stati rispettata, nessun prezzo inventato (tutti vengono da Mexal lookup), suggerimento promo cita rule_id originale. Se KO, rigenerazione.

Strumenti:Claude Haiku · check codici via PIM.attributi_per_codice · Langfuse
9

Aggiornamento Configuration Context

Se l'utente seleziona uno dei prodotti (turn successivo), il modulo si aggiunge al ConfigurationContext con tracciabilita' completa (fonte_per_campo: brand=PIM, codice=user_input, prezzo=Mexal, vincoli=RuleEngine). Audit log append-only.

Strumenti:Postgres `config_context` · audit log immutabile
10

PII redaction + risposta

Presidio maschera nome cliente Rossi (PII) nei log Langfuse. Risposta strutturata inviata alla chat web con cards per ognuno dei tre stati + pulsante "Aggiungi al progetto cucina" sul consigliato.

Strumenti:Presidio · Langfuse · Web app

Diagramma end-to-end completo

Vista panoramica di come tutti i pezzi si parlano. Un singolo schema mostra i flussi possibili, gli strumenti per layer, le frecce di dipendenza, le sezioni cross-cutting (osservabilita' + safety + human).


=================================================================
              INPUT (canali utente)
=================================================================
[Telegram] [WhatsApp] [Slack] [Web Next.js] [Webhook ERP] [Cron]
   |          |        |          |             |          |
   +----------+--------+----------+-------------+----------+
                                |
=================================================================
              EDGE / NETWORK / SECURITY
=================================================================
 Cloudflare      DDoS, WAF, rate limiting front
      |
      v
 Caddy (VPS)     TLS automatico, reverse proxy, routing
      |
      v
 Auth layer      API key validation, JWT, multi-tenant header
                                |
=================================================================
 LIVELLO 1 — TYPED QUERY LAYER (slot filling pre-LLM)
=================================================================
 Parser deterministico: regex + dizionari + spaCy IT
 Fallback Haiku con tool_use forzato per casi residui
 Output: TypedQuery {intent, categoria, filtri tipizzati, ...}
                                |
=================================================================
 LIVELLO 2 — SUPERVISOR (Filter-then-Validate orchestrator)
=================================================================
 Claude Sonnet con routing deterministico per intent
 Pattern: PIM filtra -> Knowledge Tool valida -> sintesi
 3 stati distinti: compatibile / consigliato / sconsigliato
                                |
=================================================================
      ORCHESTRATOR — workflow durabili (Inngest)
=================================================================
step.run("filter-pim")
step.run("validate-knowledge")    ogni step ATOMICO,
step.run("mexal-prezzo")           resilient, retry,
step.run("rule-engine-eval")       loggato, ispezionabile
step.run("synth-supervisor")
step.run("guardian-valida")
step.waitForEvent("approvazione")  (per flussi commerciali)

cron schedules · event listeners · approval gates · retry policy
                                |
=================================================================
 LIVELLO 3 — FONTI ETEROGENEE (federate selettivamente)
=================================================================

3A. KNOWLEDGE TOOLS    3B. PIM lite      3C. RULE       3D. MEXAL +
  per brand              singleton         ENGINE         PROMO MCP
  (constellation)        Postgres          singleton      singleton
                         JSONB             evaluator
  BlumKnowledge          schema in         Python         prezzo,
  BoschKnowledge         MD-Karpathy       legge da       disponib,
  WhirlpoolKnowledge     C*.md             R*.md          promo,
  BSHKnowledge                             frontmatter    bundle,
                                           eseguibile     target sconto
  cerca_knowledge        filtra(           valuta
  dettaglio_codice         categoria,        condizione
  valida_compatib          attributi)        DSL
  + tool dominio
  SQLite + FTS5 +
  cosine + RRF
                                |
=================================================================
 LIVELLO 4 — CONFIGURATION CONTEXT (stato persistito tipizzato)
=================================================================
 {progetto, moduli, vincoli_attivi, fonte_per_campo, ...}
 Postgres JSONB. Cresce ad ogni step. fonte_per_campo annota chi
 ha messo cosa: user_input | PIM | BrandKnowledge | Mexal | RuleEngine
                                |
=================================================================
 LIVELLO 5 — INFRASTRUTTURA / BACKEND SYSTEMS
=================================================================
[ ERP Mexal ]  [ Postgres + pgvector ]  [ MinIO (S3) ]
                un solo DB:
                - dati Langfuse
                - state Inngest
                - pgvector (Configuration Context, audit log)
                - PIM lite (JSONB)
                - conversation history

=================================================================
 CROSS-CUTTING — osservabilita' (sempre attivo, ovunque)
=================================================================
OpenTelemetry GenAI (tessuto connettivo trace cross-process)
     |
     v
Langfuse · Sentry · UptimeRobot · Loki (P3) · Metabase (P2)

trace_id propagato in OGNI livello
  trace_id = inngest_run_id = audit_id = configuration_context.id
  -> un click ti porta dal record di business al log completo

=================================================================
 CROSS-CUTTING — safety (sempre attivo, ovunque)
=================================================================
Layer A: Orchestrator strutturale (Inngest + Supervisor deterministico)
Layer B: Critic / Guardian agent (Claude Haiku)
Layer C: Hard rules in codice (if/else Python)
        budget cap · allowlist · approval gate forzato
        rate limiting · circuit breaker (pybreaker)
Layer D: Rule Engine deterministico (vincoli tecnici prodotto)
PII redaction (Microsoft Presidio) prima di ogni log
Secret management (Infisical) per credenziali
Audit log immutabile (Postgres append-only)
Kill switch (Unleash feature flag)

=================================================================
 CROSS-CUTTING — human in the loop
=================================================================
Apprise (Telegram/email/Teams)
Approval inbox custom (Next.js)
Appsmith (internal tools)
Metabase (dashboard manageriali)
Outline (wiki interna runbook + ADR)
Editor wiki Karpathy (MD curato per Knowledge / Schema PIM / Rule)

Come leggere e applicare

I cinque flussi sono esempi rappresentativi. La realta' sara' 10-20 flussi entro il primo anno, ognuno una variazione di questi pattern. Non implementarli "uno alla volta come da copione", implementare i flussi che risolvono i dolori reali, in qualunque ordine.

Tra i cinque mostrati, il Flusso 4 (ETL notturno) e' il piu' semplice da costruire per primo: deterministico, senza utenti, basso rischio, alto valore percepito. E' un ottimo "primo workflow Inngest" della propria storia.

Il Flusso 5 (cross-brand strutturato) e' invece il piu' rappresentativo del valore aggiunto del modello v2.0: senza Filter-then-Validate (PIM filtra + Knowledge Tools validano + Mexal arricchisce + Promo suggerisce), una query come "lavastoviglie 60 classe A" cadrebbe in pattern allucinatori (vector search confonde "60 cm" con "60 watt"; LLM inventa modelli plausibili; nessun vincolo cross-modulo emerge). Costruire il Flusso 5 e' la prova che il sistema non e' "un chatbot search", ma un CPQ con consulenza tecnica.

I cinque flussi condividono il 70% dell'infrastruttura: stesso Inngest, stesso Postgres+pgvector, stessi MCP server, stesso Langfuse. Aggiungere il sesto flusso costa molto meno del primo. E' l'effetto compounding dell'investimento iniziale.

"Mese 2", "Mese 4-6" sono orizzonti di pianificazione, non scadenze. Se al mese 1 si sente il dolore della mancata PII redaction, si anticipa Presidio. Se al mese 6 non si ha ancora bisogno di Authelia, si rimanda. Il vero principio e': aggiungere quando si sente il dolore, non quando il piano dice di farlo.

Per la mappa architetturale completa, i 4 contratti tipizzati, i nove punti aperti, vedi Agentizzare una PMI: stack, architettura, strumenti v2.0. Per il pattern Karpathy del livello knowledge editabile (wiki narrativi brand + R*.md regole + C*.md schema PIM), vedi Wiki narrativo AI-maintained.

Registro aggiornamenti

  1. v1.3

    Allineamento di coerenza tooling con master v2.1. Audit interno ha identificato strumenti effettivamente in uso in BlumCat reale (sentence-transformers, pdfplumber, PyMuPDF, SQLite per Knowledge Tools small) che mancavano dalla timeline del Data layer (cella Mese 1). Aggiunti come P1/P2 espliciti. Postgres+pgvector spostato a Mese 2 (introduzione nel migration path v2.0, non al day 1 di BlumCat). Voyage AI e Ollama riclassificati come "alternative" per i Mesi 4-6 (opzionali se serve). La timeline ora riflette correttamente l'evoluzione: BlumCat oggi usa SQLite + sentence-transformers locale, l'arcocat futuro introduce Postgres+pgvector quando arriva il PIM cross-brand.

  2. v1.2

    Allineamento allo stack v2.0. Aggiunto Flusso 5: query strutturata cross-brand ("lavastoviglie 60 classe A per cliente Rossi") che mostra end-to-end il pattern Filter-then-Validate: Typed Query Layer slot filling -> Supervisor routing -> PIM filtra candidati cross-brand -> Knowledge Tools brand validano in parallelo (con vincoli cross-modulo via Rule Engine) -> Mexal MCP arricchisce con prezzo cliente -> Promo MCP suggerisce target sconto -> sintesi Supervisor con tre stati distinti (compatibile / consigliato / sconsigliato). Flusso 2 (chat tecnica) riformulato per usare Knowledge Tools brand-specifici (Typed Query Layer, BlumKnowledge MCP con hybrid retrieval BM25 FTS5 + cosine + RRF, Rule Engine per regole tecniche, ConfigurationContext aggiornato). Diagramma end-to-end rivisto con i 5 livelli v2.0: Typed Query Layer + Supervisor + Inngest orchestrator + Fonti eterogenee (Knowledge / PIM / Rule Engine / Mexal+Promo) + Configuration Context + Backend systems. Aggiornato cross-cutting "safety" con quarto layer (Rule Engine deterministico per vincoli tecnici prodotto, separato da safety LLM).

  3. v1.1

    Aggiunto Callout in apertura che cita esplicitamente il "Modello di esecuzione" introdotto in v1.2 dello studio principale. I quattro flussi descritti rispettavano gia' implicitamente quel modello: il cross-link rende esplicito il legame e fa da promemoria a chi costruisca un nuovo flusso in futuro.

  4. v1.0

    Prima stesura. Timeline grafica con 9 layer × 5 fasi temporali, quattro flussi reali end-to-end (onboarding cliente, chat tecnica, generazione offerta, ETL notturno catalogo), diagramma complessivo con cross-cutting su osservabilita', safety e human-in-the-loop.