Componenti del Canvas
Il Canvas dispone di 15 componenti suddivisi in sei categorie funzionali. Ogni componente ha parametri di configurazione, produce output identificabili con variabili e serve a uno scopo preciso nel flusso.
Flusso Base
I componenti di flusso base gestiscono il punto di ingresso, le diramazioni logiche e l'output finale verso l'utente.
Begin
Funzione: Punto di ingresso obbligatorio di ogni Canvas. Definisce come il flusso viene avviato e quali dati iniziali sono disponibili.
Quando usarlo: E il primo nodo di ogni Canvas. Ogni flusso deve avere esattamente un nodo Begin.
| Parametro | Tipo | Descrizione |
|---|---|---|
| mode | task | conversational | task: avvio con form strutturato. conversational: integrazione chat, riceve {{sys.query}} automaticamente. |
| inputFields | Array | Solo per mode task. Definisce i campi del form di input. |
Struttura di un campo inputFields:
| Sottocampo | Tipo | Descrizione |
|---|---|---|
name | string | Identificatore del campo, usabile come {{sys.inputs.name}} |
label | string | Etichetta visibile nel form |
type | string | text | select | date | number | Tipo del campo |
options | Array | Solo per select: lista delle opzioni disponibili |
required | boolean | Se il campo e obbligatorio prima dell'avvio |
placeholder | string | Testo suggerito nel campo |
Output disponibili:
| Variabile | Descrizione |
|---|---|
{{sys.query}} | Testo del messaggio utente (mode conversational) |
{{sys.inputs.nomeField}} | Valore di un campo del form (mode task) |
{{sys.user_id}} | ID utente corrente |
{{sys.company_id}} | ID azienda corrente |
{{sys.conversation_id}} | ID conversazione corrente |
{{sys.timestamp}} | Timestamp di avvio del flusso (ISO 8601) |
Esempio — Form assicurativo:
mode: task
inputFields:
- name: tipoSinistro
label: Tipo di Sinistro
type: select
options: [Auto, Vita, Casa, RC, Altro]
required: true
- name: dataSinistro
label: Data del Sinistro
type: date
required: true
- name: descrizione
label: Descrizione dell'Evento
type: text
required: true
placeholder: Descrivi l'accaduto in dettaglio
- name: numeroPolizza
label: Numero Polizza
type: string
required: trueMessage
Funzione: Nodo di output che presenta il risultato finale all'utente. E il nodo terminale del flusso o di un ramo.
Quando usarlo: Alla fine di ogni ramo del flusso per mostrare una risposta. Un flusso puo avere piu nodi Message (uno per ogni ramo del Switch).
| Parametro | Tipo | Descrizione |
|---|---|---|
| content | string | Contenuto da mostrare. Accetta variabili come {{llm_1.content}}. Puo essere testo statico. |
| format | markdown | plain | Formato di rendering del testo. Usa markdown per risposte LLM. |
| showCitations | boolean | Se mostrare i badge delle fonti e le citazioni [N]. Default: true. |
Output disponibili: Il nodo Message non produce output variabili (e un nodo terminale).
Esempio — Risposta statica per topic fuori ambito:
content: |
Mi dispiace, questa domanda non rientra nell'ambito
dell'assistente attuale. Per richieste di questo tipo,
ti prego di contattare direttamente il team competente.
format: markdown
showCitations: falseEsempio — Risposta dinamica da LLM:
content: "{{llm_1.content}}"
format: markdown
showCitations: trueSwitch
Funzione: Nodo di routing che valuta condizioni logiche e instrada l'esecuzione verso rami diversi.
Quando usarlo: Quando il flusso deve comportarsi diversamente in base a una categoria, a una parola chiave nella risposta, o a un valore di un campo.
| Parametro | Tipo | Descrizione |
|---|---|---|
| conditions | Array | Lista di condizioni valutate in ordine. La prima vera viene seguita. |
| elseGoto | string | ID del nodo da raggiungere se nessuna condizione e vera. |
Struttura di una condizione:
| Sottocampo | Tipo | Descrizione |
|---|---|---|
variable | string | Variabile da valutare (es. {{categorize_1.category}}) |
operator | string | Operatore di confronto (vedi tabella sotto) |
value | string | Valore da confrontare |
goto | string | ID del nodo di destinazione se la condizione e vera |
Operatori disponibili:
| Operatore | Significato |
|---|---|
equals | Uguale a (case-insensitive) |
not_equals | Diverso da |
contains | Contiene la stringa |
not_contains | Non contiene la stringa |
starts_with | Inizia con |
ends_with | Finisce con |
greater_than | Maggiore di (numerico) |
less_than | Minore di (numerico) |
is_empty | Il valore e vuoto o null |
is_not_empty | Il valore non e vuoto |
Output disponibili: Il nodo Switch non produce output variabili, gestisce solo il routing.
Esempio — Routing per categoria:
conditions:
- variable: "{{categorize_1.category}}"
operator: equals
value: "Tecnico"
goto: llm_tecnico
- variable: "{{categorize_1.category}}"
operator: equals
value: "Commerciale"
goto: llm_commerciale
elseGoto: message_genericoIntelligenza Artificiale
Componenti che coinvolgono modelli linguistici e recupero di informazioni.
LLM
Funzione: Chiama un modello linguistico con un prompt configurabile e produce testo in output. E il componente principale per generare risposte, analisi, classificazioni e trasformazioni di testo.
Quando usarlo: Per generare risposte all'utente, analizzare contenuti recuperati, sintetizzare informazioni, o classificare testo in modalita freeform.
| Parametro | Tipo | Descrizione |
|---|---|---|
| model | writer | planner | writer: Qwen3-80B, risposte articolate e ragionamento profondo. planner: Qwen3-30B, classificazioni rapide e task semplici. |
| systemPrompt | string | Istruzioni di contesto per il modello (persona, regole, formato output). Accetta variabili. |
| userPrompt | string | Il testo effettivo della richiesta al modello. Accetta variabili. |
| temperature | number | Creativita della risposta. 0.1-0.3 per risposte fattuali, 0.7-0.9 per testo creativo. Default: 0.3. |
| maxTokens | number | Lunghezza massima della risposta in token. Default: 2048. Max: 8192. |
| jsonMode | boolean | Se true, il modello produce un oggetto JSON valido. Utile per estrarre dati strutturati. Default: false. |
Output disponibili:
| Variabile | Descrizione |
|---|---|
{{llm_N.content}} | Testo completo generato dal modello |
{{llm_N.usage.promptTokens}} | Token usati nel prompt |
{{llm_N.usage.completionTokens}} | Token usati nella risposta |
Esempio — Analisi con JSON Mode:
model: planner
systemPrompt: |
Sei un classificatore. Rispondi SOLO con JSON valido,
senza testo aggiuntivo.
userPrompt: |
Classifica questo testo come POSITIVO, NEGATIVO o NEUTRO.
Testo: {{sys.query}}
Rispondi con: {"sentiment": "POSITIVO|NEGATIVO|NEUTRO", "confidence": 0.0-1.0}
temperature: 0.1
jsonMode: trueEsempio — Analisi documentale:
model: writer
systemPrompt: |
Sei un perito assicurativo senior. Analizza la documentazione
fornita e fornisci una valutazione tecnica dettagliata.
Cita sempre le fonti con [N]. Rispondi in italiano.
userPrompt: |
Tipo sinistro: {{sys.inputs.tipoSinistro}}
Data: {{sys.inputs.dataSinistro}}
Documenti di polizza e normativa applicabile:
{{retrieval_1.formalized_content}}
Descrizione evento:
{{sys.inputs.descrizione}}
Fornisci: 1) Valutazione copertura 2) Normativa applicabile 3) Documentazione aggiuntiva richiesta
temperature: 0.2
maxTokens: 4096Retrieval
Funzione: Esegue una ricerca ibrida (semantica + full-text) nei documenti aziendali, nella Knowledge Base e nelle sorgenti esterne abilitate. Restituisce i passaggi piu pertinenti alla query.
Quando usarlo: Ogni volta che il flusso ha bisogno di contesto documentale. E il nodo che connette le domande dell'utente al patrimonio informativo dell'organizzazione.
| Parametro | Tipo | Descrizione |
|---|---|---|
| query | string | Testo di ricerca. Usa {{sys.query}} o una variabile elaborata. Accetta testo statico combinato con variabili. |
| topK | number | Numero massimo di passaggi da recuperare. Range: 5-50. Default: 10. |
| scoreThreshold | number | Soglia minima di pertinenza (0.0-1.0). Passaggi sotto soglia vengono esclusi. Default: 0.5. |
| useReranking | boolean | Se applicare il reranker BGE per riordinare i risultati. Consigliato per qualita. Default: true. |
| companyDocs | boolean | Cerca nei documenti aziendali caricati. Default: true. |
| knowledgeBase | boolean | Cerca nella Knowledge Base curata. Default: true. |
| legalSources | boolean | Cerca in Normattiva (fonti normative italiane ed europee). Default: false. |
| foodSources | boolean | Cerca in Open Food Facts (prodotti alimentari). Default: false. |
| chemSources | boolean | Cerca in ECHA/REACH (sostanze chimiche, SDS). Default: false. |
| pharmaSources | boolean | Cerca in FDA/ClinicalTrials/PubMed (farmaci, trial, pubblicazioni). Default: false. |
| aeSources | boolean | Cerca in Agenzia delle Entrate (normativa fiscale italiana). Default: false. |
| topicIds | Array | Lista di ID topic per limitare la ricerca a specifiche categorie. Opzionale. |
Output disponibili:
| Variabile | Descrizione |
|---|---|
{{retrieval_N.formalized_content}} | Testo formattato dei passaggi trovati, pronto per un prompt LLM. Include titoli e riferimenti. |
{{retrieval_N.results}} | Array JSON dei risultati completi con score, metadata, fonte. |
{{retrieval_N.count}} | Numero di passaggi recuperati. |
Esempio — Ricerca multi-sorgente legale:
query: "{{sys.inputs.tipoSinistro}} polizza assicurativa copertura {{sys.inputs.descrizione}}"
topK: 20
useReranking: true
companyDocs: true
knowledgeBase: true
legalSources: trueCategorize
Funzione: Classifica il testo di input in una delle categorie predefinite usando un modello LLM veloce. Instrada automaticamente l'esecuzione verso il ramo corrispondente.
Quando usarlo: Per routing intelligente basato sul contenuto della domanda, senza condizioni rigide. Piu robusto di Switch per categorizzazioni semantiche.
| Parametro | Tipo | Descrizione |
|---|---|---|
| input | string | Testo da classificare. Di solito {{sys.query}}. |
| categories | Array | Lista di categorie con etichetta, descrizione e nodo di destinazione. |
| minConfidence | number | Confidenza minima richiesta. Se la classificazione scende sotto questa soglia, viene usata la categoria other. Default: 0.6. |
Struttura di una categoria:
| Sottocampo | Tipo | Descrizione |
|---|---|---|
name | string | Nome della categoria (usato come valore dell'output) |
description | string | Descrizione per aiutare il modello a classificare correttamente |
goto | string | ID del nodo di destinazione per questa categoria |
Output disponibili:
| Variabile | Descrizione |
|---|---|
{{categorize_N.category}} | Nome della categoria assegnata |
{{categorize_N.confidence}} | Confidenza della classificazione (0.0-1.0) |
{{categorize_N.reasoning}} | Breve spiegazione della classificazione |
Esempio — Routing per tipo di domanda:
input: "{{sys.query}}"
minConfidence: 0.65
categories:
- name: Tecnico
description: Domande su prodotti, specifiche tecniche, manuali, installazioni, guasti
goto: llm_tecnico
- name: Commerciale
description: Domande su prezzi, offerte, contratti, promozioni, disponibilita
goto: llm_commerciale
- name: Normativo
description: Domande su leggi, regolamenti, certificazioni, obblighi di legge
goto: retrieval_normativo
- name: Altro
description: Domande non pertinenti all'ambito aziendale
goto: message_fuori_ambitoAgent
Funzione: Esegue un ciclo ReAct (Reasoning + Acting) autonomo. Il modello decide quale strumento usare, lo chiama, valuta il risultato e decide se servono ulteriori passi o se la risposta e completa.
Quando usarlo: Per task che richiedono ragionamento multi-step non determinabile a priori. L'Agent e piu flessibile di una sequenza fissa ma piu lento. Usa il modello writer per la massima qualita.
| Parametro | Tipo | Descrizione |
|---|---|---|
| systemPrompt | string | Descrizione del ruolo e delle istruzioni per l'agente. |
| userPrompt | string | Il task da eseguire. Accetta variabili. |
| tools | Array | Lista degli strumenti disponibili (vedi tabella sotto). |
| maxRounds | number | Numero massimo di iterazioni ReAct. Default: 5. Max: 10. |
| model | writer | planner | Modello da usare. writer per task complessi. |
Strumenti disponibili:
| Tool ID | Descrizione |
|---|---|
retrieval | Ricerca nei documenti aziendali e KB |
legal_search | Ricerca in Legal Sources (Normattiva) |
pharma_search | Ricerca in Pharma Sources (FDA/PubMed) |
food_search | Ricerca in Food Sources (Open Food Facts) |
chem_search | Ricerca in Chem Sources (ECHA/REACH) |
graph_query | Query sul grafo Neo4j (entita e relazioni) |
Output disponibili:
| Variabile | Descrizione |
|---|---|
{{agent_N.content}} | Risposta finale elaborata dall'agente |
{{agent_N.steps}} | Array JSON dei passi ReAct eseguiti |
{{agent_N.toolCalls}} | Numero totale di tool call effettuate |
Esempio:
systemPrompt: |
Sei un ricercatore esperto in normativa alimentare europea.
Usa gli strumenti disponibili per rispondere con precisione,
citando sempre le fonti normative.
userPrompt: "{{sys.query}}"
tools: [retrieval, food_search, legal_search]
maxRounds: 6
model: writerInterazione Utente
UserFillUp
Funzione: Sospende l'esecuzione del flusso e mostra un form all'utente per raccogliere informazioni aggiuntive. Quando l'utente invia il form, l'esecuzione riprende dal punto successivo.
Quando usarlo: Quando il flusso ha bisogno di documenti, dati o chiarimenti che non erano disponibili all'avvio. Tipico nei flussi di gestione sinistri, audit o due diligence.
| Parametro | Tipo | Descrizione |
|---|---|---|
| message | string | Messaggio mostrato all'utente prima del form. Spiega cosa e necessario e perche. Accetta variabili. |
| fields | Array | Campi del form (stessa struttura di Begin inputFields, con aggiunta di type: file). |
| tips | string | Suggerimenti opzionali mostrati sotto il form (es. "Accetta PDF, JPG, PNG fino a 10MB"). |
Tipo campo aggiuntivo per UserFillUp:
| Tipo | Descrizione |
|---|---|
file | Caricamento file. Supporta PDF, DOCX, immagini. Il file viene vettorizzato e disponibile come documento temporaneo. |
Output disponibili:
| Variabile | Descrizione |
|---|---|
{{userfillup_N.inputs.nomeField}} | Valore del campo compilato dall'utente |
{{userfillup_N.inputs.nomeFile}} | Riferimento al file caricato (se type: file) |
Esempio:
message: |
La documentazione iniziale non e sufficiente per confermare
la copertura. Ti chiediamo di fornire i seguenti documenti:
fields:
- name: fotoDanno
label: Foto del danno
type: file
required: true
- name: perizia
label: Perizia tecnica (se disponibile)
type: file
required: false
- name: note
label: Note aggiuntive
type: text
required: false
placeholder: Informazioni aggiuntive sull'accaduto
tips: "Formati accettati: PDF, JPG, PNG, DOCX. Dimensione massima: 20MB per file."Manipolazione Dati
Componenti per trasformare, combinare e filtrare dati all'interno del flusso.
VariableAssigner
Funzione: Crea o trasforma variabili combinando valori esistenti. Utile per costruire testi composti, unire array o preparare dati per i nodi successivi.
Quando usarlo: Per costruire stringhe di query da piu input, unire output di nodi diversi, o preparare dati strutturati.
| Parametro | Tipo | Descrizione |
|---|---|---|
| assignments | Array | Lista di assegnazioni variabile → valore. |
Struttura di un'assegnazione:
| Sottocampo | Tipo | Descrizione |
|---|---|---|
name | string | Nome della variabile di output |
type | concat | merge | array | custom | Tipo di operazione |
value | string / Array | Valore o template. Per concat: stringa con variabili. Per merge: oggetti da unire. Per array: lista di valori. |
Output disponibili:
| Variabile | Descrizione |
|---|---|
{{variableassigner_N.nomeVariabile}} | Valore assegnato alla variabile definita |
Operazioni disponibili:
| Tipo | Uso |
|---|---|
concat | Concatena stringhe e variabili in un unico testo |
merge | Unisce oggetti JSON |
array | Crea un array da una lista di valori |
custom | Espressione di trasformazione freeform |
Esempio — Costruire query composta:
assignments:
- name: queryCompleta
type: concat
value: "Sinistro {{sys.inputs.tipoSinistro}} del {{sys.inputs.dataSinistro}}: {{sys.inputs.descrizione}}"VariableAggregator
Funzione: Raccoglie il primo valore non vuoto tra piu sorgenti variabile. Utile per gestire fallback quando un nodo puo non produrre output.
Quando usarlo: Quando piu rami del flusso possono produrre un risultato e vuoi passare il primo disponibile al nodo successivo.
| Parametro | Tipo | Descrizione |
|---|---|---|
| sources | Array | Lista di variabili da controllare in ordine. Viene usata la prima non vuota. |
| outputName | string | Nome della variabile di output aggregata. |
Output disponibili:
| Variabile | Descrizione |
|---|---|
{{variableaggregator_N.outputName}} | Primo valore non vuoto tra le sorgenti |
Esempio — Fallback tra due LLM:
sources:
- "{{llm_writer.content}}"
- "{{llm_planner.content}}"
outputName: rispostaFinaleDataOperations
Funzione: Applica trasformazioni su array e testi: filtro, mappa, ordinamento, taglio, estrazione, unione, divisione, deduplicazione.
Quando usarlo: Per elaborare liste di risultati (es. filtrare trial clinici per fase, estrarre solo i titoli, deduplicare per ID).
| Parametro | Tipo | Descrizione |
|---|---|---|
| input | string | Variabile di input da elaborare (tipicamente un array JSON). |
| operation | string | Tipo di operazione da applicare (vedi tabella). |
| params | object | Parametri specifici dell'operazione. |
Operazioni disponibili:
| Operazione | Descrizione | Parametri chiave |
|---|---|---|
filter | Filtra elementi che soddisfano una condizione | field, operator, value |
map | Trasforma ogni elemento estraendo un campo | field |
sort | Ordina per un campo | field, direction (asc/desc) |
slice | Prende una porzione dell'array | start, end |
extract | Estrae un campo da ogni oggetto | field |
join | Unisce gli elementi dell'array in una stringa | separator |
split | Divide una stringa in array | separator |
deduplicate | Rimuove duplicati | field (campo chiave per dedup) |
Output disponibili:
| Variabile | Descrizione |
|---|---|
{{dataoperations_N.result}} | Risultato dell'operazione |
{{dataoperations_N.count}} | Numero di elementi risultanti |
Esempio — Filtrare trial clinici per fase:
input: "{{retrieval_1.results}}"
operation: filter
params:
field: metadata.phase
operator: contains
value: "Phase 3"Cicli
Componenti per iterare su liste di elementi o ripetere blocchi fino a soddisfare una condizione.
Iteration
Funzione: Itera su ogni elemento di un array, eseguendo una sotto-sequenza di nodi per ciascuno.
Quando usarlo: Per elaborare una lista di elementi uno per uno — ad esempio analizzare ogni trial clinico trovato, o processare ogni documento in un elenco.
| Parametro | Tipo | Descrizione |
|---|---|---|
| input | string | Variabile array su cui iterare. |
| iterationNodeIds | Array | Lista degli ID dei nodi da eseguire per ogni elemento. |
Variabili di contesto disponibili durante l'iterazione:
| Variabile | Descrizione |
|---|---|
{{iter.item}} | Elemento corrente dell'array |
{{iter.index}} | Indice corrente (base 0) |
{{iter.total}} | Numero totale di elementi |
Output disponibili:
| Variabile | Descrizione |
|---|---|
{{iteration_N.results}} | Array con i risultati di ogni iterazione |
{{iteration_N.count}} | Numero di iterazioni completate |
Esempio — Analizzare ogni trial clinico:
input: "{{dataoperations_1.result}}"
iterationNodeIds: [llm_analisi_trial]All'interno di llm_analisi_trial, usa {{iter.item.title}}, {{iter.item.phase}}, ecc.
Loop
Funzione: Ripete un blocco di nodi finche una condizione e vera o viene raggiunto il numero massimo di iterazioni. Utile per raffinamento iterativo o ricerca approfondita.
Quando usarlo: Per processi di raffinamento dove non conosci a priori quante iterazioni servono — ad esempio ricerca progressiva fino a trovare la risposta o raggiungere la confidenza desiderata.
| Parametro | Tipo | Descrizione |
|---|---|---|
| condition | string | Espressione booleana: il loop continua finche e true. Accetta variabili. |
| maxIterations | number | Limite massimo di iterazioni per evitare loop infiniti. Default: 5. Max: 20. |
| loopNodeIds | Array | Lista degli ID dei nodi da eseguire ad ogni iterazione. |
Variabili di contesto disponibili durante il loop:
| Variabile | Descrizione |
|---|---|
{{loop.iteration}} | Numero iterazione corrente (base 1) |
{{loop.previousResult}} | Output dell'iterazione precedente |
Output disponibili:
| Variabile | Descrizione |
|---|---|
{{loop_N.finalResult}} | Risultato dell'ultima iterazione eseguita |
{{loop_N.iterations}} | Numero totale di iterazioni eseguite |
{{loop_N.exitedEarly}} | true se il loop e uscito per ExitLoop |
ExitLoop
Funzione: Esce immediatamente dal Loop corrente, anche se la condizione del Loop e ancora vera. Posizionato all'interno del blocco di nodi del Loop.
Quando usarlo: Per uscire dal loop quando una condizione specifica e soddisfatta prima di raggiungere maxIterations — ad esempio quando la confidenza e sufficiente.
| Parametro | Tipo | Descrizione |
|---|---|---|
| condition | string | Esce dal loop se questa condizione e true. Se omessa, esce sempre quando raggiunto. |
Esempio — Loop con uscita anticipata:
Loop (condition: "{{llm_eval.confidence}} < 0.8", maxIterations: 4)
→ Retrieval (query affinata)
→ LLM (valutazione confidenza)
→ ExitLoop (condition: "{{llm_eval.confidence}} >= 0.8")Composizione
Invoke
Funzione: Esegue un altro Canvas come sotto-flusso. Permette di riutilizzare flussi esistenti come blocchi modulari.
Quando usarlo: Per scomporre flussi complessi in moduli riutilizzabili, o per chiamare un Canvas specializzato (es. un analizzatore legale) da piu Canvas diversi.
| Parametro | Tipo | Descrizione |
|---|---|---|
| canvasId | string | ID del Canvas da invocare. |
| inputMapping | object | Mappa tra variabili del Canvas corrente e input attesi dal sub-Canvas. |
| timeout | number | Timeout in millisecondi per il completamento del sub-Canvas. Default: 30000. |
Output disponibili:
| Variabile | Descrizione |
|---|---|
{{invoke_N.output}} | Output completo del sub-Canvas |
{{invoke_N.status}} | success | error | timeout |
Esempio — Invocare un analizzatore legale:
canvasId: "canvas_analisi_normativa_abc123"
inputMapping:
query: "{{sys.inputs.tipoContratto}} {{sys.inputs.descrizione}}"
topicId: "legale"
timeout: 45000Riepilogo Output per Componente
| Componente | Variabile Output Principale |
|---|---|
| Begin | {{sys.query}}, {{sys.inputs.campo}} |
| LLM | {{llm_N.content}} |
| Retrieval | {{retrieval_N.formalized_content}}, {{retrieval_N.results}} |
| Categorize | {{categorize_N.category}}, {{categorize_N.confidence}} |
| Agent | {{agent_N.content}} |
| UserFillUp | {{userfillup_N.inputs.campo}} |
| Switch | (nessun output, solo routing) |
| Message | (nessun output, nodo terminale) |
| VariableAssigner | {{variableassigner_N.nomeVar}} |
| VariableAggregator | {{variableaggregator_N.outputName}} |
| DataOperations | {{dataoperations_N.result}} |
| Iteration | {{iteration_N.results}} |
| Loop | {{loop_N.finalResult}} |
| ExitLoop | (nessun output, gestisce il loop) |
| Invoke | {{invoke_N.output}} |
Nomi automatici dei nodi
Il Canvas assegna nomi automatici ai nodi (llm_1, retrieval_2, ecc.) in base al tipo e all'ordine di inserimento. Puoi vedere il nome assegnato nell'header del nodo nel workspace. Il nome e usato come namespace nelle variabili.
Queria v3.1.2 -- Canvas Agent Builder