khora.integrations.google_adk.KhoraMemoryService implements Google
ADK’s BaseMemoryService so a Runner can use khora as its
long-term memory in one line:
InMemoryMemoryService
and VertexAiMemoryBankService. Each ADK (app_name, user_id) pair
maps to a deterministic khora namespace UUID5, so two
service instances on the same khora deployment see the same memory
without a shared registry.
ADK 2.0 incoming.google-adkis on a weekly release cadence and the 2.0 line is already in beta. The adapter is pinnedgoogle-adk>=1.32,<2.0and taggedstability: experimentaluntil ADK 2.x GAs and the adapter smoke passes against it.
Scope (v0.14)
KhoraMemoryService: long-term memory service implementingadd_session_to_memory,add_events_to_memory, andsearch_memory. Shipped.KhoraSessionService: NOT shipped. ADK shipsInMemorySessionService+DatabaseSessionService(SQLAlchemy) for short-term turn state. khora offers no differentiator there. Revisit only if a single-DB story for sessions + memory becomes a real user ask.
Install
google-adk>=1.32,<2.0. The adapter is registered under
the khora.integrations entry-point group, so discover() returns
it without explicit registration.
Constructor
| arg | default | notes |
|---|---|---|
kb | - | A connected Khora instance. The service does NOT own its lifecycle. |
app_id | "google_adk" | Free-form identifier stamped into stored metadata for audit / debugging. Distinct from the per-call app_name ADK passes (that one is part of the namespace key). |
recall_limit | 10 | Default limit forwarded to Khora.recall. |
min_similarity | 0.0 | Default similarity floor forwarded to Khora.recall. |
Method semantics
All methods are async. ADK invokes them from its own event loop, so no sync bridging is involved.add_session_to_memory(session): ingests every event insession.eventsas a separate khora document. Events with no usable content (no text parts AND no non-text parts) are skipped, matchingInMemoryMemoryService. Re-ingesting the same session is safe: deduplication keys offevent.idviaDocument.external_id.add_events_to_memory(*, app_name, user_id, events, session_id, custom_metadata): incremental delta of events for an existing namespace. Same deduplication contract asadd_session_to_memory.custom_metadatais merged into every event’sDocument.metadata.search_memory(*, app_name, user_id, query):Khora.recallagainst the resolved namespace. ReturnsSearchMemoryResponsewith oneMemoryEntryper matched event (chunks belonging to the same event are coalesced). Returns an empty response when the namespace hasn’t been ingested into yet.
Session attribution
Session.id (an arbitrary string) maps to a UUID5-derived
session_id. Pure UUID strings round-trip verbatim. Use
Khora.forget_session(namespace, session_id) to drop a whole
conversation atomically.
Non-text Parts
function_call, function_response, and inline_data parts are
JSON-encoded into Document.metadata["adk_parts"]. The bytes
of inline_data are dropped (mime type + sha1 prefix kept). They
would bloat the document store without being useful for vector recall.
A short placeholder is rendered as the document content for events
that carry only tool calls so they remain retrievable by name.
Quickstart
example.py
examples/integrations/google_adk/example.py by
tools/check_examples_drift.py (CI gate).
Limits and future work
- Filter / metadata pushdown:
search_memoryruns khora’s standard hybrid recall. ADK’s contract doesn’t surface a filter parameter yet. When it does, we’ll forwardapp_name/user_id/tagsto the SQL layer instead of relying on the namespace partition. - Session service: explicit non-goal for v0.14 (see “Scope” above).
inline_databytes are dropped on ingest. Multi-modal long-term memory needs a dedicated blob-store hookup before the bytes can be preserved without ballooning the document table.- Aligning with ADK 2.x: the adapter is pinned
<2.0until the beta’sBaseMemoryServiceshape stabilises. Track upstream changes via the nightly-skew CI job.