# Set state

Écrit des variables nommées dans le contexte du run pour qu'un nœud aval, même très éloigné, puisse les relire.

## Vue d'ensemble

`last_output` ne reflète que le **nœud précédent**. Dès qu'un autre nœud s'exécute, la valeur d'avant disparaît. **Set state** te permet de sauvegarder une valeur sous un nom stable (`customer_email`, `reply_draft`, `page_cursor`…) et de la référencer 1 ou 10 nœuds plus loin via `{state.<clé>}`.

L'état vit le temps d'**un seul run** (y compris à travers toutes les itérations d'un While). Il n'est **pas** persistant entre les runs — chaque exécution démarre avec un contexte neuf.

À utiliser quand :

- Tu vas réutiliser la même valeur **plus d'une fois** en aval.
- La valeur vient d'un nœud qui tourne **avant** un Agent / HTTP qui écraserait sinon `last_output`.
- Tu veux un seul endroit pour mettre à jour une constante du workflow (signature, modèle par défaut, id de canal…).

## Configuration

| Champ | Description |
| --- | --- |
| `key` | Nom de la variable. Snake_case. Évite les clés réservées (`input`, `last_output`, `event`, `webhook`, `condition_result`, `status`, `result`). |
| `value` | Valeur à écrire. Les chaînes supportent les `{placeholders}` — résolus au moment où le nœud s'exécute. |
| `values` | Forme batch : `{page: 1, cursor: ""}` écrit les deux d'un coup. |

## Lecture de l'état

Deux syntaxes équivalentes :

| Template | Résout en |
| --- | --- |
| `{state.greeting}` | La valeur stockée sous `greeting` (recommandée — namespace explicite) |
| `{greeting}` | Même valeur (raccourci) |

## Templates dans `value`

Le champ `value` accepte les mêmes placeholders que n'importe quel autre nœud. Exemples :

| Template `value` | Comportement |
| --- | --- |
| `bonjour` | Stocke la chaîne littérale `"bonjour"` |
| `{event.body.email}` | Lit le payload du webhook, stocke l'email |
| `{last_output.priority}` | Lit un champ d'une sortie JSON précédente |
| `{state.first} {state.last}` | Compose une valeur depuis l'état existant |

> Les templates résolvent **une fois**, à l'exécution du nœud. Si `{event.body.email}` est vide à ce moment-là, la chaîne littérale `{event.body.email}` est stockée — vérifie en amont que la valeur existe.

## Exemple : réponse à un client

```
Webhook → Set state (customer_email = {event.body.from})
        → Set state (language       = {event.body.lang})
        → Agent (rédige la réponse)         ← le last_output de l'agent écrase ici
        → Set state (reply_draft = {last_output})
        → HTTP Request (POST /send)
            body: {"to": "{state.customer_email}", "subject": "Re: support [{state.language}]", "html": "{state.reply_draft}"}
        → Respond to Webhook
            body: {"status": "sent", "to": "{state.customer_email}"}
```

Sans set state, tu perds `customer_email` dès que l'agent tourne, et tu dois aller relire `{event.body.from}` à 3 endroits différents.

## Pièges

- Le nœud ne modifie **pas** `last_output` — les conditions aval voient toujours la sortie du nœud précédent.
- Les placeholders dans `value` résolvent au moment de l'écriture. Un set state placé tout en haut ne peut pas référencer une valeur qui n'existe pas encore.
- L'arithmétique dans `value` ne marche pas : `{state.x}+1` stocke la chaîne littérale `"42+1"`. Passe par un nœud **Transform** pour du vrai calcul.
- Ne mets pas de secrets dans le state — ils apparaissent dans les logs de run. Utilise le store **Credentials**.
- Un objet stocké en state peut être indexé : `{state.user.email}`.

## Changements récents

- `value` est désormais templaté à l'écriture (était stocké littéralement avant).
- Nouveau namespace `{state.<clé>}` à côté du raccourci legacy `{<clé>}`.
- Nouvel alias trigger-agnostique `{event.*}` : `{event.body.X}` fonctionne pour les triggers webhook, schedule et event listener.

---

*Source: https://agentbuilder.systalink.sn/docs/node-set-state — human documentation.*
*Other language: [/docs-md/en/node-set-state.md](/docs-md/en/node-set-state.md).*
*Machine-readable index: [/llms.txt](/llms.txt).*
