Commit 119b8ea
committed
feat(bqaa): ADK 2.0 minimum producer cut for google#293 v5
Implements the customer-driven mid-June producer-only subset of the
ADK 2.0 observability work tracked in google#293 (parent google#190). The customer
needs these specific fields visible in BigQuery before their ADK 2.0
production cutover; full v15 contract (google#190) lands incrementally.
This change is producer-only. No consumer-side SDK / typed-view work
is included — the customer reads base-table JSON directly during the
mid-June window.
What lands
----------
A1/A2 — every ADK-enriched row carries the attributes.adk envelope:
attributes.adk.schema_version (_ADK_ENVELOPE_SCHEMA_VERSION = "1")
attributes.adk.app_name (from InvocationContext.session.app_name)
A3 — rows from on_event_callback additionally carry:
attributes.adk.source_event_id (Event.id, reliable join key)
Note: never fabricated — callback rows
without an originating Event leave it
JSON-null.
C1 — attributes.adk.node = {path, run_id, parent_path}. parent_path is
derived from path; default-empty path (NodeInfo.path = "") is
preserved verbatim with parent_path = null, no synthesis.
C2 — attributes.adk.branch (absent stays JSON null).
C3 — attributes.adk.scope = null | {id, kind} per google#198 / google#293 v5
derivation order: (1) None → null, (2) name@run_id / path/name@run_id
→ node_run, (3) any other non-empty string → function_call
(model-provided FC IDs match here), (4) empty/non-string → unknown
with warning.
C4 — emit AGENT_TRANSFER from event.actions.transfer_to_agent. Payload
pinned: from_agent = event.author, to_agent = the target. Verified
against EventActions.transfer_to_agent which stores the target only.
C5 — emit EVENT_COMPACTION from event.actions.compaction. Float
start_timestamp / end_timestamp preserved with fractional precision
(consumer view conversion deferred).
C6 — emit AGENT_STATE_CHECKPOINT when actions.agent_state is not None
OR actions.end_of_agent is True. Allows {agent_state: null,
end_of_agent: true} payloads. Inline payload only; GCS offload
for oversized state deferred.
C7 — emit TOOL_PAUSED for each event.long_running_tool_ids id, with
attributes.pause_kind (derived from function_call NAME via
_HITL_PAUSE_KIND_MAP — hitl_* for adk_request_*, tool otherwise)
and attributes.function_call_id. HITL routing is unchanged:
HITL function_responses stay on HITL_*_COMPLETED, NEVER emit
TOOL_COMPLETED. Non-HITL function_responses arriving via
on_user_message_callback emit TOOL_COMPLETED with pause_kind='tool'
so the customer can pair (TOOL_PAUSED ↔ TOOL_COMPLETED) on
(app_name, user_id, session_id, function_call_id) directly in SQL.
Pause registry / pause_orphan semantics deferred to google#206.
C8 — attributes.adk.{route, render_ui_widgets, rewind_before_invocation_id}
mirror EventActions, flat-with-prefix per google#203 (matches the rest
of the attributes.adk.* envelope convention).
D1 — delete the deprecated on_state_change_callback stub (never called
by ADK 2.0; verified no callers).
Compatibility
-------------
* AGENT_RESPONSE retains the legacy flat extras (source_event_id,
source_event_author, source_event_branch) for backward compat. The
canonical keys are now under attributes.adk.*.
* The HITL test fixtures use Mock events without long_running_tool_ids
or .id; the envelope helper is defensive against missing attrs.
* No EventData / _log_event signature change. Added one optional field
EventData.source_event: Optional[Event] = None — a minimal B0 (google#194)
step. Callbacks that have access to the source Event pass it through;
others leave it None (and the envelope correctly leaves A3/C1/C2/C3
null on those rows).
Tests
-----
257 plugin tests pass (238 existing + 19 new):
* envelope shape on event-originating and non-event-originating rows
* node parent_path derivation with both empty and nested paths
* _derive_scope for None, bare node, path/node, FC IDs, empty string
* C4/C5/C6 emit paths
* C5 fractional float-epoch precision round-trip
* C6 both-shape coverage + id-stabilization regression guard
(Event.model_post_init auto-assigns id even when constructor omits it)
* C7 TOOL_PAUSED pause_kind derivation for non-HITL and HITL
* C7 HITL non-routing: HITL function_response → HITL_*_COMPLETED only,
NEVER TOOL_COMPLETED
* C7 user-message TOOL_COMPLETED with pause_kind='tool'
* C8 flat-with-prefix route / rewind_before_invocation_id
* D1: on_state_change_callback removed from the public surface
Refs: google#293 (v5), google#190, google#194, google#196, google#197, google#198, google#199, google#200, google#201, google#202,1 parent 7d29bfa commit 119b8ea
2 files changed
Lines changed: 790 additions & 43 deletions
File tree
- src/google/adk/plugins
- tests/unittests/plugins
0 commit comments