Vitruvyan Docs
Guida alla Costruzione di una Verticale su Vitruvyan Core
Last updated: February 15, 2026
Version: 1.0
Prerequisito: Conoscenza base di Python 3.10+, FastAPI, e il pattern Plugin
Indice
- Panoramica
- Architettura del Sistema Plugin
- Quick Start — Verticale Minima (30 minuti)
- Guida Completa — Verticale Produzione
- Contratti e ABC disponibili
- Ricettario — Casi d'Uso Comuni
- Testing della Verticale
- Deployment (Docker + Service)
- Checklist Pre-Rilascio
- Anti-Pattern da Evitare
- Riferimenti
1. Panoramica
Vitruvyan Core è un sistema operativo epistemico domain-agnostic. Il core fornisce:
- Pipeline cognitiva (LangGraph) con 15+ nodi orchestrati
- Sacred Orders (Perception, Memory, Reason, Truth) come servizi governati
- Bus cognitivo (Redis Streams) per comunicazione asincrona
- Agenti singleton per accesso a PostgreSQL, Qdrant, LLM
Una verticale (domain vertical) è un pacchetto che aggiunge conoscenza e comportamento specifici di un dominio al core, senza modificare il core stesso.
Cosa fornisce una verticale
| Componente | Responsabilità | Obbligatorio? |
|---|---|---|
| Intent Config | Definire gli intenti del dominio | Sì |
| Graph Plugin | Estendere la pipeline con nodi custom | No (consigliato) |
| Prompt Registry | Personalità e scenari LLM per il dominio | No (consigliato) |
| Slot Filler | Raccolta parametri mancanti via dialogo | No |
| Response Formatter | Formattazione output specifica | No |
| Entity Resolver | Mapping entità dominio-specifiche | No |
| Execution Handler | Logica di esecuzione custom | No |
| Governance Rules | Regole di compliance specifiche | No |
| Domain Contracts | Implementazioni di scoring, risk, explainability | No |
Diagrama di integrazione
2. Architettura del Sistema Plugin
Come il Core carica le verticali
Il caricamento è controllato da variabili d'ambiente:
| Env Var | Default | Funzione |
|---|---|---|
INTENT_DOMAIN | generic | Quale intent_config.py caricare |
ENTITY_DOMAIN | (= INTENT_DOMAIN) | Quale entity_resolver_config.py caricare |
EXEC_DOMAIN | — | Quale execution_config.py caricare |
Il meccanismo di caricamento (in graph_flow.py):
Fallback: se il dominio non esiste o l'import fallisce, usa create_generic_registry() (solo intent soft + unknown).
PYTHONPATH
I servizi e il core usano vitruvyan_core/ come root del PYTHONPATH. L'import from domains.healthcare.intent_config import ... funziona perché vitruvyan_core/domains/ è sul path.
3. Quick Start — Verticale Minima (30 minuti)
Creiamo una verticale per il dominio healthcare come esempio.
Passo 1: Creare la struttura
Passo 2: intent_config.py (UNICO FILE OBBLIGATORIO)
Passo 3: Attivare la verticale
Passo 4: Verificare
Fatto. Con questo singolo file, la pipeline LangGraph riconosce i 3 intenti healthcare e li instraderà correttamente.
4. Guida Completa — Verticale Produzione
Una verticale per produzione richiede 5-8 componenti. Ecco la struttura obiettivo:
4.1 Graph Plugin (Estensione della Pipeline)
Il GraphPlugin è il cuore della verticale: definisce come il dominio estende la pipeline cognitiva.
4.2 Prompt Registry (Personalità LLM)
4.3 Slot Filler (Raccolta Parametri)
4.4 Response Formatter (Formattazione Output)
4.5 Entity Resolver Hook
4.6 Governance Rules (Compliance)
5. Contratti e ABC Disponibili
5.1 Contratti del Core (obbligatorietà descritta per ciascuno)
| Contratto | Modulo | Metodi astratti | Quando implementare |
|---|---|---|---|
GraphPlugin | core.orchestration.graph_engine | 7 | Quando aggiungi nodi alla pipeline |
Parser / BaseParser | core.orchestration.parser | 3 | Quando estrai parametri dal testo |
SlotFiller | core.orchestration.compose.slot_filler | 3 | Quando raccogli parametri via dialogo |
ResponseFormatter | core.orchestration.compose.response_formatter | 1 | Quando formatti l'output utente |
BaseDomain | domains.base_domain | 7 | Quando registri un dominio formale |
ILLMProvider | contracts.llm_provider | 5 | Solo se sostituisci OpenAI con un provider custom |
AggregationProvider | domains.aggregation_contract | 5 | Per scoring/ranking personalizzati |
ExplainabilityProvider | domains.explainability_contract | 7 | Per explainability personalizzata |
RiskProvider | domains.risk_contract | 5 | Per valutazione rischio personalizzata |
5.2 GraphPlugin — Metodi obbligatori
5.3 BaseDomain — Metodi astratti
5.4 BaseGraphState — Campi disponibili (37 campi base)
I campi sono organizzati in categorie:
| Categoria | Campi | Accesso |
|---|---|---|
| Essential | input_text, route, result, error, response, user_id | state["input_text"] |
| Intent | intent, needs_clarification, clarification_reason | state["intent"] |
| Language | language_detected, language_confidence, cultural_context, babel_status | state["language_detected"] |
| Emotion | emotion_detected, emotion_confidence, emotion_intensity, ... | state["emotion_detected"] |
| Orthodoxy | orthodoxy_status, orthodoxy_verdict, orthodoxy_findings, ... | state["orthodoxy_status"] |
| Vault | vault_status, vault_protection, ... | state["vault_status"] |
| Tracing | trace_id, semantic_matches, vsgs_status | state["trace_id"] |
| CAN | can_response, can_mode, final_response, ... | state["final_response"] |
Il tuo dominio estende questi campi con i propri (via get_state_extensions()).
6. Ricettario — Casi d'Uso Comuni
6.1 Aggiungere un intent che richiede entità
6.2 Aggiungere un intent "soft" (conversazionale, niente esecuzione)
6.3 Usare l'LLM da un nodo custom
6.4 Emettere eventi sul bus cognitivo (StreamBus)
6.5 Accesso al database
6.6 Registrare prompt multilingua
7. Testing della Verticale
7.1 Struttura test consigliata
7.2 Conftest con guard (isolamento verticale)
7.3 Test intent_config
7.4 Test isolamento multi-dominio
7.5 Esecuzione test
8. Deployment (Docker + Service)
Se la verticale necessita di un servizio dedicato (API, listener, etc.), segui il pattern LIVELLO 2.
8.1 Struttura servizio
8.2 Template main.py (< 50 righe)
8.3 Docker Compose
9. Checklist Pre-Rilascio
Contratto Plugin
-
intent_config.pypresente concreate_{domain}_registry()che ritornaIntentRegistry - Tutti gli intenti hanno
name,description,examples(almeno 2) - Nessun nome intent collide con core (
soft,unknown) o altri domini -
route_typecorretto per ogni intent (execosoft) - Factory testata in isolamento (no Docker/Redis necessari)
Isolamento
- Zero import da
core.governance.*→domains.{tuo}/(flusso unidirezionale) - Zero import cross-dominio:
domains.finance.*indomains.healthcare.* - Nessun
load_dotenv()nel codice - Nessun secret hardcoded
- Tutti i config via
os.getenv()
Testing
- Test intent registration (factory, labels, exec/soft, collision)
- Test classification prompt (genera correttamente)
- Test graph plugin (se presente) — tutti i metodi astratti implementati
- Test slot filler (se presente) — missing slots, question generation
- Test in
tests/verticals/{domain}/conimportorskipguard - Test funzionano con
INTENT_DOMAIN=generic(non rompono il core)
Documentazione
-
README.mdnella directory del dominio - Esempi eseguibili in
examples/ - Charter/filosofia documentata (opzionale ma consigliato)
Deployment (se servizio dedicato)
-
main.py< 100 righe -
config.pycentralizza tuttios.getenv() -
Dockerfileerequirements.txtpresenti - Health check endpoint (
/health) - Auth middleware integrato
- CORS middleware configurato
10. Anti-Pattern da Evitare
| ❌ Anti-Pattern | ✅ Pattern Corretto |
|---|---|
Importare from core.governance.orthodoxy_wardens... nel dominio | Comunicare via StreamBus o contratti ABC |
| Hardcodare URL/password nel codice | Usare os.getenv("VAR_NAME") |
Creare OpenAI() direttamente | Usare from core.agents.llm_agent import get_llm_agent |
| Usare regex come engine primario per intent detection | Delegare all'LLM; regex solo come fallback |
Modificare file in vitruvyan_core/core/ per il tuo dominio | Usare i contratti in contracts/ ed estendere |
Import cross-dominio (from domains.finance... in healthcare) | Ogni dominio è indipendente — comunica via bus |
Importare psycopg2 direttamente | Usare PostgresAgent via core.agents.postgres_agent |
load_dotenv() in qualsiasi file | Mai — config solo via environment variables |
Mettere logica di business nel main.py del servizio | Delegare ad adapters/ e consumer LIVELLO 1 |
| Test che richiedono Docker/Redis/Postgres per il dominio | Test puri Python in LIVELLO 1, test infra solo in LIVELLO 2 |
| Nomi intent generici ("analyze", "process") | Nomi domain-qualified ("symptom_check", "drug_interaction") |
Override forzato di validated_entities nel backend | Rispettare la lista validated dal client (anche se []) |
11. Riferimenti
Implementazioni di riferimento
| Dominio | Complessità | File | Scopo |
|---|---|---|---|
domains/finance/ | Alta | 10 file, 2000+ righe | Verticale completa di produzione |
domains/energy/ | Minima | 2 file | Plugin minimo con 3 intenti |
domains/facility/ | Minima | 2 file | Plugin minimo con 3 intenti |
domains/dummy_test/ | Baseline | 2 file | Plugin assoluto minimo (1 intent) |
Documentazione architetturale
- SERVICE_PATTERN.md — Template servizio LIVELLO 2
- SACRED_ORDER_PATTERN.md — Pattern Sacred Order
- copilot-instructions.md — Regole invarianti del core
- V1_0_RELEASE_AUDIT_FEB15_2026.md — Stato dell'arte V1.0
- Vertical Contract V1 — Contratto normativo verticale
- Vertical Conformance Checklist — Checklist pass/fail
- Vertical Manifest Template — Manifest standard
Contratti ABC (codice sorgente)
vitruvyan_core/contracts/__init__.py— Import point unicovitruvyan_core/contracts/orchestration.py— Export orchestration contractsvitruvyan_core/contracts/neural_engine/— Contratti Neural Engine (IDataProvider,IScoringStrategy)vitruvyan_core/core/orchestration/graph_engine.py—GraphPlugin,NodeContract,GraphEnginevitruvyan_core/core/orchestration/intent_registry.py—IntentRegistry,IntentDefinitionvitruvyan_core/core/orchestration/base_state.py—BaseGraphState(37 campi)vitruvyan_core/core/orchestration/parser.py—Parser,BaseParser,ParsedSlotsvitruvyan_core/core/orchestration/compose/slot_filler.py—SlotFiller,SlotDefinitionvitruvyan_core/core/orchestration/compose/response_formatter.py—ResponseFormattervitruvyan_core/core/llm/prompts/registry.py—PromptRegistryvitruvyan_core/domains/base_domain.py—BaseDomain,EntitySchema,SignalSchema
Nota finale: La verticale non modifica mai il core. Se hai bisogno di una primitiva che non esiste nei contratti, apri una discussione per estendere le ABC — non fare workaround nel dominio.