Variables and memory

A graph runs once per message and remembers nothing by itself. State lives in two separate mechanisms: variables, which you control, and memory, which the conversation with the model fills in.

Variables

A variable is declared by the var node: a name, a type (string, integer, float, boolean, json, csv, dataframe), a scope and a default value. That node only reads; writing is done by var_set — the value arrives on its Input port, the reference to the declaring node on its Var port.

Entry
VariableS
Set Variable
Exit
  • Execute + Data
  • Data
var declares, var_set writes: the value goes to Input, the variable reference to Var.

On write the value is coerced to the declared type: the string "1" written into an integer variable becomes a number, so the next comparison still works. A value that cannot be coerced is stored as it is.

Three scopes

Scope How long it lives When to pick it
session One workflow run Loop counters, values passed between branches of one turn.
thread Across messages, stored in the database Conversation state: the customer’s language, a ticket number, the stage of a scenario.
call Never stored Every read answers with the default — a constant, not memory.

The key for thread is the chat thread: a web-chat session, a Telegram chat. A run with no chat behind it (a manual run, a webhook without a session) uses the run itself as the thread, so thread there behaves like session.

Reading them in templates

{{ variables.<name> }} sees session variables plus the engine’s loop_index inside while_loop. A thread variable is not part of that namespace — read it through the declaring node’s output: {{ nodes.<var node id>.output }}.

Conversation memory

Memory holds the message history and connects to ai_agent with a link_memory edge. The three nodes differ in what happens as the history grows:

  • buffer_memory — the whole history;
  • window_memory — only the last N messages (window_size, 10 by default);
  • summary_memory — older messages are compressed into a summary by a model: by default compression starts past 20 messages and the latest 6 stay verbatim. The model comes from the parent agent or from a dedicated link_llm edge.

All three take the same thread / session / call scope, defaulting to thread — the history survives between messages of one chat. The key is the node plus the thread, so two memory nodes in one graph keep two separate histories.

llm_response has no memory port: use its own chat-history option or the chat_history node.

Agent memory

agent_memory is not a history but a long-lived key-value store the agent maintains itself. The node is attached with a link_extension edge and the model gets tools to store, delete and clear entries (expose_tools, with the set chosen in enabled_tools). An initial state can be set in the configuration.

The difference from variables is who writes:

VariablesAgent memory
Who writesGraph nodes — you decide whenThe model, through a tool call
Who readsTemplates and nodesThe model, in its own context
ShapeOne typed value per nameA key-value dictionary

If the graph needs the value (a condition, a filter, a request field), use a variable. If the model has to remember it between turns, use agent memory.

Inspecting and clearing

Open a run, click a node and switch to the “State” tab. Memory nodes show the message history, agent memory shows the dictionary; the scope is printed beside it and there is a “Clear state” action. The tab appears only for nodes that serve state — a thread variable cannot be inspected this way, so surface it through a node in the graph.

app.iterna.ai

Node inspector

agent_memory_1

Scope: thread

Clear state
KeyValue
client_nameMaria
order_idA-1043
stagewaiting_payment
The State tab of a memory node.