diff --git a/docs/integrations/bigquery-agent-analytics.md b/docs/integrations/bigquery-agent-analytics.md index 37ae1e7dad..4dc0a0ea4a 100644 --- a/docs/integrations/bigquery-agent-analytics.md +++ b/docs/integrations/bigquery-agent-analytics.md @@ -8,7 +8,7 @@ catalog_tags: ["observability", "google"] # BigQuery Agent Analytics plugin for ADK
- Supported in ADKPython v1.21.0Java v1.5.0 + Supported in ADKPython v1.21.0Java v1.5.0Kotlin v0.8.0
The BigQuery Agent Analytics Plugin significantly enhances Agent Development Kit @@ -58,6 +58,21 @@ The plugin includes three reliability and observability fixes: For information on costs, see the [BigQuery documentation](https://cloud.google.com/bigquery/pricing?e=48754805&hl=en#data-ingestion-pricing). +??? note "Kotlin support" + + The **Kotlin** plugin logs invocation lifecycle events. It writes an + `INVOCATION_STARTING` row when an invocation begins and an + `INVOCATION_COMPLETED` row when it ends, and creates the partitioned, + clustered events table on first use if it does not already exist. + + Rows are inserted one at a time through `tabledata.insertAll`, synchronously + on the invocation path, rather than through the Storage Write API used by + Python and Java. + + The following are not implemented in Kotlin: LLM, tool, agent, state, HITL + and A2A events; the ADK 2.0 workflow events; automatic view creation; Auto + Schema Upgrade; tool provenance; GCS offloading; and drop statistics. + ## Use cases - **Agent workflow debugging and analysis:** Capture a wide range of *plugin @@ -89,6 +104,10 @@ examples, see [Event types and payloads](#event-types). The **View** column shows the BigQuery view optionally created when [`create_views`](#configuration-options) is enabled (the default). +In **Kotlin**, the plugin logs `INVOCATION_STARTING` and `INVOCATION_COMPLETED` +only and creates no views, so the other rows and the entire **View** column +apply to Python and Java. + | Event Type | Captured When | Key Payload Fields | View | | --- | --- | --- | --- | | `USER_MESSAGE_RECEIVED` | A user message enters the invocation | text summary / content parts | `v_user_message_received` | @@ -193,6 +212,33 @@ shows the BigQuery view optionally created when } ``` +=== "Kotlin" + + Add the plugin to your agent's `App` object. For prerequisites, see + [Prerequisites](#prerequisites). The plugin is JVM-only and ships outside + core, so add the integrations artifact: + + ```kotlin title="build.gradle.kts" + implementation("com.google.adk:google-adk-kotlin-integrations:0.8.0") + ``` + + ```kotlin title="BigQueryAnalyticsExample.kt" + --8<-- "examples/kotlin/snippets/integrations/BigQueryAnalyticsExample.kt:quickstart" + ``` + + The plugin creates the events table on first use, so the credentials in + scope need permission to create a table in the dataset, not only to insert + rows. Set `location` to your dataset's location; it defaults to `"US"`. For + the full set of options, see [Configuration + options](#configuration-options). + + Logging never fails the turn: if the table cannot be created or a row cannot + be inserted, the plugin logs the error and the invocation continues. When + rows are missing, enable logging for + `com.google.adk.kt.plugins.agentanalytics.BigQueryAgentAnalyticsPlugin` — + logs are emitted under that class name, not under the plugin's ADK name + (`bigquery_agent_analytics`). + ### Run and test agent @@ -708,6 +754,44 @@ account) under which the agent is running needs these Google Cloud roles: BigQueryAgentAnalyticsPlugin plugin = new BigQueryAgentAnalyticsPlugin(config); ``` +=== "Kotlin" + + In Kotlin, all configuration is managed via the `BigQueryLoggerConfig` data + class, which the plugin takes as its only required argument. + + #### BigQueryLoggerConfig properties + + | Option | Type | Default | Use when | + | --- | --- | --- | --- | + | `projectId` | `String` | *(required)* | Select the Google Cloud project | + | `datasetId` | `String` | *(required)* | Select the BigQuery dataset | + | `enabled` | `Boolean` | `true` | Temporarily disable logging | + | `location` | `String` | `"US"` | Match the BigQuery dataset location (for example, `"EU"` or `"us-central1"`) | + | `tableName` | `String` | `"agent_events"` | Use a custom table name | + | `credentials` | `Credentials?` | `null` | Use explicit service-account credentials instead of [ADC](https://cloud.google.com/docs/authentication/application-default-credentials) | + + The following code sample shows how to define a configuration for the + BigQuery Agent Analytics plugin in Kotlin: + + ```kotlin + import com.google.adk.kt.plugins.agentanalytics.BigQueryAgentAnalyticsPlugin + import com.google.adk.kt.plugins.agentanalytics.BigQueryLoggerConfig + + val config = + BigQueryLoggerConfig( + projectId = "my-project", + datasetId = "my_dataset", + location = "EU", + tableName = "agent_events", + ) + + val plugin = BigQueryAgentAnalyticsPlugin(config = config) + ``` + + The options listed under the **Python** and **Java** tabs, such as batching, + content formatting, event allowlists, GCS offloading, and view creation, do + not exist in Kotlin. + ## Schema and production setup @@ -735,6 +819,11 @@ provides a comprehensive reference with example values. | **is_truncated** | `BOOLEAN` | `NULLABLE` | `true` if `content` or `attributes` exceeded the BigQuery cell size limit (default 10MB) and were partially dropped. | `false` | | **content_parts** | `RECORD` | `REPEATED` | Array of multi-modal segments (Text, Image, Blob). Used when content cannot be serialized as simple JSON (e.g., large binaries or GCS refs). | `[{"mime_type": "text/plain", "text": "hello"}]` | +In **Kotlin**, the plugin creates the table with these same columns but +populates only `timestamp`, `event_type`, `agent`, `session_id`, +`invocation_id`, `user_id`, and `content`. The remaining columns are always +null. + The plugin automatically creates the table if it does not exist. For production, you can optionally create the table manually using the DDL below. @@ -1067,6 +1156,10 @@ updated by tools). | `USER_MESSAGE_RECEIVED` | `{"text_summary": "Help me book a flight."}` | | `AGENT_RESPONSE` | `{"response": "Here are the flights..."}` | +In **Kotlin**, the two invocation events carry a summary message instead of an +empty object: `{"message": "Invocation started"}` and +`{"message": "Invocation completed"}`. + **AGENT_RESPONSE** Logged when the agent yields a final response to the user. The response text is stored in `content`, while the source event metadata is stored in `attributes`. diff --git a/examples/kotlin/build.gradle.kts b/examples/kotlin/build.gradle.kts index b057c5cd7f..bbca101f99 100644 --- a/examples/kotlin/build.gradle.kts +++ b/examples/kotlin/build.gradle.kts @@ -30,6 +30,11 @@ dependencies { // own catalog; the spec and jsonrpc transport arrive transitively. implementation("com.google.adk:google-adk-kotlin-a2a:0.8.0") implementation("org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.Final") + // BigQueryAgentAnalyticsPlugin lives in the integrations module. Unlike the + // a2a artifact above, this one publishes google-cloud-bigquery and + // google-auth on jvmApiElements, so the BigQuery types its constructor + // defaults name arrive on the compile classpath with no second line. + implementation("com.google.adk:google-adk-kotlin-integrations:0.8.0") implementation("com.google.cloud:google-cloud-storage:2.48.2") implementation("io.opentelemetry:opentelemetry-sdk:1.56.0") implementation("io.opentelemetry:opentelemetry-exporter-otlp:1.56.0") diff --git a/examples/kotlin/snippets/integrations/BigQueryAnalyticsExample.kt b/examples/kotlin/snippets/integrations/BigQueryAnalyticsExample.kt new file mode 100644 index 0000000000..eeafd52b9d --- /dev/null +++ b/examples/kotlin/snippets/integrations/BigQueryAnalyticsExample.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.adk.kt.examples.integrations + +// --8<-- [start:quickstart] +import com.google.adk.kt.agents.Instruction +import com.google.adk.kt.agents.LlmAgent +import com.google.adk.kt.apps.App +import com.google.adk.kt.models.Gemini +import com.google.adk.kt.plugins.agentanalytics.BigQueryAgentAnalyticsPlugin +import com.google.adk.kt.plugins.agentanalytics.BigQueryLoggerConfig + +val analyticsAgent = + LlmAgent( + name = "my_agent", + model = Gemini(name = "gemini-flash-latest"), + instruction = Instruction("You are a helpful assistant."), + ) + +/** + * Wraps [analyticsAgent] in an [App] whose invocations are logged to BigQuery. + * + * The plugin creates the day-partitioned table on first use, so the credentials + * in scope need permission to create a table in the dataset, not only to insert + * rows. Without explicit `credentials`, application default credentials are used. + * + * Logging failures never fail the turn: a table that cannot be created, or a row + * that cannot be inserted, is logged and the invocation carries on. + */ +fun analyticsApp( + projectId: String, + datasetId: String, + datasetLocation: String, +): App { + val plugin = + BigQueryAgentAnalyticsPlugin( + config = + BigQueryLoggerConfig( + projectId = projectId, + datasetId = datasetId, + // Defaults to "US"; pass your dataset's location instead. + location = datasetLocation, + ), + ) + + return App( + appName = "my_agent", + rootAgent = analyticsAgent, + plugins = listOf(plugin), + ) +} +// --8<-- [end:quickstart] diff --git a/tools/kotlin-snippets/files_to_test.txt b/tools/kotlin-snippets/files_to_test.txt index cbc8a9d848..cdd18c4837 100644 --- a/tools/kotlin-snippets/files_to_test.txt +++ b/tools/kotlin-snippets/files_to_test.txt @@ -44,3 +44,4 @@ snippets/sessions/RewindExample.kt snippets/tools/confirmation/ToolConfirmationExample.kt snippets/tools/confirmation/dynamic/ReimbursementTools.kt snippets/skills/SkillsExample.kt +snippets/integrations/BigQueryAnalyticsExample.kt