Skip to content

feat(adk): overhaul ADK backend to align with v1.0.0 store#400

Merged
cofin merged 23 commits intomainfrom
feat/adk-ch1-combined
Mar 22, 2026
Merged

feat(adk): overhaul ADK backend to align with v1.0.0 store#400
cofin merged 23 commits intomainfrom
feat/adk-ch1-combined

Conversation

@cofin
Copy link
Copy Markdown
Member

@cofin cofin commented Mar 21, 2026

Summary

Improved ADK integration based on upstream improvements since initial implementation.

  • Full-event JSON storage: Replace 17-column decomposed EventRecord with 5-column model (session_id, invocation_id, author, timestamp, event_json). Eliminates column drift with upstream ADK — new Event fields are captured automatically without schema changes.
  • State persistence fix: append_event() now persists session state atomically with the event via append_event_and_update_state(). Previously, state mutations from event.actions.state_delta were lost on reload.
  • Scoped state: temp: keys stripped before persistence, app:/user: split/merge helpers for future cross-session state sharing.
  • Unified async contract: All stores (including previously sync-only DuckDB, ADBC, pymysql, Oracle sync, Spanner, psycopg sync, mysqlconnector sync) now extend BaseAsyncADKStore and wrap sync operations via sqlspec.utils.sync_tools.async_().
  • Artifact service: New SQLSpecArtifactService composing SQL metadata tables with sqlspec/storage/ content backends (S3, GCS, Azure, local filesystem).
  • BigQuery removed: Correctness bugs (JSON_VALUE flattening, unsafe bytes encoding) and architectural mismatch (high latency, eventual consistency, per-query cost) confirmed removal.
  • CockroachDB upgraded: GIN indexes and native tsvector FTS restored (incorrectly stripped in prior code).
  • Memory service expanded: add_events_to_memory() and add_memory() implemented (ADK v1.25+ contract).
  • Capability config: ADKConfig expanded with fts_language, artifact_storage_uri, schema_version, partitioning, retention, compression, and SQLite optimization sections.

cofin added 20 commits March 20, 2026 21:57
Adds test_converters.py (39 tests) and test_service.py (13 tests) for
Chapter 1 of the ADK Clean-Break Overhaul. Tests are written against the
new contract and will fail until the production code is updated.
Parametrized smoke test covering all 28 shipped ADK store classes (session
and memory, async and sync). Asserts __abstractmethods__ is empty so any
store missing a required base-class method is caught immediately. Several
stores are expected to fail today — the test documents that problem ahead
of the Ch1 clean-break overhaul that will fix them.
- split_scoped_state returns (app, user, session) not (session, app, user)
- merge_scoped_state has optional app_state/user_state params
- event_json uses model_dump() (dict) not model_dump_json() (str)
- record_to_event uses model_validate() not model_validate_json()
- session_to_record calls filter_temp_state
- create_session calls filter_temp_state
- revert extract_content_text to original format
- xfail test for extra fields (Event has extra='forbid')
BigQuery has correctness bugs (JSON_VALUE flattening, unsafe bytes
encoding) and is architecturally mismatched for ADK session storage
(high latency query jobs, eventual consistency, per-query cost model).

- Delete sqlspec/adapters/bigquery/adk/ directory
- Remove BigQuery from ADK backends docs table
- Remove BigQuery ADK entries from store instantiation tests
- Base BigQuery adapter (sqlspec.adapters.bigquery) is preserved
Rebuild DuckdbADKStore for the clean-break 5-column EventRecord:
- Events table now uses (session_id, invocation_id, author, timestamp,
  event_json) instead of 17+ decomposed columns
- Implement create_event_and_update_state() for atomic event+state writes
- Update create_event() to build event_json blob from legacy parameters
- Update list_events() to return new 5-key EventRecord shape
- Use TIMESTAMPTZ instead of TIMESTAMP for timezone-aware storage

Fix DuckdbADKMemoryStore FTS bugs:
- Replace wrong @@ operator with match_bm25() for BM25-ranked search
- Move FTS index refresh from search to post-insert/delete only
- Add stemmer, stopwords, strip_accents config to FTS index creation
Rebuild the Spanner session/event stores for the clean-break EventRecord
(5 keys: session_id, invocation_id, author, timestamp, event_json).

Changes:
- Events table DDL reduced to 5 columns with event_json as JSON type
- Implement create_event_and_update_state() for atomic event+state writes
- Update list_events/create_event to use new EventRecord shape
- Add ORDER BY update_time DESC to list_sessions
- Add _get_drop_memory_table_sql to SpannerSyncADKMemoryStore
- Remove bytes_to_spanner/spanner_to_bytes imports (no more actions column)
- Keep FARM_FINGERPRINT sharding and commit timestamp support
Update ADBC ADK store to use the new 5-column EventRecord contract
(session_id, invocation_id, author, timestamp, event_json). All dialect
DDL branches use appropriate JSON types: JSONB for PostgreSQL, JSON for
DuckDB, VARIANT for Snowflake, TEXT for SQLite and generic fallback.
Adds create_event_and_update_state for atomic event+state persistence.
Rebuild asyncmy, pymysql, and mysqlconnector ADK session/event stores
for the clean-break EventRecord contract (5 columns: session_id,
invocation_id, author, timestamp, event_json as native JSON).

