Session State & Memory for Google ADK Agents
The official ADK sessions / state guide and memory guide describe a powerful but unforgiving model: misuse a state prefix and you can leak one user's data into another user's session.
This page covers how to use ADK's three state scopes correctly and how to choose between the available MemoryService implementations.
The three state prefixes
ADK organizes session state by prefix. The prefix is not decorative — it changes who can read the value and how long it persists.
| Prefix | Scope | Persistence | Example |
|---|---|---|---|
| No prefix | This session only | Until the session ends | state["last_search_query"] |
user: | All sessions for this user | Across sessions for the same user | state["user:preferred_language"] |
app: | All sessions for all users in this app | Tenant-wide | state["app:enabled_features"] |
temp: | This single LLM call only | Wiped after one turn | state["temp:retry_count"] |
Get the prefix wrong and either:
- A user's preference leaks to another user (
app:when you meantuser:) - Settings vanish unexpectedly (no prefix when you needed
user:) - Per-turn state pollutes across turns (no
temp:prefix on transient data)
Checklist
1. Audit every state[...] write in your agent
Before deploying a Google ADK agent to production, grep your agent code for state[ and verify each write uses the intended prefix. Treat this like a security review — because it is one.
2. Choose the right MemoryService for cross-session recall
ADK ships three implementations of MemoryService for long-term memory beyond the active session:
| Service | When to use | Tradeoffs |
|---|---|---|
| InMemoryMemoryService | Local development, demos | Wiped on restart; not for production |
| VertexAiMemoryBank | Production with cross-session recall | Managed by Google; pay-per-store |
| RAG-backed (Vector Search / custom) | Large knowledge corpora the agent should "recall" | You own infra; needs embedding pipeline |
Default: VertexAiMemoryBank for production unless you specifically need RAG over a large document corpus.
3. Audit memory before each release
In TraptureIQ's Sessions module, playback a representative session and verify:
- The agent recalls user-level facts (preferences, prior decisions)
- The agent does not recall facts from other users
- The agent does not treat
temp:state as durable
This 5-minute review catches most state-leak bugs.
4. Bound session length
Long sessions create three problems: cost (tokens grow), latency (longer context = slower), and state pollution (more chances for prefix bugs). Enforce a session length cap aligned to your use case:
| Use case | Suggested cap |
|---|---|
| Customer support chat | 30 minutes or 50 turns |
| Internal assistant | 4 hours or 200 turns |
| Long-running workflow | Use the A2A pattern, not one giant session |
5. Set a state-key naming convention
Every team eventually invents user:lang and user:language for the same thing. Prevent it:
<scope>:<feature>.<sub_feature>
user:preferences.language
user:preferences.timezone
app:features.flags.beta_search
Document the canonical key list. Treat additions like schema changes.
Anti-patterns
- Storing PII without a prefix — Lives only in the current session, which is correct in scope, but is then often duplicated into logs anyway. Use TraptureIQ's AgentGuard → PII redaction on the log path.
- Storing tokens or credentials in any state — Use a secret manager, not session state.
- Mixing memory and prompt — Don't dump memory content into the system prompt. Use ADK's
MemoryServiceretrieval at runtime so the agent reads the relevant slice. - Mutating
app:state from request handlers — Treatapp:as feature-flag-grade config, not as a write target on every request.
Where to investigate
- Session playback → Sessions
- Sessions table for cross-session inspection → Session Dashboard
- Auditing state writes → Logs (filter by
state.writeevents)
References
- ADK: Session state
- ADK: Memory
- ADK: Sessions overview