You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is your feature request related to a specific problem?
Yes. Python has shipped FirestoreSessionService and FirestoreMemoryService since v1.31.0
(#5088), but they don't behave like the other session and memory services, and there is no
Python documentation for them. Testing them against a real Firestore database on 2.9.1 and main (f33d4923), I reproduced these problems:
Nested user: / app: state is merged instead of replaced. Updating user:profile
from {"name": "Alice", "role": "admin"} to {"name": "Alice"} stores {"name": "Alice", "role": "admin"}, so the removed key comes back on the next get_session. The in-memory, SQLite and database session services replace the value.
Cause: user_states / app_states are written with transaction.set(..., merge=True) in
both create_session and append_event, and Firestore deep-merges nested maps.
Session-scoped state is not affected (it is stored as JSON).
The services can't be imported from their package. from google.adk.integrations.firestore import FirestoreSessionService raises ImportError
because integrations/firestore/__init__.py exports nothing. It is the only package under integrations/ like this.
GetSessionConfig(after_timestamp=...) returns the wrong events. Events are stored with "timestamp": firestore.SERVER_TIMESTAMP, so the filter and event ordering use the write
time instead of event.timestamp.
get_user_state is not supported. It raises NotImplementedError, while the in-memory,
database, SQLite and Redis session services implement it.
add_session_to_memory stores duplicates. Each call writes a new document per event, so
adding the same session again (for example after every turn) stores every memory again.
Search hides this by de-duplicating results, but storage keeps growing. add_events_to_memory is also not implemented; InMemoryMemoryService supports it.
Positional-filter warnings.list_sessions and get_session with after_timestamp
call .where("field", op, value), so google-cloud-firestore emits UserWarning: Detected filter using positional arguments on every call.
Describe the Solution You'd Like
Make the Firestore services behave like the other backends, with no change to their public
API other than implementing two existing base-class methods:
Write user: / app: state back whole so a new value replaces the old one.
Export FirestoreSessionService and FirestoreMemoryService from google.adk.integrations.firestore, loaded lazily (as integrations/model_armor does) so
importing the package still does not require google-cloud-firestore.
Store each event's own timestamp so after_timestamp and event ordering use event time.
Implement get_user_state by reading the user_states document the service already writes.
Give each memory entry a stable document ID derived from app, user, session and event IDs,
so re-adding a session overwrites instead of duplicating, and implement add_events_to_memory.
Pass query filters as where(filter=FieldFilter(...)), as FirestoreMemoryService already
does.
Impact on your work
I build agents for Google Cloud customers, and Firestore is the natural serverless session
store for agents on Cloud Run. Today:
A value removed from nested user or app state (for example a role or a permission flag)
silently stays in Firestore and comes back on the next turn.
Memory storage grows with every turn when sessions are added to memory after each turn.
Moving an agent between session services changes its behavior.
Python users have no documentation showing how to use these services: the adk.dev Firestore page covers Java only.
Willingness to contribute
Yes. I have the fix ready with unit tests, one commit per item above, and can open the PR
once this is triaged. I will also open a PR in google/adk-docs adding Python usage to the
Firestore page.
馃煛 Recommended Information
Describe Alternatives You've Considered
DatabaseSessionService with Cloud SQL or AlloyDB: works correctly, but needs a database
instance to run and manage, which Firestore avoids.
VertexAiSessionService: works, but ties sessions to Agent Engine.
Workarounds on the current Firestore services: import from the full module path, avoid dict
values in user: / app: state, and add each session to memory only once. These avoid the
symptoms but are easy to miss, and nothing in the docs mentions them.
Proposed API / Implementation
No new public API. The changes stay inside src/google/adk/integrations/firestore/ and its
unit tests:
# 1. create_session / append_event: write the full, already-updated dicttransaction.set(user_ref, current_user) # was: transaction.set(user_ref, current_user, merge=True)# 3. append_event: store the event's own time"timestamp": datetime.fromtimestamp(event.timestamp, tz=timezone.utc) # was: firestore.SERVER_TIMESTAMP# 5. memory: stable document ID per eventdoc_id=sha256("\x00".join((app_name, user_id, session_idor"", event.id)))
After the change, a local run of the shared session contract suite
(tests/unittests/sessions/test_session_service.py) against a real Firestore database goes
from 18 passed / 13 failed to 27 passed / 4 failed. The 4 remaining failures are covered below.
Additional Context
Minimal reproduction for item 1 (pip install google-adk==2.9.1 google-cloud-firestore, a
Firestore Native database):
Should the CLI accept --session_service_uri firestore://... and --memory_service_uri firestore://...? Today an unregistered session scheme falls back to DatabaseSessionService and fails with ValueError: Invalid database URL format. I have a
working services.py registration and can propose a built-in scheme if that is wanted.
Registering Firestore in tests/unittests/sessions/_conformance.py needs a stateful Firestore
fake. I can do that as a follow-up.
馃敶 Required Information
Is your feature request related to a specific problem?
Yes. Python has shipped
FirestoreSessionServiceandFirestoreMemoryServicesince v1.31.0(#5088), but they don't behave like the other session and memory services, and there is no
Python documentation for them. Testing them against a real Firestore database on 2.9.1 and
main(f33d4923), I reproduced these problems:user:/app:state is merged instead of replaced. Updatinguser:profilefrom
{"name": "Alice", "role": "admin"}to{"name": "Alice"}stores{"name": "Alice", "role": "admin"}, so the removed key comes back on the nextget_session. The in-memory, SQLite and database session services replace the value.Cause:
user_states/app_statesare written withtransaction.set(..., merge=True)inboth
create_sessionandappend_event, and Firestore deep-merges nested maps.Session-scoped state is not affected (it is stored as JSON).
from google.adk.integrations.firestore import FirestoreSessionServiceraisesImportErrorbecause
integrations/firestore/__init__.pyexports nothing. It is the only package underintegrations/like this.GetSessionConfig(after_timestamp=...)returns the wrong events. Events are stored with"timestamp": firestore.SERVER_TIMESTAMP, so the filter and event ordering use the writetime instead of
event.timestamp.get_user_stateis not supported. It raisesNotImplementedError, while the in-memory,database, SQLite and Redis session services implement it.
add_session_to_memorystores duplicates. Each call writes a new document per event, soadding the same session again (for example after every turn) stores every memory again.
Search hides this by de-duplicating results, but storage keeps growing.
add_events_to_memoryis also not implemented;InMemoryMemoryServicesupports it.list_sessionsandget_sessionwithafter_timestampcall
.where("field", op, value), sogoogle-cloud-firestoreemitsUserWarning: Detected filter using positional argumentson every call.Describe the Solution You'd Like
Make the Firestore services behave like the other backends, with no change to their public
API other than implementing two existing base-class methods:
user:/app:state back whole so a new value replaces the old one.FirestoreSessionServiceandFirestoreMemoryServicefromgoogle.adk.integrations.firestore, loaded lazily (asintegrations/model_armordoes) soimporting the package still does not require
google-cloud-firestore.after_timestampand event ordering use event time.get_user_stateby reading theuser_statesdocument the service already writes.so re-adding a session overwrites instead of duplicating, and implement
add_events_to_memory.where(filter=FieldFilter(...)), asFirestoreMemoryServicealreadydoes.
Impact on your work
I build agents for Google Cloud customers, and Firestore is the natural serverless session
store for agents on Cloud Run. Today:
silently stays in Firestore and comes back on the next turn.
Firestore page covers Java only.
Willingness to contribute
Yes. I have the fix ready with unit tests, one commit per item above, and can open the PR
once this is triaged. I will also open a PR in
google/adk-docsadding Python usage to theFirestore page.
馃煛 Recommended Information
Describe Alternatives You've Considered
DatabaseSessionServicewith Cloud SQL or AlloyDB: works correctly, but needs a databaseinstance to run and manage, which Firestore avoids.
VertexAiSessionService: works, but ties sessions to Agent Engine.values in
user:/app:state, and add each session to memory only once. These avoid thesymptoms but are easy to miss, and nothing in the docs mentions them.
Proposed API / Implementation
No new public API. The changes stay inside
src/google/adk/integrations/firestore/and itsunit tests:
After the change, a local run of the shared session contract suite
(
tests/unittests/sessions/test_session_service.py) against a real Firestore database goesfrom 18 passed / 13 failed to 27 passed / 4 failed. The 4 remaining failures are covered below.
Additional Context
Minimal reproduction for item 1 (
pip install google-adk==2.9.1 google-cloud-firestore, aFirestore Native database):
Not proposed here, open questions:
last_update_timeusing Firestore'sserver
updateTimeinstead of the appended event's timestamp, which looks intentional afterFirestore Session Service does not handle timestamp correctly聽#5632 / fix(firestore): populate last_update_time in list_sessions from Firestore updateTime聽#5642. The fourth is
list_sessions(user_id=None), which needs a single-fieldcollection-group index on
sessions.appName; I would document that.--session_service_uri firestore://...and--memory_service_uri firestore://...? Today an unregistered session scheme falls back toDatabaseSessionServiceand fails withValueError: Invalid database URL format. I have aworking
services.pyregistration and can propose a built-in scheme if that is wanted.tests/unittests/sessions/_conformance.pyneeds a stateful Firestorefake. I can do that as a follow-up.