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.
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.
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.
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().
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.
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.
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.
Validazione Guardian agent
GuardianUn 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.
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].
Approval gate umano
Approvalstep.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.
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.
Notifica conclusione
Apprise notifica al commerciale "Email inviata a [Cliente]" con link al trace Langfuse per audit immediato.
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.
Ricezione messaggio
Telegram Bot API invia webhook al VPS. Il runtime conversazionale identifica l'utente via memoria persistente. Genera trace_id.
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.
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).
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.
Rule Engine: applica regole tecniche
Hard rulerule_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.
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.
Guardian valida output
GuardianIl 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.
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".
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.
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.
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.
Hard rule: verifica credito
Hard ruleHard 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.
Generazione bozza offerta
L'agente compone offerta. Tool calling iterativo: lookup prezzi listino, calcolo sconto raccomandato basato su storico, calcolo totale, termini pagamento standard.
Guardian valida regole commerciali
GuardianIl 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}.
Conditional approval gate
ApprovalBranching deterministico: se sconto calcolato superiore al 15%, step.waitForEvent("offerta.approvata", timeout: "24h"). Apprise notifica responsabile commerciale via Telegram. Altrimenti auto-approve e prosegue.
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.
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).
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.
Trigger cron
Inngest scheduler fa partire il workflow alle 03:00 ogni notte. trace_id generato, batch_id univoco per il run.
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.
Parse XML BMEcat
Parser BMEcat estrae record articoli: codice, descrizione IT, dimensioni, immagine URL, scheda PDF URL, gerarchia categoria. Validazione schema. Statistiche del run.
Diff vs DB locale
Confronto sintetico hash-based con catalogo Postgres esistente. Output: (nuovi, modificati, rimossi).
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.
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.
Eval automatico retrieval
GuardianL'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.
Snapshot backup
WAL-G backup incrementale Postgres. Restic backup file su MinIO con retention policy 30gg locale + 90gg remoto.
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."
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.
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).
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.
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.
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).
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."}},
...
]
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.
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".
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%".
Guardian valida sintesi
GuardianIl 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.
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.
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
- 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.
- 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).
- 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.
- 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.