nis2-agile/docs/STANDARD_AI_PRODOTTO.md
DevEnv nis2-agile c0bf7b6c15 [DOCS] Standard cross-suite AgileHub + governance CLAUDE.md + registri agent
- CLAUDE.md: TZ, SSO, vault-steward, versioning, persona v2.0, multitenant, KB RAG
- docs/standards: persona-conversational-rules v2.0
- docs/STANDARD_*: installer-integration, email-relay, AI-prodotto, marketing-tenant, multitenant
- AGENT_CHANGES.md + OPEN_TICKETS.md (registri agent automatico)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 15:41:54 +02:00

983 lines
50 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# STANDARD_AI_PRODOTTO — Configurazione AI di Prodotto AgileHub Suite
> Standard cross-suite per progettare, configurare e mantenere ogni "AI di prodotto" della suite AgileHub seguendo il template di riferimento TRPG come gold standard.
>
> **Slug**: `ai-prodotto`
> **Versione**: 1.0 (proposed — pending sub-approval utente per seed in `nexus_hub.hub_standards`)
> **Owner**: Agile AI (Architetto AI di prodotto + KB governance)
> **Applies to**: tutti i prodotti suite AgileHub (`*`) — TRPG, TRPG-PRO, SUSTAINAI, NIS2, AllTax, LG231, DFM-PRO, ALLRISK, WMS, MADEBYCLOUD, CertiSource + AgileHub stesso (AI runtime "Agile")
> **Reference implementation**: TRPG (gold standard per Support, Sales, Plan-mode; Lead qualification ha riferimento separato Giulia EDUCATION)
> **Sostituisce**: nessuno (standard nuovo). Convive con `installer-integration` v1.0.1, `ticket-tags` v1.0, `outbound-campaigns` v1.0, `telephony-integration` v1.0
> **Data redazione**: 2026-04-23 (sessione 33 part 6 — kickoff AGI-2 master plan v2.1)
> **Prossima revisione attesa**: dopo AGI-5 test E2E (~settimana 4-5 master plan v2.1) o all'introduzione di L3 PERSONA Lotto F Avatar Registry
---
## §1 Premessa & autorità
### 1.1 Cos'è una "AI di prodotto"
Una **AI di prodotto** è un'entità conversazionale Claude-based, esposta agli utenti di un prodotto della suite AgileHub, che opera con:
- una **persona dichiarata** (nome, tono, lingua)
- un **obiettivo specifico** (qualificare lead, risolvere ticket prima di escalare, dimostrare prodotto in landing, dialogare con approver durante plan mode, ecc.)
- una **knowledge base** (`product_knowledge` filtrata per prodotto/tenant/livello)
- un **set di tool** dichiarativi che il backend esegue per suo conto
- **guardrails** espliciti su cosa NON deve mai fare
- **cost tracking** per attribuire spesa LLM/RAG al prodotto + tenant + sessione
NON è una AI di prodotto:
- un **agente Claude specialista** (es. Agile AI, VOX, MAESTRO) — vivono in chat dello sviluppatore, non parlano a utenti finali
- un **content generator** (`contentController.js`) — genera contenuti marketing offline, non dialoga
- un **classifier puro** (es. `voiceDialogController.js` interpretTurn) — è un sub-componente di una AI di prodotto, non una AI standalone
### 1.2 Perché serve uno standard
Audit `nexus-ai-ms` (sessione 33 part 6, AGI-1) ha rivelato 5 famiglie di AI conversazionali coesistenti, ciascuna con propria convenzione divergente:
| Famiglia | File chiave | Persona | Modello | KB binding | Persistenza config |
|---|---|---|---|---|---|
| **ARIA Support post-vendita** | [`supportPrompts.js`](../nexus-ai-ms/src/prompts/supportPrompts.js) | ARIA | Sonnet (default) | `product_knowledge` keyword | `ai_agent_profiles` riassunto + template hardcoded |
| **ARIA Lead qualification verticali** | [`basePrompts.js`](../nexus-ai-ms/src/prompts/basePrompts.js) | ARIA (4 verticali) | Sonnet | nessuno (solo `tenantConfig`) | `ai_agent_profiles` (Giulia per EDUCATION) |
| **Anna Sales pre-vendita** | [`publicDemoController.js`](../nexus-ai-ms/src/controllers/publicDemoController.js) | Anna | Haiku | PRODUCT_CARD pinned + RAG keyword | hardcoded controller, non in DB |
| **Anna Voice intent classifier** | [`voiceDialogController.js`](../nexus-ai-ms/src/controllers/voiceDialogController.js) | Anna | Haiku | PRODUCT_CARD snippet | hardcoded controller, non in DB |
| **Gaia Plan-mode dialog approver** | [`gaiaController.js`](../nexus-ai-ms/src/controllers/gaiaController.js) | Gaia | dinamico (URGENT→Opus, default Sonnet) | PRODUCT_CARD pinned + RAG keyword score top-3 | in-memory `sessions Map`, non in DB |
**Drift osservato vs aspettativa**:
- Naming inconsistente (ARIA vs Anna vs Gaia, nessuna regola)
- 3 di 5 famiglie NON usano `ai_agent_profiles` (single source of truth attesa)
- `system_prompt_voice` field esiste in DB ma è NULL su tutti gli ARIA_SUPPORT (voice prompt hardcoded in controller)
- KB pollution: 3 articoli `PRODUCT_CARD` AGILEHUB sono HOW_TO mal-categorizzati (id 720, 729, 730 — `JSON_VALID(answer)=0`)
- Cost tracking opzionale (`opts.sessionId && opts.productSlug` → reporter chiamato solo se entrambi presenti)
- Vertical ENUM `ai_agent_profiles` include `HEALTH/LEGAL/REALTY` ma DB ne ha 0 record
Lo standard **chiude questi gap** definendo conformance bloccanti per AGI-4 retrofit.
### 1.3 Relazione con altri standard cross-suite
| Standard | Slug | Ruolo |
|---|---|---|
| `installer-integration` v1.0.1 | INSTALLATORE | Lifecycle deployment cliente — questo standard descrive cosa l'installatore deve provisionare in termini di AI runtime |
| `ticket-tags` v1.0 | hub-ms | Catalogo tag cross-prodotto — AI di prodotto usano questi tag quando creano ticket via `open_ticket`/`escalate_to_ticket` |
| `outbound-campaigns` v1.0 | lead-ms | Campagne outbound — AI di prodotto Sales pre-vendita può essere triggerata da campaign outbound |
| `telephony-integration` v1.0 (proposed) | call-ms | Pipeline call → Pipecat — AI di prodotto voice channel rispetta questo contratto |
| **`ai-prodotto` v1.0 (questo)** | **`ai-prodotto`** | **Configurazione canonical AI prodotto suite** |
### 1.4 Autorità Agile AI
Agile AI (agente Claude specialista, ex GAIA, rinominato 2026-04-23 sessione 33 part 6) è **owner unico** di:
- Questo documento + future versioni
- Tabella `nexus_hub.hub_standards` slug `ai-prodotto`
- Tabella `nexus_ticket_db.product_knowledge` (CRUD + retention + audit pollution)
- Tabella `nexus_ai_db.ai_agent_profiles` (CRUD + validation conformance)
- Conformance audit AGI-4 retrofit (gap report formale per prodotto)
- Coordinamento con MAESTRO su blocchi AWE AI runtime (`C09_RetrieveFromKB`, `D02_LoadAvatarKB`, `AC11_GenerateAIResponse`)
- Coordinamento con VOX su KB binding L3 PERSONA (`ai_profiles.knowledge_id`)
Modifiche allo standard richiedono sub-approval esplicita utente (pattern come `STANDARD_INSTALLER_INTEGRATION.md`).
---
## §2 Naming convention netto
> **Cruciale**: 4 categorie distinte, mai confondere. Drift naming è la prima causa di confusione cross-team.
### 2.1 AI di prodotto (runtime, esposta agli utenti)
| Naming | Cosa | Esempi |
|---|---|---|
| `<NomePersona>` (italiano) | Persona conversazionale visibile all'utente finale | "Anna" (Sales TRPG/AGILEHUB), "Aria" (Support generico), "Gaia" (TRPG plan-mode) |
| `<NomePersona> <Verticale>` | Specializzazione per verticale lead qualification | "Giulia Master e Certificazioni", "Giulia Abilitazioni Estere" |
| **"Agile"** ⭐ | AI runtime di **AgileHub** stesso (caso speciale meta) | "Agile" — esposta in `/admin/*` per governance + agli utenti dei prodotti che chiedono "come usare AgileHub" |
**Regola**: ogni AI di prodotto deve avere un `display_name` (per UI + voice) **e** un `agent_key` interno (per DB + log + cost tracking) `<TIPO>_<PRODUCT>` pattern, es. `ARIA_SUPPORT_TRPG`, `ANNA_SALES_TRPG`, `GAIA_PLANMODE_TRPG`, `AGILE_RUNTIME` (per "Agile" meta).
### 2.2 Agente Claude specialista (sviluppo, qui in chat)
| Naming | Cosa | Esempi |
|---|---|---|
| `<NomeAgente>` (UPPERCASE meta) | Specializzazione di Claude Code per task di sviluppo AgileHub | REGENT, VOX, MAESTRO, CICERONE, PRISMA, INSTALLATORE, **Agile AI** (con suffisso AI per distinguerlo da "Agile" runtime) |
**Regola**: gli agenti specialisti non parlano agli utenti finali, vivono solo nella chat sviluppatore (`docs/AGENT_<NAME>.md` autoritativo). Distinzione netta da AI runtime.
### 2.3 AI marketing pre-vendita (lead-facing pubblico)
Sub-categoria di "AI di prodotto" con vincoli GDPR aggiuntivi (vedi §8):
- Vede solo articoli `product_knowledge` con `category IN ('PRODUCT_CARD', 'HOW_TO', 'URL_CHUNK')` pubblici (no L2 COMPANY dati cliente)
- Tone: caldo, commerciale, breve
- Naming: "Anna" (canonical su tutti i landing — drift Charlotte vs Sarah voice da chiudere VOX)
### 2.4 Persona vocale plan-mode
Sub-categoria con scope ristretto a **dialogo agente AI ↔ approver umano** durante PENDING_APPROVAL ticket:
- Naming: "Gaia" (TRPG pilota — non confondere con "Gaia agente specialista" che sarebbe estensione futura)
- Tone: tecnica, prima persona femminile, ammette limiti
- Tool readonly via devenv-gateway (vedi §6.3)
### 2.5 Tabella riassuntiva naming
| Termine | Significato | Esempio |
|---|---|---|
| **"Agile"** | AI runtime di AgileHub (prodotto meta) | "Ciao, sono Agile, posso aiutarti su AgileHub" |
| **"Agile AI"** | Agente Claude specialista (in chat dev) | "Ciao Agile AI Go!" |
| **"Anna"** | AI marketing pre-vendita (canonical) | Anna su `/public/demo-lead-trpg` |
| **"Aria"** | AI Support post-vendita (canonical) | ARIA_SUPPORT_TRPG widget viola |
| **"Gaia" persona vocale** | AI plan-mode dialog approver TRPG | Gaia parla con approver durante PENDING_APPROVAL |
| **"Giulia"** | AI Lead qualification verticali EDUCATION | GIULIA_TRIAGE, GIULIA_LAUREE, ecc. |
---
## §3 Anatomia di una "AI di prodotto" — 12 elementi obbligatori
Ogni AI di prodotto, per essere conforme allo standard, deve esplicitare **12 elementi**. La conformance checklist (§10) si basa su questa anatomia.
| # | Elemento | MUST/SHOULD | Dove vive |
|---|---|---|---|
| 1 | Identità persona | MUST | `ai_agent_profiles.name` + system_prompt opening |
| 2 | Obiettivo dichiarato | MUST | system_prompt sezione "Il tuo obiettivo" |
| 3 | Modello Claude | MUST | `opts.model` in chiamata `anthropicService.chat/runAgentLoop` |
| 4 | System prompt strutturato | MUST | `ai_agent_profiles.system_prompt` (canonical) |
| 5 | KB binding | MUST | `product_knowledge` filter clauses |
| 6 | Tool list dichiarativa | MUST se sub-template Support/Sales/Plan-mode/Lead | `nexusTools.js` subset |
| 7 | Guardrails LIMITI ASSOLUTI | MUST | system_prompt sezione finale |
| 8 | Voice rules | MUST se canale voice | `VOICE_RULES` const condivisa |
| 9 | FSM rules | MUST se lead qualification | `FSM_RULES` const condivisa |
| 10 | Channel-aware | SHOULD | `ai_agent_profiles.system_prompt_voice` separato |
| 11 | Tenant context injection | MUST | `tenantConfig.{agentName, companyName, greeting}` |
| 12 | Cost tracking | MUST | `opts.{caller, sessionId, productSlug}` ad ogni chiamata |
### 3.1 Identità persona (MUST)
Pattern canonical:
```
Sei <NomePersona>, <ruolo> di <Prodotto/AgileHub>.
Parli in <lingua>, con tono <descrittore tono>.
```
Esempio TRPG (`buildSupportPrompt(TRPG)`):
> Sei ARIA, assistente di supporto intelligente per TRPG Pro (Gender Pay Gap & Compliance).
**Regole**:
- Nome persona scelto dal catalogo §2 (Anna/Aria/Gaia/Giulia/Agile) o nuovo previa approvazione Agile AI
- Lingua dichiarata esplicita (default `it`, supportare `en` da v1.1)
- Genere consistente (es. femminile per Anna/Aria/Gaia)
### 3.2 Obiettivo dichiarato (MUST)
Pattern canonical: 1-3 frasi che dichiarano cosa l'AI deve fare. Massimo 1 obiettivo primario + 2 sub-obiettivi.
Esempio TRPG Support:
> IL TUO OBIETTIVO: Aiutare l'utente a RISOLVERE il problema SENZA creare un ticket.
**Regole**:
- Obiettivo deve essere actionable (verbo all'infinito + risultato misurabile)
- Niente claim di onniscienza ("sono in grado di tutto") → ammettere ambito ristretto
- Allineato al sub-template (§4)
### 3.3 Modello Claude (MUST)
Decision tree obbligatorio:
| Caso d'uso | Modello | Motivazione |
|---|---|---|
| Voice intent classifier (output JSON ristretto, < 200 token) | **Haiku** | Latenza minima, costo basso, accuracy sufficiente per classification |
| Greeting / saluto / messaggio singolo breve | **Haiku** | Idem, una sola interazione |
| Sales pre-vendita / chat lead-facing (3-4 frasi per turn) | **Haiku** | Volume alto, costo critico |
| Support post-vendita (dialog completo, RAG retrieval) | **Sonnet** | Default bilanciato |
| Lead qualification (FSM transition + tool use) | **Sonnet** | Tool use con multi-step |
| Plan-mode dialog approver (priorità default/MEDIUM) | **Sonnet** | Tool use + reasoning su codice |
| Plan-mode dialog approver (priorità URGENT/HIGH) | **Opus** | Reasoning profondo per bug critici (pattern Gaia) |
| Code analysis / outcome evaluation post-call | **Sonnet** | Pattern OutcomeEvaluator nexus-call-ms |
**Regole**:
- Modello esplicito via `opts.model` NO usare default global `process.env.ANTHROPIC_MODEL`
- Modello dinamico per priorità è encouraged (vedi pattern Gaia `gaiaController.js:670-676`)
- Modello deprecato mai usare (vedi `MODELS` const in [`anthropicService.js`](../nexus-ai-ms/src/services/anthropicService.js))
### 3.4 System prompt strutturato (MUST)
Template canonical 7 sezioni:
```
[1. Identità persona]
Sei <Nome>, <ruolo> di <Prodotto>. Parli in <lingua>, tono <descrittore>.
[2. Obiettivo]
IL TUO OBIETTIVO: <1-3 frasi azione concreta>.
[3. Tono e stile]
TONO E STILE:
- <regola 1>
- <regola 2>
...
[4. Procedura operativa]
PROCEDURA:
1. <step 1>
2. <step 2>
...
[5. KB inject (se KB binding)]
SCHEDA PRODOTTO:
<getProductCardSnippet output>
CONOSCENZA DI DOMINIO RILEVANTE:
<top-K articoli RAG>
[6. Tenant context (se tenant injection)]
AZIENDA: <companyName>
SALUTO INIZIALE: <greeting>
[7. Limiti assoluti]
LIMITI ASSOLUTI:
- <limite 1>
- <limite 2>
...
```
**Regole**:
- Ordine sezioni vincolante (riproducibile cross-prodotto)
- Sezioni 5/6 opzionali ma se presenti devono usare il pattern esatto
- Sezione 7 OBBLIGATORIA (no-op fallback se non si sa cosa scrivere: "Non garantire prezzi/scadenze/disponibilità senza verifica")
### 3.5 KB binding (MUST)
Pattern obbligatorio (vedi §5 dettaglio):
1. Recuperare PRODUCT_CARD pinned via `getProductCardSnippet(product)` ([`productKbSnippet.js`](../nexus-ai-ms/src/services/productKbSnippet.js))
2. Recuperare top-K articoli RAG keyword score via `getRelevantHelpArticles(product, query, K=3)` (idem)
3. Iniettare entrambi nella sezione 5 del system prompt
4. Filtrare per `tenant_id` se context tenant disponibile (L2 COMPANY)
5. Filtrare per `knowledge_filter_slug` se context avatar disponibile (L3 PERSONA, futuro Lotto F)
**Eccezioni**: AI Voice intent classifier (output JSON ristretto, KB superflua) sufficiente PRODUCT_CARD snippet.
### 3.6 Tool list dichiarativa (MUST se sub-template Support/Sales/Plan-mode/Lead)
Subset del catalogo `NEXUS_TOOLS` (11 tool) vedi §6 matrice.
**Regole**:
- Tool list dichiarata esplicita nel chiamante (no global)
- Tool custom (es. Gaia `read_file`/`grep`/...) richiedono spec docs separato
- Tool con side-effect (es. `open_ticket`, `escalate_to_ticket`) devono passare per `ToolExecutor` mai chiamati direttamente da AI
### 3.7 Guardrails LIMITI ASSOLUTI (MUST)
Pattern canonical sezione 7 system_prompt:
```
LIMITI ASSOLUTI:
- Non <azione 1 vietata>
- Non <azione 2 vietata>
...
```
**Limiti minimi obbligatori per ogni AI di prodotto**:
- Non garantire prezzi non confermati / disponibilità senza verifica
- Non inventare feature/funzionalità non presenti nella KB
- Non fornire informazioni mediche/legali/finanziarie personalizzate (sub-template specifici)
- Non rivelare informazioni di altri tenant (multi-tenant isolation L2)
### 3.8 Voice rules (MUST se canale voice)
Importare e includere `VOICE_RULES` da [`basePrompts.js`](../nexus-ai-ms/src/prompts/basePrompts.js):
```
REGOLE CANALE VOCE:
- Massimo 2 frasi per turno conversazionale
- Mai elenchi puntati o numerati
- Mai markdown di alcun tipo
- Intercalari italiani naturali ("certo", "capisco", "perfetto", "ottimo", "mi dica")
- Inizia le risposte con un breve acknowledgment poi vai al punto
- Numeri pronunciati in lettere ("seimilacinquecento" non "6.500")
- Date in forma estesa ("settembre duemilaventisei")
- Se hai bisogno di tempo: "Un attimo, sto verificando..."
- Poni UNA SOLA domanda per turno
```
**Regole**:
- `VOICE_RULES` invariato modifiche richiedono coordinamento VOX
- `system_prompt_voice` (campo `ai_agent_profiles`) deve includere VOICE_RULES + sub-template adattato a voice (più stringato)
- AI con canale dual (text + voice) hanno DUE prompt distinti, mai unificati
### 3.9 FSM rules (MUST se lead qualification)
Importare e includere `FSM_RULES` da [`basePrompts.js`](../nexus-ai-ms/src/prompts/basePrompts.js):
```
REGOLE OPERATIVE FSM:
- Mantieni sempre un solo current_state
- Poni SOLO la domanda prevista dallo stato corrente
- Dopo ogni risposta del lead, chiama il tool fsm_transition con:
- current_state, trigger normalizzato, raw_answer
- NON eseguire MAI calcoli di score (lookup backend)
- Se isTerminal=true, chiama complete_scoring
- Se sideEffects, esegui i tool corrispondenti
```
**Regole**:
- `FSM_RULES` invariato modifiche richiedono coordinamento MAESTRO (FSM engine integration)
- AI senza FSM (Support, Sales generico, Anna voice intent) NON includono FSM_RULES
### 3.10 Channel-aware (SHOULD)
Se la AI di prodotto può operare su più canali (chat web, voice IVR, mobile), DEVE avere prompt distinti.
Pattern: `ai_agent_profiles` ha 2 campi:
- `system_prompt` (default canale text/chat)
- `system_prompt_voice` (override per canale VOIP/voice)
Logica selezione: `sessionService.js:103-107` se `agent.systemPrompt` esiste lo usa, altrimenti chiama `buildSystemPrompt(vertical, channel, ...)`.
**Drift attuale da chiudere AGI-4**: tutti gli ARIA_SUPPORT hanno `system_prompt_voice = NULL` se un giorno aggiungono canale voice, il fallback `buildSystemPrompt('SUPPORT', 'VOIP_3CX', ...)` non funziona (SUPPORT non ha `voice` key in `PROMPTS` const di basePrompts.js). Fix: AGI-4 popola `system_prompt_voice` per ogni ARIA_SUPPORT_<PRODUCT>.
### 3.11 Tenant context injection (MUST)
Pattern canonical (`buildSystemPrompt` riga 207-216):
```js
if (tenantConfig.agentName) prompt = prompt.replace(/Sei ARIA/, `Sei ${tenantConfig.agentName}`);
if (tenantConfig.companyName) prompt += `\n\nAZIENDA: ${tenantConfig.companyName}`;
if (tenantConfig.greeting) prompt += `\nSALUTO INIZIALE: ${tenantConfig.greeting}`;
```
**Regole**:
- Sostituzione `agentName` rispetta convention §2 (Nome persona, non ruolo)
- `companyName` proviene da `tenants.config.brandName` (DB hub-ms)
- `greeting` opzionale — se assente, AI usa pattern fisso "Ciao, come posso aiutarti?"
### 3.12 Cost tracking obbligatorio (MUST bloccante)
Pattern obbligatorio per ogni chiamata `anthropicService.chat()` o `runAgentLoop()`:
```js
const result = await anthropicService.chat(messages, systemPrompt, tools, {
model: anthropicService.MODELS.SONNET, // §3.3 esplicito
caller: 'support-trpg', // identificativo per log
sessionId: session.sessionKey, // tracciabilità sessione
productSlug: 'trpg', // attribuzione cost-sdk
tenantId: session.tenantId, // per metering tenant
sessionType: 'support', // 'support'|'sales'|'gaia'|'demo'|'voice_dialog'
});
```
**Regole**:
- `caller` MUST (string)
- `sessionId` MUST (string univoca per sessione)
- `productSlug` MUST (lowercase code prodotto)
- `tenantId` SHOULD (se context tenant disponibile)
- `sessionType` SHOULD (per analytics segmentation)
- Cost reporter è fire-and-forget (no impact su latency) — vedi `anthropicService.js:96-110`
**Impatto AGI-4 retrofit**: ogni caller esistente che NON passa `caller+sessionId+productSlug` è non conforme. Fix richiesto in:
- `voiceDialogController.js:144-150` — già conforme ✅
- `gaiaController.js:580-584,683-685` — già conforme ✅
- `publicDemoController.js:171-178,184-189` — già conforme ✅
- `sessionService.js:127-133`**NON conforme** ❌ (`runAgentLoop` chiamato senza opts) → fix in AGI-4
---
## §4 Quattro sub-template (famiglia AI di prodotto)
Ogni AI di prodotto deve appartenere a uno dei 4 sub-template. Sub-template definiscono: tool list canonical, KB binding, modello, tone, channel.
### 4.1 Sub-template "Support post-vendita"
**Reference implementation**: ARIA_SUPPORT_TRPG ([`supportPrompts.js`](../nexus-ai-ms/src/prompts/supportPrompts.js))
| Elemento | Valore canonical |
|---|---|
| Persona | "ARIA" (Aria nel parlato) |
| Obiettivo primario | Risolvere il problema dell'utente PRIMA di creare ticket |
| Modello | Sonnet (default) |
| KB binding | `product_knowledge` cat IN ('FAQ','HOW_TO','TROUBLESHOOT','KNOWN_ISSUE','TRAINING') + PRODUCT_CARD pinned |
| Tool list | `search_knowledge_base`, `forward_to_expert`, `escalate_to_ticket` (3) |
| Channel | text (canale voice futuro pending) |
| FSM | NO |
| Tenant context | obbligatorio (tenant esiste post-login) |
| Multi-livello KB | L0 + L1 + L2 (filtra `tenant_id`) |
| Anti-pollution | si — solo articoli APPROVED + active |
**Distingue formazione vs bug** (regola business critica):
- FORMAZIONE: "non so dove si trova", "come faccio a", ... → `forward_to_expert`
- BUG: "da errore", "non funziona", "crash", ... → `escalate_to_ticket`
### 4.2 Sub-template "Sales pre-vendita"
**Reference implementation**: Anna su [`publicDemoController.js`](../nexus-ai-ms/src/controllers/publicDemoController.js) (`/public/demo-lead-trpg`)
| Elemento | Valore canonical |
|---|---|
| Persona | "Anna" (canonical cross-prodotto) |
| Obiettivo primario | Presentare prodotto + qualificare lead + lead capture (email/contatto) |
| Modello | Haiku (volume alto, costo critico) |
| KB binding | PRODUCT_CARD pinned (obbligatoria) + `getRelevantHelpArticles` cat IN ('HOW_TO','URL_CHUNK','FAQ','DOC_CHUNK') |
| Tool list | (base): nessun tool. (demo agent): `show_feature`, `run_macro`, `query_product_state` (3 demo tool) |
| Channel | text (chat web) — voice futuro |
| FSM | NO |
| Tenant context | NO (lead-facing pubblico, no auth) |
| Multi-livello KB | SOLO L0 + L1 (NO L2 dati cliente — vincolo GDPR §8) |
| Anti-pollution | si + filter `category!='TROUBLESHOOT'` (no info bug interni) |
| Lead capture | dopo 4-5 turni: `"Ti mando una demo personalizzata. Come ti contatto?"` |
| Demo mode flag | `demo_enabled=true` per attivare 3 demo tool (iframe pilot) |
### 4.3 Sub-template "Plan-mode dialog approver" (Gaia)
**Reference implementation**: Gaia TRPG ([`gaiaController.js`](../nexus-ai-ms/src/controllers/gaiaController.js))
| Elemento | Valore canonical |
|---|---|
| Persona | "Gaia" (TRPG pilota; nome alternativo per altri prodotti TBD) |
| Obiettivo primario | Dialogare con approver umano per raffinare proposta diagnosi ticket PENDING_APPROVAL |
| Modello | dinamico: URGENT/HIGH→Opus, default→Sonnet |
| KB binding | PRODUCT_CARD pinned + RAG keyword top-3 articoli `product_knowledge` |
| Tool list | 11 tool readonly via devenv-gateway: `read_file`, `grep`, `list_dir`, `git_log`, `git_blame`, `run_tests`, `dry_run_sql`, + side-effect: `update_proposal`, `mark_ready`, `request_approver_decision`, `trigger_apply` |
| Channel | voice (Charlotte ElevenLabs `XB0fDUnXU5powFXDhCwa` — drift Sarah da chiudere VOX) |
| FSM | NO (state machine session in-memory) |
| Tenant context | obbligatorio (ticket scoped) |
| Multi-livello KB | L0 + L1 + L2 (tenant del ticket) |
| Stallo detection | dopo 12 turni / 15 min / 3 request_approver_decision → status `STALLED` + ticket → PENDING_HUMAN_REVIEW |
| Anti-loop | max 60 tool call per sessione |
| Persistenza | in-memory `sessions Map` (TODO: persistere in `gaia_sessions` per metrics §metrics endpoint) |
**Caratteristica unica**: ha tool readonly che chiamano `devenv-gateway` (porta 4220 nel container DevEnv prodotto) per ispezionare codice/tests/SQL. Pattern non replicabile direttamente su altri prodotti senza scaffold gateway dedicato.
### 4.4 Sub-template "Lead qualification verticali"
**Reference implementation**: Giulia (7 agent EDUCATION, basate su `basePrompts.js` PROMPTS const)
| Elemento | Valore canonical |
|---|---|
| Persona | "Giulia" (EDUCATION), "ARIA Health/Legal/Realty" (verticali pending — 0 record DB) |
| Obiettivo primario | Qualificare lead tramite FSM verticale-specifica (D1-D23 EDUCATION, H1-H8 HEALTH, L1-L8 LEGAL, R1-R9 REALTY) |
| Modello | Sonnet (tool use multi-step) |
| KB binding | nessuno (verticali pre-vendita non hanno KB di dominio prodotto) |
| Tool list | 5 base FSM: `fsm_transition`, `complete_scoring`, `open_ticket`, `schedule_callback`, `flag_high_priority` |
| Channel | text + voice (entrambi configurati con `system_prompt_voice` separato) |
| FSM | OBBLIGATORIA (config FSM via `fsmConfigId` foreign key) |
| Tenant context | obbligatorio |
| VOICE_RULES | OBBLIGATORIE se canale voice |
| FSM_RULES | OBBLIGATORIE sempre |
**Verticali ENUM ammessi** in `ai_agent_profiles.vertical`: `EDUCATION`, `HEALTH`, `LEGAL`, `REALTY` (proposta v1.1: aggiungere `SUPPORT`, `SALES`, `PLAN_MODE`, `META` per coprire altri sub-template — oggi vertical=`SUPPORT` è hack).
---
## §5 KB binding multi-livello (L0 / L1 / L2 / L3)
### 5.1 Definizione livelli
| Livello | Scope | Tenant ID | Esempio TRPG | Owner aggiornamento |
|---|---|---|---|---|
| **L0 SYSTEM** | Cross-prodotto, regole AgileHub generali | `tenant_id=1` (system) + `product='AGILEHUB'` | "Cosa è plan vs bypass mode", "Come funzionano i ticket" | Agile AI |
| **L1 FIRM** | Per prodotto, dominio applicativo (no dati cliente) | `tenant_id=1` (system) + `product=<PROD>` | TRPG: "Cos'è D.P.R. 151/2011" | Agile AI + esperto verticale prodotto |
| **L2 COMPANY** | Per tenant cliente specifico | `tenant_id != 1` + `product=<PROD>` | TRPG Tremolada (`tenant_id=3`): 294 articoli formula bonus | Tenant admin + Agile AI validation |
| **L3 PERSONA** ⭐ futuro | Per avatar specifica (vestizione) | `tenant_id != 1` + `product=<PROD>` + `knowledge_filter_slug='<slug>'` | "Anna Tremolada Consulente Senior TRPG" → solo articoli marcati `trpg-tremolada-consulente` | Agile AI + VOX (Lotto F Avatar Registry) |
### 5.2 PRODUCT_CARD pinned obbligatoria
Ogni prodotto MUST avere **esattamente 1** record `product_knowledge` con:
- `category='PRODUCT_CARD'`
- `tenant_id=1` (L1 base)
- `active=TRUE`, `review_status='APPROVED'`
- `answer` = JSON valido struttura `{description, scope[], target_buyer, free_markdown}`
**Anti-pollution check** (per audit AGI-4): query
```sql
SELECT product, COUNT(*) as cards, SUM(JSON_VALID(answer)) as valid_json
FROM product_knowledge
WHERE category='PRODUCT_CARD' AND active=TRUE
GROUP BY product
HAVING cards != 1 OR valid_json != cards;
```
**Drift attuale (audit 2026-04-23)**:
- AGILEHUB: **3** PRODUCT_CARD (id 720, 729, 730) tutti con `JSON_VALID=0` → fix AGI-4: UPDATE category='HOW_TO' (sono articoli AWE M1/M2/Orchestration mal-categorizzati)
- TRPG: 1 PRODUCT_CARD ✅ valido
- LG231/ALLTAX/SUSTAINAI/NIS2: **0** PRODUCT_CARD ❌ → fix AGI-4: scaffold scheda base
### 5.3 Schema `product_knowledge` esteso (proposta migration)
Schema attuale (verificato Hetzner 2026-04-23):
```
id, tenant_id, product, category, question, answer, tags JSON, keywords,
source ENUM, source_type ENUM, source_url, source_file_path, source_source_id,
content_hash, fetched_at, chunk_index, chunk_total,
learned_from_session_id, learned_from_ticket_id, expert_id,
review_status ENUM, views, helpful, language, active, created_at, updated_at
```
**Migration proposta v1.0 → v1.1** (NON applicare in v1.0, sub-approval separata):
```sql
ALTER TABLE product_knowledge
ADD COLUMN kb_level ENUM('L0','L1','L2','L3') NULL DEFAULT NULL AFTER product,
ADD COLUMN knowledge_filter_slug VARCHAR(64) NULL DEFAULT NULL AFTER kb_level,
ADD INDEX idx_kb_level (kb_level),
ADD INDEX idx_knowledge_filter (knowledge_filter_slug);
```
Backfill `kb_level`:
- `tenant_id=1 AND product='AGILEHUB'``L0`
- `tenant_id=1 AND product!='AGILEHUB'``L1`
- `tenant_id!=1 AND knowledge_filter_slug IS NULL``L2`
- `tenant_id!=1 AND knowledge_filter_slug IS NOT NULL``L3` (futuro Lotto F)
### 5.4 Retrieval keyword (oggi) → Voyage AI embedding (futuro)
**Oggi** (LIVE produzione):
- `getRelevantHelpArticles(product, query, K)` ([`productKbSnippet.js`](../nexus-ai-ms/src/services/productKbSnippet.js))
- Tokenizzazione naive: split query in token >3 char, scoring `LIKE %token%` su `keywords` (peso 3) + `question` (peso 2) + `answer` (peso 1)
- Order by `score DESC, views DESC LIMIT K`
- **Limiti**: nessun semantic match (sinonimi, riformulazioni), no re-ranking, latency dipende da MySQL
**Roadmap v1.1+** (decision Agile AI + utente):
- **Opzione A**: Voyage AI embedding service ($0.10/M token) → vector column → cosine similarity
- **Opzione B**: rimanere keyword + aggiungere stemming italiano + sinonimi manuali
- **Opzione C**: Claude Haiku re-ranking layer (cross-encoder LLM) sul top-N keyword
- **Trigger decisione**: quando articoli per prodotto > 100 con KB binding multi-tenant attivo
### 5.5 Anti-pollution principle
Memoria persistente `feedback_no_demo_data_production.md`:
> Articoli `product_knowledge` seedati con contenuti fuori scope inquinano RAG ranking.
**Regole vincolanti**:
1. NO articoli demo/test in produzione: usare `product='TEST_DEMO'` per testing
2. NO PRODUCT_CARD multipli per stesso `(tenant_id, product)`
3. NO PRODUCT_CARD con `JSON_VALID(answer)=0`
4. NO articoli con `language` diverso dal default tenant senza override esplicito
5. Spot check periodico Agile AI (almeno mensile + post AGI-4 retrofit)
### 5.6 L3 PERSONA forward-looking (vestizione avatar)
Concetto introdotto sessione 33 part 4 (visione utente Avatar Registry):
```
AVATAR TECNICO + VESTIZIONE = PERSONA PUBBLICA
(voice_id + (display_name + visibile cliente
replica_id) knowledge_id + "Anna Tremolada
system_prompt + Consulente Senior")
cost_per_minute)
```
**Implementazione Lotto F (settimane 2-3 master plan v2.1)** — coordinata con VOX Lotto A foundation:
1. Migration `ai_profiles` (nexus-presenter-ms) ADD COLUMN `knowledge_id VARCHAR(64) NULL` (slug logico filtro KB)
2. Migration `product_knowledge` ADD COLUMN `knowledge_filter_slug VARCHAR(64) NULL` (vedi §5.3)
3. Modify `getRelevantHelpArticles` per accettare `knowledge_filter_slug` opzionale: `WHERE (knowledge_filter_slug IS NULL OR knowledge_filter_slug = ?)`
4. Ranking weight per livello: L0=0.5, L1=1.0, L2=1.5, L3=2.0
5. Seed esempi:
- Avatar "Anna Generica" → `knowledge_id='agilehub-default'`
- Avatar "Anna Tremolada Consulente TRPG" → `knowledge_id='trpg-tremolada-consulente'`
- Articoli AGILEHUB esistenti → marcare `knowledge_filter_slug='agilehub-default'`
- Articoli TRPG L2 Tremolada → marcare `knowledge_filter_slug='trpg-tremolada-consulente'`
**Coordinamento**:
- VOX: schema `ai_profiles` esteso (Lotto A) + voice integration
- MAESTRO: blocchi AWE `D02_LoadAvatarKB(slug)` + `C09_RetrieveFromKB(query, knowledge_id, livello)`
- PRISMA: UI tab agenti `/admin/agents` con KB binding selector (Lotto C, approval gate)
**Status v1.0**: documentato come `PROPOSED` — implementazione conforme richiesta da v1.1 dopo deploy Lotto F.
---
## §6 Tool list standard
### 6.1 Catalogo NEXUS_TOOLS (11 tool)
Da [`nexusTools.js`](../nexus-ai-ms/src/tools/nexusTools.js):
| # | Tool | Family | Side-effect | Eseguito da |
|---|---|---|---|---|
| 1 | `fsm_transition` | FSM | Sì (FSM state) | nexus-fsm-ms via `ToolExecutor.fsmTransition` |
| 2 | `complete_scoring` | FSM | Sì (lead score) | nexus-lead-ms (futuro; oggi log) |
| 3 | `open_ticket` | FSM | Sì (ticket new) | nexus-ticket-ms (futuro; oggi log) |
| 4 | `schedule_callback` | FSM | Sì (calendario) | log only oggi |
| 5 | `flag_high_priority` | FSM | Sì (lead flag) | log only oggi |
| 6 | `search_knowledge_base` | Support | NO (read-only) | nexus-ticket-ms `/product-knowledge/search` |
| 7 | `forward_to_expert` | Support | Sì (expert notification) | nexus-ticket-ms `/support-sessions/:id/forward-expert` |
| 8 | `escalate_to_ticket` | Support | Sì (ticket new) | nexus-ticket-ms `/support-sessions/:id/escalate` |
| 9 | `show_feature` | Demo | Sì (iframe message) | client postMessage via `demoActions[]` accumulator |
| 10 | `run_macro` | Demo | Sì (iframe message) | client postMessage via `demoActions[]` accumulator |
| 11 | `query_product_state` | Demo | NO (read-only) | placeholder MVP — futuro live state pull |
### 6.2 Tool list per famiglia (matrice sub-template × tool)
| Tool | Support | Sales | Plan-mode | Lead qualif |
|---|---|---|---|---|
| `fsm_transition` | NO | NO | NO | **MUST** |
| `complete_scoring` | NO | NO | NO | **MUST** |
| `open_ticket` | NO | SHOULD (lead capture) | NO | SHOULD |
| `schedule_callback` | NO | SHOULD | NO | SHOULD |
| `flag_high_priority` | NO | NO | NO | SHOULD |
| `search_knowledge_base` | **MUST** | NO | NO | NO |
| `forward_to_expert` | **MUST** | NO | NO | NO |
| `escalate_to_ticket` | **MUST** | NO | NO | NO |
| `show_feature` | NO | SHOULD se `demo_enabled` | NO | NO |
| `run_macro` | NO | SHOULD se `demo_enabled` | NO | NO |
| `query_product_state` | NO | SHOULD se `demo_enabled` | NO | NO |
| `read_file`/`grep`/`list_dir`/`git_log`/`git_blame` (custom Gaia) | NO | NO | **MUST se Plan-mode** | NO |
| `run_tests`/`dry_run_sql` (custom Gaia) | NO | NO | SHOULD se Plan-mode | NO |
| `update_proposal`/`mark_ready`/`request_approver_decision`/`trigger_apply` (custom Gaia) | NO | NO | **MUST se Plan-mode** | NO |
### 6.3 Estensioni custom (Gaia readonly via devenv-gateway)
Pattern Gaia (TRPG pilota, [`gaiaController.js:228-250`](../nexus-ai-ms/src/controllers/gaiaController.js)):
```js
const PRODUCT_GATEWAYS = {
TRPG: {
url: process.env.TRPG_GATEWAY_URL || 'http://trpg-pro-agile-devenv:4220',
key: process.env.TRPG_GATEWAY_KEY || process.env.DEVENV_GATEWAY_KEY,
displayName: 'TRPG',
},
};
async function callGateway(product, toolName, args) {
const gw = PRODUCT_GATEWAYS[product];
// POST a http://<gateway>/tools/<toolName> con X-Internal-Key
}
```
**Regole estensione custom tool**:
- Tool con prefisso `read_*`/`grep`/`list_*`/`git_*` SHOULD essere readonly
- Tool con side-effect su prodotto target richiedono devenv-gateway dedicato per quel prodotto
- Spec contratto separato (es. `docs/SPEC_DEVENV_GATEWAY_TOOLS.md` futuro)
- Audit obbligatorio (vedi `gaia_audit_log` per Gaia)
### 6.4 Cost estimation per tool (D6 metering)
Tool che usano LLM hanno cost esplicito tracciato via cost-sdk. Tool che usano solo HTTP/DB → cost trascurabile, no metering.
Esempio Gaia (per session):
- LLM cost: cumulato via `runAgentLoop``result.totalUsage.{inputTokens,outputTokens}` × pricing modello
- Tool readonly cost: trascurabile (HTTP locale)
- Tool `dry_run_sql`: trascurabile (snapshot readonly DB)
---
## §7 Guardrails minimi obbligatori
### 7.1 Pattern canonical LIMITI ASSOLUTI
Sezione 7 system_prompt deve sempre presente, formato:
```
LIMITI ASSOLUTI:
- Non <azione vietata 1>
- Non <azione vietata 2>
...
```
### 7.2 Limiti minimi per famiglia
**Support post-vendita**:
- Non inventare funzionalità non presenti nella KB
- Non chiedere informazioni tecniche complesse (log, stack trace) — quello lo farà il team tecnico
- Non superare 6 scambi senza proporre `forward_to_expert` o `escalate_to_ticket`
- Se la KB non ha risultati, dirlo onestamente
**Sales pre-vendita**:
- Non inventare feature non presenti nella scheda
- Non garantire prezzi non confermati ("dipende dal volume — te lo vedo dopo")
- Non promettere SLA/disponibilità senza verifica
- Non sminuire prodotti competitor (etica commerciale)
- Tool MAI proattivamente — solo su richiesta esplicita utente (regola FERREA `demo_enabled`)
**Plan-mode dialog approver (Gaia)**:
- Non modificare mai il codice sorgente del prodotto (tool readonly only)
- Non eseguire SQL non-SELECT (`dry_run_sql` enforced backend)
- Ammettere quando non si sa
- Non chiamare `trigger_apply` in altre situazioni che non sia approvazione esplicita approver
**Lead qualification verticali**:
- Non garantire posti/disponibilità senza verifica
- Non indicare prezzi non confermati
- Non promettere esiti concorsi/graduatorie/cause/vendite (per verticale)
- (HEALTH) Non formulare diagnosi, non suggerire farmaci
- (LEGAL) Non dare consulenza legale personalizzata, non citare articoli di legge specifici
- (REALTY) Non garantire prezzi/valutazioni senza sopralluogo
### 7.3 Limiti universali (cross-famiglia, MUST sempre)
- Rispondere SEMPRE in italiano (default; `en` se tenant lo richiede)
- Rispettare scoping multi-tenant (mai rivelare dati altri tenant)
- Non superare il limite turni configurato (anti-loop)
- Non inventare valori KB ("preferisco verificare col team — ti rispondo se mi lasci un contatto")
---
## §8 GDPR — split AI prodotto vs AI marketing
### 8.1 Principio
Memoria persistente `project_ai_prodotto_vs_marketing.md`: due cervelli AI separati per GDPR compliance.
| Tipo AI | Dati accessibili | Audience | Hosting |
|---|---|---|---|
| **AI prodotto** (server-side) | L0 + L1 + L2 (dati cliente reali) | utenti autenticati del cliente | post-login, scoped tenant_id |
| **AI marketing** (pubblico) | L0 + L1 SOLO `category IN ('PRODUCT_CARD','HOW_TO','URL_CHUNK')` filtrati pubblici | lead anonimi su landing | pre-login, no tenant context |
### 8.2 Implementazione filtro
Per **AI Sales pre-vendita** (publicDemoController):
```sql
WHERE product = ?
AND tenant_id = 1 -- L0/L1 only
AND category IN ('PRODUCT_CARD','HOW_TO','URL_CHUNK','FAQ','DOC_CHUNK')
AND review_status = 'APPROVED'
AND active = TRUE
AND (language IS NULL OR language = ?)
```
Per **AI Support post-vendita / Plan-mode** (autenticati):
```sql
WHERE product = ?
AND (tenant_id = 1 OR tenant_id = ?) -- L0/L1 + L2 cliente
AND review_status = 'APPROVED'
AND active = TRUE
```
### 8.3 GDPR Right to be Forgotten
- DELETE articoli L2 con `tenant_id = <cliente_da_dimenticare>`: cascade + audit log
- L3 PERSONA (futuro): DELETE articoli con `knowledge_filter_slug = '<cliente>-<persona>'`
- Endpoint dedicato: `DELETE /ai/products/:product/knowledge?tenant_id=X&confirm=YES_GDPR`
- Backup retention: 30 giorni dopo delete (compliance retention)
### 8.4 Anti-leak vincolante
- AI marketing NEVER deve restituire articoli con `tenant_id != 1`
- AI prodotto NEVER deve restituire articoli di altri `tenant_id` rispetto al chiamante
- Log query KB con `tenant_id` filter applicato (per audit GDPR)
---
## §9 Cost tracking MUST (cost-sdk integration)
### 9.1 Pattern obbligatorio
Vedi §3.12. Chiamata canonical:
```js
const result = await anthropicService.chat(messages, systemPrompt, tools, {
model: anthropicService.MODELS.SONNET,
caller: 'support-trpg', // MUST
sessionId: session.sessionKey, // MUST
productSlug: 'trpg', // MUST
tenantId: session.tenantId, // SHOULD
sessionType: 'support', // SHOULD
});
```
### 9.2 Anti-pattern (NON conforme AGI-4)
```js
// BAD: opts mancanti
const result = await anthropicService.chat(messages, systemPrompt, tools);
// ^ 4° arg vuoto
```
### 9.3 Esempio TRPG conforme
Da `voiceDialogController.js:144-150`:
```js
const result = await anthropicService.chat(messages, systemPrompt, null, {
model: anthropicService.MODELS.HAIKU,
caller: 'voice-dialog',
sessionId,
productSlug: (ticket?.product ? String(ticket.product).toLowerCase() : 'agilehub'),
sessionType: 'voice_dialog',
});
```
Da `gaiaController.js:683-685`:
```js
{ model: preferredModel, caller: `gaia:${priority}`, sessionId: session.sessionId,
productSlug: (session.product || 'agilehub').toLowerCase(), sessionType: 'gaia' }
```
### 9.4 Cost reporter implementation
Vedi `anthropicService.js:6-23` + `shared-libraries/cost-sdk` integration:
- Fire-and-forget (no impact su latency)
- Endpoint: `POST {HUB_URL}/api/cost/log` (nexus-hub-ms Fase 2 LIVE)
- Visibility dashboard: `/admin/cost?month=YYYY-MM` (admin_tenant role)
### 9.5 Telemetria di base (anche senza cost-sdk)
Pattern `anthropicService.js:93-95` (sempre attivo se `opts.caller || AI_USAGE_LOG=1`):
```js
logger.info(`[ai-usage] caller=${opts.caller} model=${model} in=${usage.inputTokens} out=${usage.outputTokens}`);
```
Quindi `caller` è MUST anche per debug/log baseline.
---
## §10 Conformance checklist (per audit AGI-4 retrofit)
### 10.1 Matrice 12 elementi × MUST/SHOULD
Per ogni AI di prodotto (tabella `ai_agent_profiles` + caller controllers):
| # | Elemento | Verifica | Fix se mancante |
|---|---|---|---|
| 1 | Identità persona | `ai_agent_profiles.name` valorizzato + system_prompt riga 1 = "Sei <Nome>" | UPDATE `name` + UPDATE `system_prompt` (header) |
| 2 | Obiettivo dichiarato | `system_prompt` contiene "IL TUO OBIETTIVO" o equivalente | UPDATE `system_prompt` aggiungere sezione 2 |
| 3 | Modello Claude esplicito | grep caller per `opts.model` | Modificare caller con `opts.model: MODELS.X` |
| 4 | System prompt strutturato 7 sezioni | `LENGTH(system_prompt) > 800` AND contiene marker sezioni | UPDATE `system_prompt` con template canonical |
| 5 | KB binding | sub-template Support/Sales/Plan-mode → caller chiama `getProductCardSnippet` + `getRelevantHelpArticles` | Modificare caller con KB inject |
| 6 | Tool list dichiarativa | sub-template !=Lead generico → tool list non vuota nel caller | Modificare caller passando tools |
| 7 | LIMITI ASSOLUTI | `system_prompt` contiene "LIMITI ASSOLUTI" + N bullet | UPDATE `system_prompt` aggiungere sezione 7 |
| 8 | VOICE_RULES (se voice) | `system_prompt_voice` contiene `VOICE_RULES` text | UPDATE `system_prompt_voice` |
| 9 | FSM_RULES (se Lead) | `vertical IN ('EDUCATION','HEALTH','LEGAL','REALTY')``system_prompt` contiene `FSM_RULES` | UPDATE `system_prompt` |
| 10 | Channel-aware | se canale voice supportato → `system_prompt_voice IS NOT NULL` | UPDATE `system_prompt_voice` |
| 11 | Tenant context | caller chiama `buildSystemPrompt(vertical, channel, tenantConfig)` con tenantConfig valorizzato | Modificare caller passare tenantConfig |
| 12 | Cost tracking MUST | `caller` + `sessionId` + `productSlug` in ogni `anthropicService.{chat,runAgentLoop}` call | Modificare caller passando opts |
### 10.2 Score conformance
Per ogni AI di prodotto:
- 12/12 MUST + tutti SHOULD applicabili → **CONFORME**
- 12/12 MUST, alcuni SHOULD mancanti → **CONFORME PARZIALE** ⚠️ (warning, no block)
- < 12 MUST **NON CONFORME** (bloccante AGI-4 sign-off)
### 10.3 Procedura audit AGI-4 per prodotto
1. Agile AI esegue audit checklist produce `docs/AGI4_GAP_<PRODUCT>.md`
2. Gap report contiene: matrice 12 elementi compilata, fix proposti per ogni gap, effort stimato
3. Sub-approval esplicita utente per applicare fix
4. Apply (modifiche `nexus-ai-ms/src/...`) pattern §10.3 team roster (modifiche file di prodotto AgileHub stesso, OK)
5. Smoke test: 3-5 query reali AI prodotto post-fix
6. Aggiornamento `ai_agent_profiles` + commit + sub-approval push Gitea
---
## §11 "Agile" — AI runtime di AgileHub (caso speciale)
### 11.1 Scope deciso (sessione 33 part 6, decisione utente AGI-2 domanda 4)
**Entrambi (full)**: una sola "Agile" AI con context routing.
| Context | Trigger | System prompt | Tool list | KB |
|---|---|---|---|---|
| **Admin AgileHub** | Chiamata da pagine `/admin/*` autenticato role `admin_tenant`/`admin_global` | "Agile per amministratori" governance tone | `query_master_plan`, `query_standard`, `query_agent_status`, `query_workflow_runs`, `query_cost`, `search_kb_agilehub` | L0 AGILEHUB + L1 ADMIN |
| **Utenti finali prodotti** | Chiamata da widget cross-prodotto / pagine `/help`-style | "Agile per utenti" assistente tone | `search_kb_agilehub`, `escalate_to_support` | L0 AGILEHUB + L1 USER (subset pubblico) |
### 11.2 Naming canonical
- `display_name`: "Agile"
- `agent_key`: `AGILE_RUNTIME` (in `ai_agent_profiles`)
- `vertical`: nuovo ENUM `META` (proposta v1.1 schema migration)
### 11.3 System prompt template "Agile"
```
Sei Agile, l'assistente AI di AgileHub.
[Context routing — admin]
Stai parlando con un amministratore di AgileHub. Aiutalo a:
- Conoscere lo stato del sistema (master plan settimana corrente, agenti specialisti, standard cross-suite, workflow runs AWE, cost mese corrente)
- Trovare articoli nella KB AGILEHUB
- Suggerire azioni concrete (es. "vuoi consultare REGENT per arbitrato?")
[Context routing — utente finale]
Stai parlando con un utente di un prodotto AgileHub. Aiutalo a:
- Capire come usare AgileHub (workflow editor, dashboard, mobile)
- Trovare guide nella KB AGILEHUB
- Escalare a support se serve
[KB inject: top-K articoli AGILEHUB rilevanti]
[Tool list: query_* per admin, search/escalate per user]
[LIMITI ASSOLUTI: non rivelare info di altri tenant; non inventare feature non presenti in KB]
```
### 11.4 Modello Claude
- Default: **Sonnet** (dialogo + tool use)
- Greeting / messaggio singolo: Haiku
- Reasoning profondo (es. "perché workflow run è failed?"): Opus on-demand
### 11.5 KB binding
- L0 AGILEHUB: 52 articoli esistenti (ground truth audit 2026-04-23) id 720+
- L1 ADMIN/USER: split via nuovo campo `audience ENUM('admin','user','all')` in product_knowledge (proposta v1.1 schema)
- L3 PERSONA: `display_name='Agile Admin'` vs `display_name='Agile Helper'` con stessi voice_id ma KB filter differente (futuro Lotto F)
### 11.6 Implementazione AGI-3 (~5-6gg)
Step:
1. INSERT `ai_agent_profiles` record `AGILE_RUNTIME` con system_prompt template
2. Nuovo controller `agileController.js` con context routing logic
3. Tool dispatcher: `query_master_plan`, `query_standard`, ecc. (5-7 tool nuovi)
4. Endpoint `/ai/agile/chat` con auth detection (role admin admin context)
5. Widget UI in `/admin/agile` (Agile chat panel coordinamento PRISMA approval gate)
6. Smoke test: 5 query admin + 5 query user
7. Cost tracking conformance MUST
**Dipendenze AGI-3**:
- AGILE AI design tool list + system prompt template (questo doc + estensione)
- MAESTRO co-owner workflow integration (chiamare blocco AWE da Agile)
- PRISMA reviewer UI exposure (`/admin/agile` panel)
- Sub-approval utente prima del deploy LIVE
---
## §12 Stato adoption per prodotto (snapshot 2026-04-23)
### 12.1 Tabella matrice prodotto × elementi standard
Audit DB Hetzner 2026-04-23 (`SELECT product, count, has_card, kb_levels FROM ...`):
| Prodotto | Tot articoli KB | PRODUCT_CARD | KB livelli presenti | ai_agent_profiles | Score conformance | Note |
|---|---|---|---|---|---|---|
| **AGILEHUB** | 52 | **3 (pollution)** | L0 only | 0 | NON CONFORME | Fix AGI-4: UPDATE 2 PRODUCT_CARD HOW_TO; creare AGILE_RUNTIME (AGI-3) |
| **TRPG** | 295 | 1 | L1 (1) + L2 (294 Tremolada) | 1 (ARIA_SUPPORT_TRPG) short prompt | CONFORME PARZIALE | Fix: estendere `system_prompt` ARIA_SUPPORT_TRPG a template completo; aggiungere ANNA_SALES_TRPG + GAIA_PLANMODE_TRPG in DB |
| **TRPG-PRO** | 0 | 0 | nessuno | 0 | NON CONFORME | Fix: scaffolding L1 base + ai_agent_profiles ARIA_SUPPORT_TRPG_PRO |
| **SUSTAINAI** | 27 | 0 | L1 (1) + L2 (26 cliente 5) | 1 (ARIA_SUPPORT_SUSTAINAI) short prompt | NON CONFORME | Fix: scaffolding PRODUCT_CARD + estendere system_prompt |
| **NIS2** | 2 | 0 | L1 (1) + L2 (1 cliente 7) | 1 (ARIA_SUPPORT_NIS2) short prompt | NON CONFORME | Fix: scaffolding KB completo + PRODUCT_CARD |
| **AllTax (TAXAI)** | 83 | 0 | L2 only (cliente 6) | 1 (ARIA_SUPPORT_ALLTAX) short prompt | NON CONFORME | Fix: scaffolding L1 base + PRODUCT_CARD |
| **LG231** | 91 | 0 | L1 (1) + L2 (90 cliente 8) | 1 (ARIA_SUPPORT_LG231) short prompt | NON CONFORME | Fix: scaffolding PRODUCT_CARD + estendere system_prompt |
| **DFM-PRO** | 0 | 0 | nessuno | 0 | NON CONFORME | Scope completo retrofit AGI-4 |
| **ALLRISK** | 0 | 0 | nessuno | 0 | NON CONFORME | Scope completo retrofit AGI-4 |
| **WMS** | 0 | 0 | nessuno | 0 | NON CONFORME | Scope completo retrofit AGI-4 |
| **MADEBYCLOUD** | 0 | 0 | nessuno | 0 | NON CONFORME | Fuori scope AGI-4 master plan v2.1 |
| **CertiSource** | 0 | 0 | nessuno | 0 | NON CONFORME | Fuori scope AGI-4 master plan v2.1 |
### 12.2 Drift cross-prodotto da chiudere
| Drift | Affected | Fix |
|---|---|---|
| `system_prompt` ARIA_SUPPORT troppo corto (220-300 char vs template ~3000 char) | TRPG, SUSTAINAI, ALLTAX, NIS2, LG231 | AGI-4: UPDATE `system_prompt` con `buildSupportPrompt(<PRODUCT>)` rendered text |
| `system_prompt_voice` NULL su tutti ARIA_SUPPORT | tutti | AGI-4: popolare `system_prompt_voice` se voice supportato |
| Anna Sales non in `ai_agent_profiles` (hardcoded controller) | tutti i prodotti con landing demo | AGI-4: INSERT `ANNA_SALES_<PRODUCT>` per ogni prodotto con landing |
| Gaia Plan-mode in-memory (no record DB) | TRPG (pilota) | AGI-4 (post AGI-5): persistere config in `ai_agent_profiles` `GAIA_PLANMODE_TRPG` + tabella `gaia_sessions` per metrics |
| 7 Giulia EDUCATION non hanno fsm_config_id valorizzato (`has_fsm=0` query DB) | tutti i 7 Giulia | AGI-4: link FSM config |
| Cost tracking opzionale in `sessionService.js:127` | tutti i caller `runAgentLoop` legacy | AGI-4: passare opts cost-sdk |
### 12.3 Priorità retrofit AGI-4
Settimane 3-4 master plan v2.1 (~7-10gg):
| Settimana | Prodotti | Effort |
|---|---|---|
| 3 (8-14/5) | AGILEHUB (fix pollution + creare Agile AGI-3) | 5gg |
| 3-4 (12-21/5) | TRPG estendere ARIA_SUPPORT + creare ANNA_SALES + GAIA_PLANMODE | 2gg |
| 4 (15-21/5) | SUSTAINAI + NIS2 + ALLTAX + LG231 (fix existing ARIA_SUPPORT + scaffold PRODUCT_CARD) | 3gg |
| 5 (22-28/5) | DFM-PRO + ALLRISK + WMS (scope completo) | 4gg |
| Backlog v1.1 | MADEBYCLOUD + CertiSource | TBD |
---
## §13 Cronologia versioni
| Data | Versione | Modifica | Owner |
|---|---|---|---|
| 2026-04-23 | 1.0 (proposed) | Creazione standard. Sub-template Support + Sales + Plan-mode + Lead qualif. KB multi-livello L0/L1/L2 + L3 PERSONA forward-looking. Cost tracking MUST. Naming convention netto (Agile vs Agile AI vs Anna vs Gaia). Conformance checklist 12 elementi. Tabella adoption snapshot 12 prodotti. | Agile AI (AGI-2 master plan v2.1) |
| _(future)_ | 1.1 | Migration `kb_level` + `knowledge_filter_slug` + `audience` columns. ENUM vertical esteso (`META`, `SUPPORT`, `SALES`, `PLAN_MODE`). L3 PERSONA promosso da `PROPOSED` a STANDARD. Embedding service decision. | TBD |
---
**Documento mantenuto da**: Agile AI (Architetto AI di prodotto + KB governance)
**Distribuzione**: in attesa sub-approval utente per seed `nexus_hub.hub_standards` slug=`ai-prodotto` v1.0 + distribuzione cross-suite (pattern `installer-integration`)
**Riferimento operativo**: [`docs/AGENT_AGILE_AI.md`](AGENT_AGILE_AI.md) v1.0 + [`docs/BRIEFING_AGILE_AI.md`](BRIEFING_AGILE_AI.md) v1.0
**Master Plan link**: [`docs/MASTER_PLAN_GO_LIVE_4_WEEKS.md`](MASTER_PLAN_GO_LIVE_4_WEEKS.md) v2.1 sezione AGI-1...AGI-6