Memory
Memory is how your assistant remembers things about the customer between turns - and between agents. Every agent reads and writes the same pool, so what one agent learns, the next one knows.
You declare the variables you want to keep at AI agents → Configuration → Memory. Declaring a variable doesn't store anything by itself; it tells the platform this value is worth remembering, what shape it is, and what it means.
When you need memory (and when you don't)
If you only need to pass a value into a tool or workflow, you don't need memory. The tool picks its inputs up from its own input mapping at execution time.
Reach for memory when a later turn, or a different agent, needs to know something.
Tool input mapping → moving data between a turn and a tool call
Memory → context you want to remember across turns
The test is whether the value outlives the turn that produced it. An order ID you look up, format, and immediately read back doesn't need to be remembered. An order ID the customer will refer to five turns later does.
Which scope it belongs in
Once you've decided a value is worth keeping, decide who should be able to see it. There are three scopes, and an Agent node's Allowed variables picker offers all three in one list, tagged by scope.
| Scope | Created | Lasts | Read by |
|---|---|---|---|
| Global | on this page | the conversation | every agent and every flow |
| Journey | inside a multi agent | one run of that flow | the nodes of that flow |
| User | your CDP | the customer's lifetime | everything, read-only |
The rule: global if another agent needs it, journey if only this flow does.
Note that isn't the same as "will a later turn need it". A later turn inside the same flow is exactly what journey variables are for. The question is whether anything outside this flow has to read the value.
What usually belongs in global
The things every agent would otherwise look up for itself:
- Who the customer is — the identity or account record, resolved once
- What they're entitled to — plan, tier, role, eligibility flags that gate what any agent may offer
- Where the conversation has got to — which service they chose, whether identity was verified
The last one is worth calling out: if a flow verifies identity and a different agent later needs to know it happened, that flag has to be global. Journey scope dies with the flow run.
What usually stays journey-scoped
Anything that's scaffolding for one procedure: the raw values a flow collects on its way to an outcome, retry state, a slot list you're about to offer. Making these global costs you twice — they're prompt weight on every turn for every agent, and they're names that can now collide with something else.
Same name, two scopes
A global and a journey variable can share a name, and the global wins on read. Nothing in the flow shows you which one you're reading, and there's no warning.
That makes it worth prefixing anything flow-specific — letter_year, booking_date — rather than reusing a generic year or date that a global might already own.
Declaring a variable
Each variable has four fields:
| Field | Required | Notes |
|---|---|---|
| Variable name | Yes | Letters, digits and underscores, starting with a letter or underscore. Up to 100 characters |
| Data type | Yes | string, number, boolean, object or array |
| Default value | No | Seeded when the conversation starts |
| Description | Yes | What it means and when to use it. Up to 500 characters |
You can hold up to 500 variables.
The description isn't documentation - the model reads it. It's how the agent decides whether this is the variable to write a value into. "The customer's confirmed delivery address, set once they've approved it" is a usable instruction; "address" isn't.
Name variables for what they hold. delivery_full_address, name_on_order and account_tier tell the next person - and the model - what's inside. data1, temp, data_temp2 tell them nothing, and make collisions much harder to spot.
Once you have more than a screenful, the search box and the data-type filter above the list are the fastest way back to one.
Where a variable is used
Each variable shows what references it, split into two kinds you'll recognise: Agents and Flows. It's worth looking before you edit one - a rename or a type change lands everywhere at once.
It also protects you on delete. An unused variable goes immediately. One that's still referenced opens a confirmation first:
Delete 'order_id'? This variable is used in 3 places. Deleting it may break it.
with every referencing agent and flow listed underneath. It's a warning, not a block - you can still delete it, so read the list rather than clicking through.
How memory behaves at runtime
This is the part most people get wrong. Everything declared on this page is global — one pool, shared by every agent in the conversation. There's no per-agent partition among them, whatever the UI grouping suggests.
That's true of the variables you declare here. It is not true of journey variables, which belong to one flow run and are gone when it ends.
In practice:
- Memory survives agent handoffs. If the billing agent writes
last_invoice_id, the support agent can read it on the next turn. - Memory survives short breaks. The window resets on every customer message and is 60 minutes by default. It's configurable per assistant, so check yours if a long gap matters to your use case.
- Memory is per customer. Two customers talking to the same assistant have completely separate memory.
Because every agent sees every other agent's writes, colliding names silently overwrite each other. Two agents that both write status will clobber one another with no error. Prefix anything agent-specific - billing_status, returns_status - whenever there's a chance of overlap.
Upgrading to unified memory
If your variables are still scoped to one agent, the Memory page offers to make them shared:
Share memory across every agent and workflow Make this agent's variables global so every agent and workflow can read and write them.
After upgrading, every agent and every flow reads and writes the same variables, and you get the usage tracking described above - references aren't tracked for per-agent variables.
Two things to know before you click:
- It's a one-way change. Variables become global; there's no toggle back.
- You upgrade on staging, not production. On a production assistant the button is replaced by "Unified memory is upgraded on the staging agent and arrives here when you publish." Do it on staging, test, then publish.
Best practices
- Declare what you depend on. If an agent reads
customer_tier, declare it - even when a different agent is what writes it. Declarations are the only documentation the next person editing this has. - Reference declared variables in prompts; don't improvise. Before writing an agent's instructions, decide which variables it reads and writes, and use those names. A prompt that invents a variable mid-sentence is pointing at something nothing seeds and nothing persists. (Variables local to a multi agent flow are separate - those are scoped to the flow.)
- Use workflow-returned values as-is. When a tool returns a value, store and reuse it verbatim. Asking the model to reformat or "correct" it gets you silent corruption.
Bad: prompt the model to re-title-case the city a lookup returned. Good: store
result.normalized_city- the value the workflow already normalised - and treat it as canonical. - Set a default when something reads before anything writes. Without one the variable is
undefineduntil first written, and a tool downstream may receive an empty payload. - Don't use memory as a scratchpad. The window resets on activity but isn't indefinite. If a value only matters inside one turn, pass it through tool input mapping instead.
- Don't put secrets in memory. It's conversation-scoped, not encrypted storage. Tokens and credentials belong in tool configuration.
Next: Lifecycle hooks - run a workflow around a turn.