Skip to content

Google ADK Integration

sqlspec.extensions.adk integrates SQLSpec with Google Agent Development Kit (google-adk >= 2.10.0), providing persistent database-backed implementations of ADK's BaseSessionService (SQLSpecSessionService), BaseMemoryService (SQLSpecMemoryService), and BaseArtifactService (SQLSpecArtifactService) across 19 database adapters.

Installation

uv add "sqlspec[adk]"

Architecture and Store Services

ADK Service SQLSpec Class Adapter Store Base Responsibility
Session & Event Store SQLSpecSessionService BaseAsyncADKStore / BaseSyncADKStore Persists conversation sessions, structured state (app:, user:, session state), and ordered Event records with optimistic revision checks and per-session concurrency locks.
Long-Term Memory Store SQLSpecMemoryService BaseAsyncADKMemoryStore / BaseSyncADKMemoryStore Indexes conversation turns and tool outputs into adk_memory_entries with substring (simple), full-text (fts), vector (vector), and Reciprocal Rank Fusion (hybrid) search.
Artifact Store SQLSpecArtifactService BaseAsyncADKArtifactStore / BaseSyncADKArtifactStore Stores versioned binary and text artifacts scoped by (app_name, user_id, session_id, filename, version) with user:-prefixed cross-session sharing and artifact:// resolution.

Configuring extension_config["adk"]

Configure table names, full-text indexing, vector dimensions, and optional owner foreign keys on any adapter via extension_config["adk"] (ADKConfig):

docs/examples/extensions/adk/backend_config.py
"""Configure Google ADK session, event, and memory table names on an ADBC adapter."""

from sqlspec.adapters.adbc import AdbcConfig

__all__ = ("main",)


def main() -> AdbcConfig:
    """Attach ADK store table settings via extension_config on AdbcConfig."""
    adk_config = {
        "session_table": "adk_session",
        "events_table": "adk_event",
        "memory_table": "adk_memory",
        "memory_use_fts": True,
    }
    config = AdbcConfig(
        connection_config={"driver_name": "gizmosql", "gizmosql_backend": "duckdb"},
        extension_config={"adk": adk_config},
    )
    adk_settings = config.extension_config.get("adk")
    assert isinstance(adk_settings, dict)
    assert adk_settings.get("memory_use_fts") is True
    return config


if __name__ == "__main__":
    print(main())

Key ADKConfig Options

Key Type Default Description
session_table str "adk_sessions" Table storing session metadata and serialized state JSON.
events_table str "adk_events" Table storing ordered conversation events linked to session_table.
memory_table str "adk_memory_entries" Table storing searchable long-term memory entries.
artifact_table str "adk_artifacts" Table storing versioned binary/text agent artifacts.
memory_use_fts bool False Enables native full-text search indexing (FTS5 on SQLite, tsvector/GIN or ParadeDB BM25 on PostgreSQL, CONTAINS on Oracle Text, FULLTEXT on MySQL/MSSQL, SEARCH on Spanner).
memory_use_vector bool False Adds vector embedding storage and index DDL (pgvector, Oracle 26ai VECTOR, Spanner ARRAY<FLOAT32>, DuckDB FLOAT[N]).
memory_vector_dimensions int 768 Embedding vector dimensionality when memory_use_vector=True.
owner_id_column str | None None Optional DDL definition (for example, "tenant_id UUID NOT NULL REFERENCES tenants(id)") linking sessions to an application table.

Persisting Sessions and Events

Instantiate the adapter's *ADKStore (such as AiosqliteADKStore, AsyncpgADKStore, OracleAsyncADKStore, or SpannerAsyncADKStore), call await store.ensure_tables(), and pass the store to SQLSpecSessionService(store) or call the store directly:

docs/examples/extensions/adk/memory_store.py
"""Persist and reload Google ADK session events using AiosqliteADKStore."""

import asyncio
from datetime import UTC, datetime

from google.adk.events.event import Event
from google.genai import types

from sqlspec.adapters.aiosqlite import AiosqliteConfig
from sqlspec.adapters.aiosqlite.adk import AiosqliteADKStore
from sqlspec.extensions.adk import StoredEvent
from sqlspec.extensions.adk.converters import event_to_record

__all__ = ("main",)