- Events table DDL reduced from 17 columns + BLOB to 5 columns + JSON
- Async stores implement append_event_and_update_state() for atomic
  event+state persistence in a single transaction
- Sync stores implement create_event(), create_event_and_update_state(),
  and list_events() to satisfy BaseSyncADKStore abstract methods
- mysqlconnector extracts shared DDL helpers (_mysql_sessions_ddl,
  _mysql_events_ddl) to reduce duplication between async and sync stores
- All adapters use %s parameter style consistently
- Memory stores left unchanged
Implement Chapter 11 (artifact-service) of the ADK Clean-Break Overhaul.

Adds SQLSpecArtifactService implementing all 7 BaseArtifactService methods
(save_artifact, load_artifact, list_artifact_keys, delete_artifact,
list_versions, list_artifact_versions, get_artifact_version) by composing
SQL-backed metadata storage with sqlspec/storage/ content backends.

Architecture:
- Metadata (version, filename, mime_type, custom_metadata, canonical_uri)
  stored in a SQL table via BaseAsync/SyncADKArtifactStore
- Content bytes stored in object storage (S3, GCS, Azure, local filesystem)
  via StorageRegistry, addressed by canonical URI
- URI pattern: {base}/apps/{app}/users/{user}/[sessions/{sid}/]artifacts/{file}/v{ver}
- Versioning is append-only (0-based, monotonically increasing)
- Content written first, metadata second (fail-fast ordering)
- Delete removes metadata first, content cleanup is best-effort

New files:
- sqlspec/extensions/adk/artifact/__init__.py (package exports)
- sqlspec/extensions/adk/artifact/_types.py (ArtifactRecord TypedDict)
- sqlspec/extensions/adk/artifact/store.py (BaseAsync/SyncADKArtifactStore ABCs)
- sqlspec/extensions/adk/artifact/service.py (SQLSpecArtifactService)

Also adds artifact_table and artifact_storage_uri fields to ADKConfig.
Update all ADK integration tests to work with the new 5-column
EventRecord (session_id, invocation_id, author, timestamp, event_json)
instead of the old 17-column decomposed schema.

Changes per adapter:
- asyncmy: Replace old event dicts with 5-key EventRecord for
  append_event; update schema verification to check new columns
- mysqlconnector: Same as asyncmy
- duckdb: Remove get_event calls (method removed), update event
  assertions to check event_json instead of top-level columns
- oracledb: Replace 17-column EventRecord literals with 5-key
  records; remove old boolean/LOB column-specific tests
- spanner: Update event content assertions to read from event_json
- adbc: Update all event operation tests to verify 5-key shape;
  update DDL tests to check for event_json column types instead
  of old BLOB/BOOLEAN/INTEGER columns

No BigQuery ADK tests exist (already removed in prior chapter).
….async_()

Convert all sync ADK session and memory stores from BaseSyncADKStore/
BaseSyncADKMemoryStore to BaseAsyncADKStore/BaseAsyncADKMemoryStore.

Each sync store now:
- Extends the async base class instead of the sync base class
- Has private sync methods (e.g., _create_session, _get_session)
- Has public async wrappers using async_() from sync_tools
- Maps create_event_and_update_state -> append_event_and_update_state
- Maps list_events -> get_events (with after_timestamp/limit params)
- Adds append_event method
- Drops legacy create_event method

Stores converted (session + memory):
- DuckDB, ADBC, Psycopg (sync), CockroachDB Psycopg (sync),
  MySQL Connector (sync), PyMySQL, Oracle (sync), Spanner (sync),
  SQLite (memory store only)

The SQLite session store was already using this pattern and served as
the reference implementation.
- Change EventRecord.event_json type from str to dict[str, Any] to match
  actual usage (model_dump returns dict, stores deserialize from DB to dict)
- Fix sync _create_tables methods calling async DDL methods without await
  by using run_() wrapper consistently across all sync stores
- Fix sync _create_session methods calling async get_session by using
  sync _get_session instead
- Add missing datetime import in pymysql store
- Fix Oracle/ADBC/DuckDB stores to deserialize event_json from str to dict
  when reading from database
@cofin cofin changed the title feat(adk): clean-break overhaul — full-event JSON, state persistence, unified async feat(adk): overhaul ADK backend to align with v1.0.0 store Mar 21, 2026
cofin added 3 commits March 21, 2026 19:38
…it` parameters across adapters, and refactor event insertion logic.
…andling, refining Spanner JSON serialization, and adding session creation error checks.
…and enhance migration configuration documentation.
@cofin cofin merged commit cf1f007 into main Mar 22, 2026
16 checks passed
@cofin cofin deleted the feat/adk-ch1-combined branch March 22, 2026 02:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant