- 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>
983 lines
50 KiB
Markdown
983 lines
50 KiB
Markdown
# 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
|