async def main() -> list[StoredEvent]:
    """Create an ADK session, append a user event, and fetch stored events."""
    config = AiosqliteConfig(connection_config={"database": ":memory:"})
    try:
        store = AiosqliteADKStore(config)
        await store.ensure_tables()

        session = await store.create_session(
            session_id="session_1", app_name="docs", user_id="user_1", state={"mode": "demo"}
        )

        event = Event(
            id="evt_1",
            invocation_id="inv_1",
            author="user",
            content=types.Content(parts=[types.Part(text="Hello")]),
            timestamp=datetime.now(UTC).timestamp(),
        )
        event_record = event_to_record(event, session["app_name"], session["user_id"], session["id"])
        await store.append_event(event_record)
        events = await store.get_events(session["app_name"], session["user_id"], session["id"])
        assert len(events) == 1
        return events
    finally:
        await config.close_pool()


if __name__ == "__main__":
    print(len(asyncio.run(main())))

When wiring an ADK Runner, pass SQLSpecSessionService(store), SQLSpecMemoryService(memory_store), and SQLSpecArtifactService(artifact_store) inside an async context manager (async with SQLSpecSessionService(store) as session_service:) so session locks and resources close cleanly on shutdown.

ADKMemoryStore supports four search modes across engines:

  1. Simple (simple): Portable case-insensitive substring matching across all 19 ADK adapters.
  2. Full-Text (fts): Native lexical ranking (FTS5 on sqlite/aiosqlite, tsvector or ParadeDB @@@ BM25 on PostgreSQL, Oracle Text CONTAINS with "AND", "OR", "ACCUM", and "NEAR" operators, MATCH ... AGAINST on MySQL, and SEARCH/SCORE on Spanner).
  3. Vector (vector): Cosine or inner-product similarity search on asyncpg, psycopg, psqlpy, adbc (pgvector), oracledb (Oracle 26ai HNSW FETCH APPROX FIRST or exact top-K), spanner (APPROX_COSINE_DISTANCE), and duckdb (array_cosine_similarity).
  4. Hybrid RRF (hybrid): Single-round-trip Reciprocal Rank Fusion (1 / (k + rank)) combining vector distance and full-text rank in one SQL CTE on PostgreSQL (asyncpg, psycopg, psqlpy, adbc), Oracle 26ai (oracledb), Cloud Spanner (spanner), and DuckDB (duckdb).
docs/examples/extensions/adk/tool_integration.py
"""Index and query tool-generated memories with full-text search in AiosqliteADKMemoryStore."""

import asyncio
from datetime import UTC, datetime

from sqlspec.adapters.aiosqlite import AiosqliteConfig
from sqlspec.adapters.aiosqlite.adk import AiosqliteADKMemoryStore
from sqlspec.extensions.adk import StoredMemory

__all__ = ("main",)


async def main() -> int:
    """Insert a tool invocation memory entry and search it via FTS."""
    config = AiosqliteConfig(
        connection_config={"database": ":memory:"}, extension_config={"adk": {"memory_use_fts": True}}
    )
    try:
        store = AiosqliteADKMemoryStore(config)
        await store.ensure_tables()

        record: StoredMemory = {
            "id": "mem_1",
            "session_id": "session_1",
            "app_name": "docs",
            "user_id": "user_1",
            "scope": "user",
            "event_id": "evt_1",
            "author": "tool",
            "timestamp": datetime.now(UTC),
            "content_json": {"tool": "search", "query": "sqlspec"},
            "content_text": "tool:search query=sqlspec",
            "metadata_json": None,
            "inserted_at": datetime.now(UTC),
            "embedding": None,
        }
        await store.insert_memory_entries([record])
        results = await store.search_entries(query="sqlspec", app_name="docs", user_id="user_1")
        assert len(results) == 1
        return len(results)
    finally:
        await config.close_pool()


if __name__ == "__main__":
    print(asyncio.run(main()))

Schema Migrations and CLI Maintenance

Instead of calling ensure_tables() at runtime in production, enable "adk" in migration_config={"enable_extensions": ["adk"]} so sqlspec upgrade tracks ADK schema revisions alongside your application migrations.

Use the built-in sqlspec adk memory CLI commands to inspect, clean up, or verify memory stores:

sqlspec --config myapp.db.spec adk memory stats
sqlspec --config myapp.db.spec adk memory cleanup --older-than-days 90

Recap

  • Configure ADK tables, FTS, and vector search in extension_config["adk"].
  • Pair SQLSpecSessionService, SQLSpecMemoryService, and SQLSpecArtifactService with your adapter's adk store classes.
  • See the Database Capability Matrix for per-adapter ADK vector/FTS support and the ADK Extension Reference for full API signatures.