Session Isolation: Keeping One User's Agent State Separate from Another's
Cross-session leaks are security incidents, not "memory bugs."
Search across all documentation pages
Cross-session leaks are security incidents, not "memory bugs."
This cheatsheet scopes short-term agent state so tenant A never reads tenant B's history, scratchpad, or tool cache.
| Check | Rule | Failure mode if skipped |
|---|---|---|
| 1. Authenticated principal | Every turn resolves tenant_id + user_id (or service account) from verified auth, not from prompt text | Spoofed identity via message body |
| 2. Composite store keys | Session keys include tenant (and user) scope: agent:stm:{tenant}:{user}:{session} | UUID-only keys collide or get guessed across tenants |
| 3. Client session ids | Treat client-supplied session ids as untrusted labels; bind them to the principal server-side | IDOR: open another user's session by id |
| 4. No global singleton memory | Ban process-global HISTORY = [] in multi-tenant hosts | Last request wins; silent cross-talk |
| Check | Rule | Failure mode if skipped |
|---|---|---|
| 5. Authorize before GET | On load, verify the principal may access that session row/key | Horizontal privilege escalation |
| 6. Authorize before SET/DELETE | Same check on write and clear-chat | Attacker wipes or poisons others' state |
| 7. Tool cache isolation | Cache keys include tenant/user/session (or stronger); never key only by tool args | Shared cache returns other tenants' documents |
| 8. Scratchpad isolation | Pads live under the same session scope as messages | Progress state leaks across users |
| Check | Rule | Failure mode if skipped |
|---|---|---|
| 9. No ambient session in thread locals without clear | If you use contextvars/thread locals, set and clear per request | Worker reuse serves wrong session |
| 10. Queue jobs carry scope | Async workers receive tenant/user/session in the job payload and re-check authz | Background tool run attaches to wrong chat |
| 11. Log redaction | Logs use session ids, not full prompts by default; never log foreign tenant data in shared traces without ACL | Ops tools become an exfiltration path |
| 12. Multi-agent handoffs | Handoff packages stay inside the same tenant boundary; strip foreign keys | Specialist agent loads another org's pad |
| Check | Rule | Failure mode if skipped |
|---|---|---|
| 13. TTL per session class | Abandoned chats expire; legal holds are explicit, not accidental forever keys | Redis/disk fills; retained PII without purpose |
| 14. User clear / account delete | Product paths delete session keys and related caches | "Delete my data" leaves agent STM |
| 15. Admin support access | Break-glass access is audited and time-bounded | Silent cross-tenant reads by staff tools |
agent:stm:{tenant_id}:{user_id}:{session_id} # messages + scratchpad blob
agent:tcache:{tenant_id}:{user_id}:{session_id}:{tool}:{args_hash}
agent:lock:{tenant_id}:{user_id}:{session_id} # optional write lockdef assert_session_access(auth: dict, tenant_id: str, user_id: str, session_id: str) -> None:
if auth["tenant_id"] != tenant_id or auth["user_id"] != user_id:
raise PermissionError("session scope mismatch")
# Also verify session_id belongs to user in DB/index when ids are enumerablesession_id from the URL while trusting the client.sha256(query) globally "for hit rate."No. UUIDs reduce guessing but do not replace authorization. Always bind session rows to tenant and user and check on every read/write.
Yes for collaborative agents - model it as an explicit ACL (session members), not as a missing tenant check.
In secret storage per tenant or per integration install - not inside the shared session JSON when avoidable.
Automated tests: user A writes a distinctive secret into session state; user B attempts read by id and by cache key; assert deny. Repeat after deploys.
Yes for long-term memory. This page focuses on short-term session state; apply the same tenant filters on retrieval queries.
Still separate users and sessions if multiple people share the deployment. Isolation complexity scales with shared infrastructure.
Yes, but the job must carry scope and the summarizer must only read/write that session key.
Injection can try to make the model request other sessions' data; isolation must be enforced in code so tool/runtime denies cross-scope access even if the model asks.
Stack versions: Pins from the category manifest (verify at build): OpenRouter (~315+ models, July 2026 pricing/fees); LangGraph 1.0+; CrewAI 1.14+; Microsoft Agent Framework 1.0; Vercel AI SDK 6; Pydantic AI (latest); LlamaIndex (latest); OpenAI Agents SDK (latest + MCP); MCP (Linux Foundation governance); A2A (HTTP+SSE+JSON-RPC 2.0); Solana
@solana/web3.js+@solana/spl-token.
Reviewed by Chris St. John·Last updated Jul 16, 2026