> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.userbot.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.userbot.ai/_mcp/server.

# La sintassi dei riferimenti

Dentro un workflow, ogni campo di configurazione accetta un valore fisso oppure
un **riferimento**: un percorso fra doppie parentesi graffe, che a ogni
esecuzione viene sostituito con il dato vero.

Il modo pratico per costruirli è **Inserisci contesto**, che apre l'albero dei
dati disponibili e scrive il percorso al posto tuo. In cima all'albero c'è
**Input Run**, l'input dell'esecuzione; sotto, i blocchi a monte. Questa pagina
serve quando devi leggere un riferimento scritto da altri, o capire perché uno
non funziona.

## Le due forme ammesse

Nei campi dei blocchi le forme sono due, e non ne esistono altre. L'unica
eccezione sono i rami **Manuale** della Condizione, descritti più sotto.

| Forma                                                                                 | Cosa richiama                                                                     |
| ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `{{$input.percorso}}`                                                                 | Un dato dell'**input dell'esecuzione**, cioè quello con cui il workflow è partito |
| `{{riferimentoBlocco.input.percorso}}` oppure `{{riferimentoBlocco.output.percorso}}` | Un dato di un blocco che ha già girato                                            |

Il **secondo segmento deve essere `input` o `output`**. Non ci sono alternative:
`{{agent.risultato}}` non è un riferimento valido, e fa fallire il passaggio.

Dopo il secondo segmento il percorso scende dentro i dati con i punti, e i numeri
servono per gli elementi di un elenco: `{{hTTPRequest.output.body.items.0.id}}`.

Cosa c'è in `$input` dipende da come è partito il flusso. Dalla chat trovi il
messaggio dell'utente, in `$input.userMessage.text` e
`$input.userMessage.attachments`. Da un webhook trovi i dati inviati in
`$input.data`. Da un evento di un'app li trovi nell'output del Trigger. Se il
flusso non è partito da una chat, `$input.userMessage` è vuoto ma non fa fallire
il passaggio.

## Il riferimento di un blocco non è il suo titolo

Il primo segmento è il **riferimento** del blocco, non il nome che gli hai dato
sulla tela. È assegnato alla creazione, deriva dal tipo del blocco, e non cambia
se rinomini il blocco.

| Blocco                    | Riferimento        |
| ------------------------- | ------------------ |
| Trigger                   | `trigger`          |
| Agente                    | `agent`            |
| Invia messaggio           | `sendMessage`      |
| Richiesta dati            | `requestData`      |
| QR Code                   | `qrCode`           |
| Scala ad umano            | `scalaSuOperatore` |
| Condizione                | `condition`        |
| Pausa                     | `pause`            |
| Chiama workflow           | `callWorkflow`     |
| Codice                    | `code`             |
| HTTP request              | `hTTPRequest`      |
| Invia email               | `sendEmail`        |
| Ricerca knowledge         | `knowledgeSearch`  |
| AI Core                   | `aiCore`           |
| Ricerca web               | `webSearch`        |
| Azioni delle integrazioni | `integrationTool`  |

Dal secondo blocco dello stesso tipo si aggiunge un numero: `agent2`, `agent3`.
L'elenco completo, blocco per blocco, sta nel
[Riferimento dei blocchi](/riferimento-blocchi).

## `input` non sono i dati in arrivo

È il punto che confonde di più. Per ogni blocco che ha girato ci sono due
insiemi di dati, e il primo non è quello che sembra.

* **`output`** è quello che il blocco ha prodotto: la risposta di una chiamata, i
  campi di un modulo, i messaggi di un agente. È quello che serve quasi sempre.
* **`input`** è la **configurazione del blocco già risolta**: i suoi campi con i
  riferimenti sostituiti dai valori veri di quel giro. Non sono i dati che gli
  sono arrivati dal blocco a monte.

Se vuoi sapere con quale indirizzo è partita una chiamata, guardi
`hTTPRequest.input.url`. Se vuoi sapere cosa ha risposto, guardi
`hTTPRequest.output.body`.

![Un passaggio della traccia aperto sui suoi due pannelli, Input sopra e Output sotto: sono due insiemi separati, e si leggono uno alla volta. Qui nell'Output ci sono lo stato della chiamata e l'identificativo che ha restituito](/_fern-img/84e5a1f9c38c1efc60d21461fbdfe9467def1ab85261736bfca3f8700fa01650.webp)

## Il tipo del dato dipende da come scrivi il campo

La differenza è sottile e cambia il risultato.

* **Un'espressione da sola**, che occupa tutto il campo, **conserva il tipo**: se
  il dato è un numero resta un numero, se è un elenco resta un elenco, se è un
  oggetto resta un oggetto.
* **Un'espressione dentro una frase diventa testo.** Scrivendo
  `Ticket {{hTTPRequest.output.body.id}} aperto` ottieni una stringa, anche se
  l'identificativo era un numero.

Conta quando il campo a valle si aspetta un tipo preciso: il corpo JSON di una
chiamata, un valore numerico, un elenco da passare a un altro workflow. Se ti
serve il tipo originale, lascia l'espressione da sola nel campo.

## Le espressioni nei rami Manuali della Condizione

Un ramo **Manuale** della Condizione non sostituisce un valore: fa una domanda
sui dati, e la risposta è vero o falso. Per questo, solo lì, fra le doppie graffe
si scrive un confronto.

```
{{hTTPRequest.output.status === 200}}
{{requestData.output.paese === "IT" && requestData.output.importo > 1000}}
{{$input.userMessage.text.includes("urgente")}}
```

I percorsi si scrivono come negli altri campi. Si possono confrontare con `==`,
`===`, `!=`, `!==`, `>`, `<`, `>=`, `<=`, unire con `&&` e `||`, negare con `!`,
e sui testi si usano `includes`, `startsWith` ed `endsWith`. Fuori dalla
Condizione la stessa espressione non viene calcolata.
→ [Riferimento dei blocchi](/riferimento-blocchi)

## Un percorso inesistente fa fallire il passaggio

Se il percorso non porta a nessun dato (perché il blocco non ha ancora girato,
perché quel campo in quel caso non c'era, perché il riferimento è scritto male)
il passaggio **fallisce** e il suo ramo si ferma lì. Fanno eccezione **Ricerca
knowledge**, che esce da **Errore**, e le azioni delle integrazioni, che seguono
quello che hai scelto in **In caso di errore**.

È voluto: meglio un errore chiaro che una email inviata con l'oggetto vuoto. La
conseguenza pratica è che i campi facoltativi vanno trattati come tali. Se un
sistema esterno restituisce il numero di telefono solo qualche volta, non
scriverlo in un campo obbligatorio a valle.

## Errori frequenti

#### Ho scritto il riferimento a memoria e non funziona

Quasi sempre il primo segmento è sbagliato, perché dedotto dal titolo del
blocco invece che dal suo tipo. Cancella e riscrivilo con **Inserisci
contesto**.

#### L'albero di Inserisci contesto è vuoto

Il blocco a monte non ha mai girato, quindi non ci sono dati da mostrare.
L'albero lo dice (*Nessun dato disponibile al momento*) e offre **Esegui
nodo**: eseguilo una volta e i suoi valori compaiono.

#### Il passaggio fallisce con un riferimento non risolto

Il percorso non corrisponde a nessun dato in quel giro. Il messaggio di
errore del passaggio riporta il percorso cercato: confrontalo con l'Output
del blocco a monte.

#### Mi serve un numero e ottengo del testo

L'espressione è dentro una frase. Mettila da sola nel campo, e il tipo si
conserva.