Back to Blog
2026-03-06
5 min read
Install adk-secure-sessions, swap one import, and verify your agent's session data is encrypted at rest — start to finish in under 5 minutes.
In Part 1, I showed that Google ADK stores everything your agent knows — tool calls, user messages, conversation context — in plaintext SQLite. If that made you uncomfortable, this post fixes it.
This is the recipe card. Ingredients, steps, done. The explanation of why the soufflé rises comes later in Part 3.
DatabaseSessionService (or a willingness to create a minimal one)No system libraries, no C compilation, no Docker. The library is pure Python with two runtime dependencies: google-adk and cryptography. A short ingredient list.
Or with uv:
Verify the install:
Your agent code probably has something like this:
Replace it with:
Two changes: the import line and the constructor. Everything else in your agent stays the same — create_session, get_session, list_sessions, delete_session, append_event — the full ADK session lifecycle, identical behavior. The difference is what hits the disk.
For proper connection cleanup, wrap the service in async with. Here's a complete, runnable script:
Copy this into a file and run it. The API behaves identically to ADK's DatabaseSessionService — same methods, same signatures, same return types. The only difference is what's stored on disk: switching from a glass jar to a lockbox. Same ingredients go in, same ingredients come out, but nobody can peek inside without the key.
Trust but verify. Open the SQLite database directly and confirm the data is actually encrypted.
Using the sqlite3 CLI:
You'll see a base64-encoded string — the encrypted envelope — not readable JSON:
Using Python:
What you won't see: {"patient_name": "Jane Doe", "diagnosis_code": "J06.9"}. That's the point. With DatabaseSessionService, anyone with file access reads your mise en place. With EncryptedSessionService, they see noise.
For a more convincing demo, run the basic usage example from the repo — it runs a real multi-turn ADK agent with Ollama and then inspects the raw database to prove no plaintext leaks. After a three-turn conversation about patient intake, the database contains zero occurrences of "Jane Doe" or "headache."
The passphrase is the only secret. Never hardcode it.
Set it in your environment, your .env file, or your secrets manager. The library handles everything else — FernetBackend derives a cryptographic key using PBKDF2-HMAC-SHA256 with 480,000 iterations. You don't need to generate, store, or rotate raw key material.
If you use the wrong passphrase to read a session encrypted with a different one, you get a clear DecryptionError — never garbage data, never silent corruption.
Five steps, plaintext to encrypted-at-rest:
pip install adk-secure-sessionsYour agent still works the same way. Your tests still pass. But the SQLite file is now useless without the key — like a walk-in freezer with a combination lock. Nothing changes about how the food is stored or retrieved, but the back door isn't open anymore.
When things go wrong, the library tells you what happened:
ConfigurationError — raised at startup if the backend is misconfigured. You'll catch this before any data is written.DecryptionError — raised if you read a session with the wrong key. The library never returns garbage.pip install adk-secure-sessions, swap the constructor, donecreate_session, get_session, list_sessions, delete_session, and append_event all work identicallyDecryptionError for wrong keys, ConfigurationError for bad setup