This feature is in early access. Functionality may evolve. Contact your PolyAI representative for guidance on production use.
How it works
Agent Memory is a key-value store attached to a user identifier (such as a phone number). Persist small, structured data between conversations so your agent can:- Skip repeated questions for returning callers
- Greet callers by name or reference past interactions
- Resume interrupted conversations where the caller left off
- Track handoff history and resolution status
- Read memory using
conv.memory.get("key") - Write memory by setting
conv.state["key"] = value(if the key is listed instate_keys)
Configuration
Enable Agent Memory
Navigate to Project > Settings > Experimental Config in Agent Studio and add the memory configuration:| Field | Description |
|---|---|
analytics_enabled | Adds repeat caller metrics to Studio analytics dashboards |
state_keys | Keys from conv.state that should be saved to memory at the end of the conversation |
identifier_blacklist | Optional list of identifiers to exclude (e.g., test phone numbers) |
state_keys. Memory is persisted at the end of the conversation, so only values set during the call are saved.
Using memory in functions
Reading memory
Useconv.memory.get("key") in any function to retrieve a previously stored value:
Writing memory
Set values inconv.state – they are persisted to memory at the end of the conversation if the key is listed in state_keys:
Full example: returning caller
Repeat caller analytics
Whenanalytics_enabled is set to true, Agent Memory automatically tracks five metrics for each returning caller:
| Metric | Description |
|---|---|
REPEAT_CALLER_CONV_ID | Conversation ID of the caller’s first interaction |
REPEAT_CALLER_DATETIME | Timestamp of the first interaction |
REPEAT_CALLER_QA | QA outcome from the first interaction |
REPEAT_CALLER_HANDOFF_REASON | Reason for handoff in the first interaction |
REPEAT_CALLER_HANDOFF_TO | Handoff destination from the first interaction |
Repeat caller metrics always reference the first interaction in the retention window, not the most recent one. This is by design for data privacy compliance – linking calls in a chain could allow identification beyond the retention period.
Memory behavior
Timing
- Memory is fetched once per turn from the memory service and cached. Multiple
conv.memory.get()calls in the same turn do not trigger additional lookups. - Memory is written at the end of the conversation (after the end function executes). Values set in
conv.stateduring a function on turn 1 are not available throughconv.memoryon turn 2 of the same call.
Persistence
Each write acts as a patch – it updates or adds specific keys without removing existing ones. If conversation 1 writes{"cheese_type": "gouda"} and conversation 2 writes {"booking_day": "Friday"}, the next lookup returns both fields.
Expiry
All memory identifiers and fields expire after 90 days (maximum, for GDPR compliance). Once expired, data is automatically deleted and no longer accessible.Identifiers
The current supported identifier is the caller’s phone number. This is set automatically – you do not need to configure it.Support for additional identifiers (email, account ID) and identifier linking across channels is planned for future releases.
Compliance
Key compliance considerations:- Agent Memory is not intended for automated decision-making that significantly impacts end users
- Do not store sensitive PII in a single field – separate fields allow independent expiry
- Custom memory fields cannot be used to build caller profiles
- Timestamps stored in memory should be rounded to the hour to prevent linking calls across the retention window
- All data expires within 90 days
FAQ
Can I store nested JSON?
Can I store nested JSON?
Values are stored as JSON-encoded strings. You can store structured data in a single field, but it is recommended to keep fields flat so they can expire independently – especially for anything containing PII.
Can I check if any memory exists?
Can I check if any memory exists?
Yes. Use Python’s
in operator:Can I prevent accidental overwrites?
Can I prevent accidental overwrites?
Not natively – the latest write always wins. Guard against overwrites in your code:
When are memory writes committed?
When are memory writes committed?
Memory is persisted at the end of the conversation, after the end function executes. Values set in
conv.state during a function are not available in conv.memory until the next call.Does memory work across channels?
Does memory work across channels?
Currently, memory is scoped by phone number. Support for linking identifiers across channels (voice, SMS, webchat) is planned for future releases.
How do I get all stored memory fields?
How do I get all stored memory fields?
Use the
fields() method:
