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