Skip to content

Commit dc3e302

Browse files
adding Runtime kotlin snippets (#1788)
* adding Runtime kotlin snippets * Adding kotlin snippets into files to test * Linting fixes via ktlint * Simplify imports * Add license headers * Add code snippet for resume config * Remove unused import * Add placeholder var definition --------- Co-authored-by: Kristopher Overholt <koverholt@google.com>
1 parent bc85c88 commit dc3e302

7 files changed

Lines changed: 313 additions & 20 deletions

File tree

docs/runtime/event-loop.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Runtime Event Loop
22

33
<div class="language-support-tag">
4-
<span class="lst-supported">Supported in ADK</span><span class="lst-python">Python v0.1.0</span><span class="lst-typescript">Typescript v0.2.0</span><span class="lst-go">Go v0.1.0</span><span class="lst-java">Java v0.1.0</span>
4+
<span class="lst-supported">Supported in ADK</span><span class="lst-python">Python v0.1.0</span><span class="lst-typescript">Typescript v0.2.0</span><span class="lst-go">Go v0.1.0</span><span class="lst-java">Java v0.1.0</span><span class="lst-kotlin">Kotlin v0.1.0</span>
55
</div>
66

77
The ADK Runtime is the underlying engine that powers your agent application during user interactions. It's the system that takes your defined agents, tools, and callbacks and orchestrates their execution in response to user input, managing the flow of information, state changes, and interactions with external services like LLMs or storage.
@@ -179,6 +179,12 @@ The `Runner` acts as the central coordinator for a single user invocation. Its r
179179
}
180180
```
181181

182+
=== "Kotlin"
183+
184+
```kotlin
185+
--8<-- "examples/kotlin/snippets/runtime/RunnerLoop.kt:conceptual_loop"
186+
```
187+
182188
### Execution Logic's Role (Agent, Tool, Callback)
183189

184190
Your code within agents, tools, and callbacks is responsible for the actual computation and decision-making. Its interaction with the loop involves:
@@ -372,6 +378,12 @@ Your code within agents, tools, and callbacks is responsible for the actual comp
372378
// If this subsequent code needs to yield another event, it would do so here.
373379
```
374380

381+
=== "Kotlin"
382+
383+
```kotlin
384+
--8<-- "examples/kotlin/snippets/runtime/RunnerLoop.kt:execution_logic"
385+
```
386+
375387
This cooperative yield/pause/resume cycle between the `Runner` and your Execution Logic, mediated by `Event` objects, forms the core of the ADK Runtime.
376388

377389
## Key components of the Runtime
@@ -588,6 +600,12 @@ Understanding a few key aspects of how the ADK Runtime handles state, streaming,
588600
// or emitting more events based on the now-updated `ctx.session().state()`.
589601
```
590602

603+
=== "Kotlin"
604+
605+
```kotlin
606+
--8<-- "examples/kotlin/snippets/runtime/RunnerLoop.kt:state_update_timing"
607+
```
608+
591609
### "Dirty Reads" of Session State
592610

593611
* **Definition:** While commitment happens *after* the yield, code running *later within the same invocation*, but *before* the state-changing event is actually yielded and processed, **can often see the local, uncommitted changes**. This is sometimes called a "dirty read".
@@ -666,6 +684,12 @@ Understanding a few key aspects of how the ADK Runtime handles state, streaming,
666684
// is yielded *after* this tool runs and is processed by the Runner.
667685
```
668686

687+
=== "Kotlin"
688+
689+
```kotlin
690+
--8<-- "examples/kotlin/snippets/runtime/RunnerLoop.kt:dirty_read"
691+
```
692+
669693
* **Implications:**
670694
* **Benefit:** Allows different parts of your logic within a single complex step (e.g., multiple callbacks or tool calls before the next LLM turn) to coordinate using state without waiting for a full yield/commit cycle.
671695
* **Caveat:** Relying heavily on dirty reads for critical logic can be risky. If the invocation fails *before* the event carrying the `state_delta` is yielded and processed by the `Runner`, the uncommitted state change will be lost. For critical state transitions, ensure they are associated with an event that gets successfully processed.

docs/runtime/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Agent Runtime
22

33
<div class="language-support-tag">
4-
<span class="lst-supported">Supported in ADK</span><span class="lst-python">Python v0.1.0</span><span class="lst-typescript">TypeScript v0.2.0</span><span class="lst-go">Go v0.1.0</span><span class="lst-java">Java v0.1.0</span>
4+
<span class="lst-supported">Supported in ADK</span><span class="lst-python">Python v0.1.0</span><span class="lst-typescript">TypeScript v0.2.0</span><span class="lst-go">Go v0.1.0</span><span class="lst-java">Java v0.1.0</span><span class="lst-kotlin">Kotlin v0.1.0</span>
55
</div>
66

77
ADK provides several ways to run and test your agents during development. Choose

docs/runtime/resume.md

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Resume stopped agents
22

33
<div class="language-support-tag">
4-
<span class="lst-supported">Supported in ADK</span><span class="lst-python">Python v1.14.0</span>
4+
<span class="lst-supported">Supported in ADK</span><span class="lst-python">Python v1.14.0</span><span class="lst-kotlin">Kotlin v0.1.0</span>
55
</div>
66

77
An ADK agent's execution can be interrupted by various factors including
@@ -23,16 +23,24 @@ Enable the Resume function for an agent workflow by applying a Resumability
2323
configuration to the App object of your ADK workflow, as shown in the following
2424
code example:
2525

26-
```python
27-
app = App(
28-
name='my_resumable_agent',
29-
root_agent=root_agent,
30-
# Set the resumability config to enable resumability.
31-
resumability_config=ResumabilityConfig(
32-
is_resumable=True,
33-
),
34-
)
35-
```
26+
=== "Python"
27+
28+
```python
29+
app = App(
30+
name='my_resumable_agent',
31+
root_agent=root_agent,
32+
# Set the resumability config to enable resumability.
33+
resumability_config=ResumabilityConfig(
34+
is_resumable=True,
35+
),
36+
)
37+
```
38+
39+
=== "Kotlin"
40+
41+
```kotlin
42+
--8<-- "examples/kotlin/snippets/runtime/RunConfigExample.kt:resumability_config"
43+
```
3644

3745
!!! warning "Caution: Long Running Functions, Confirmations, Authentication"
3846
For agents that use
@@ -77,13 +85,21 @@ curl -X POST http://localhost:8000/run_sse \
7785
You can also resume a workflow using the Runner object Run Async method, as
7886
shown below:
7987

80-
```python
81-
runner.run_async(user_id='u_123', session_id='s_abc',
82-
invocation_id='invocation-123')
88+
=== "Python"
8389

84-
# When new_message is set to a function response,
85-
# we are trying to resume a long running function.
86-
```
90+
```python
91+
runner.run_async(user_id='u_123', session_id='s_abc',
92+
invocation_id='invocation-123')
93+
94+
# When new_message is set to a function response,
95+
# we are trying to resume a long running function.
96+
```
97+
98+
=== "Kotlin"
99+
100+
```kotlin
101+
--8<-- "examples/kotlin/snippets/runtime/RunConfigExample.kt:resume_usage"
102+
```
87103

88104
!!! info "Note"
89105
Resuming a workflow from the ADK Web user interface or using the ADK

docs/runtime/runconfig.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Runtime Configuration
22

33
<div class="language-support-tag">
4-
<span class="lst-supported">Supported in ADK</span><span class="lst-python">Python v0.1.0</span><span class="lst-typescript">TypeScript v0.2.0</span><span class="lst-go">Go v0.1.0</span><span class="lst-java">Java v0.1.0</span>
4+
<span class="lst-supported">Supported in ADK</span><span class="lst-python">Python v0.1.0</span><span class="lst-typescript">TypeScript v0.2.0</span><span class="lst-go">Go v0.1.0</span><span class="lst-java">Java v0.1.0</span><span class="lst-kotlin">Kotlin v0.1.0</span>
55
</div>
66

77
`RunConfig` controls how agents behave at runtime, including streaming mode,
@@ -58,6 +58,12 @@ to `runner.run_async()` or `runner.run_live()` to override default behavior.
5858
.build();
5959
```
6060

61+
=== "Kotlin"
62+
63+
```kotlin
64+
--8<-- "examples/kotlin/snippets/runtime/RunConfigExample.kt:basic_usage"
65+
```
66+
6167
## Manage sessions and context
6268

6369
<div class="language-support-tag">
@@ -151,6 +157,12 @@ execute function calls. CFC uses the Live API under the hood.
151157
.build();
152158
```
153159

160+
=== "Kotlin"
161+
162+
```kotlin
163+
--8<-- "examples/kotlin/snippets/runtime/RunConfigExample.kt:streaming_config"
164+
```
165+
154166
## Configure audio and speech
155167

156168
<div class="language-support-tag">
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.adk.kt.examples.runtime
18+
19+
import com.google.adk.kt.agents.LlmAgent
20+
import com.google.adk.kt.agents.ResumabilityConfig
21+
import com.google.adk.kt.agents.RunConfig
22+
import com.google.adk.kt.agents.StreamingMode
23+
import com.google.adk.kt.annotations.ExperimentalResumabilityFeature
24+
import com.google.adk.kt.models.Gemini
25+
import com.google.adk.kt.runners.InMemoryRunner
26+
import com.google.adk.kt.sessions.InMemorySessionService
27+
import com.google.adk.kt.types.Content
28+
import com.google.adk.kt.types.Role
29+
import kotlinx.coroutines.flow.collect
30+
import kotlinx.coroutines.runBlocking
31+
32+
// --8<-- [start:basic_usage]
33+
val config =
34+
RunConfig(
35+
streamingMode = StreamingMode.SSE,
36+
)
37+
38+
// Pass it to runner.runAsync
39+
// runner.runAsync(..., runConfig = config)
40+
// --8<-- [end:basic_usage]
41+
42+
// --8<-- [start:full_example]
43+
fun runWithConfig(runner: InMemoryRunner) =
44+
runBlocking {
45+
val config =
46+
RunConfig(
47+
streamingMode = StreamingMode.SSE,
48+
customMetadata = mapOf("priority" to "high"),
49+
)
50+
51+
runner
52+
.runAsync(
53+
userId = "user123",
54+
sessionId = "session456",
55+
newMessage = Content.fromText(Role.USER, "Hello!"),
56+
runConfig = config,
57+
).collect { event ->
58+
// handle events
59+
}
60+
}
61+
// --8<-- [end:full_example]
62+
63+
// --8<-- [start:custom_metadata]
64+
val metadataConfig =
65+
RunConfig(
66+
customMetadata = mapOf("user_tier" to "premium"),
67+
)
68+
// --8<-- [end:custom_metadata]
69+
70+
// --8<-- [start:streaming_config]
71+
val streamingConfig =
72+
RunConfig(
73+
streamingMode = StreamingMode.SSE,
74+
)
75+
// --8<-- [end:streaming_config]
76+
77+
private val rootAgent =
78+
LlmAgent(name = "my_agent", model = Gemini(name = "gemini-flash-latest"))
79+
80+
// --8<-- [start:resumability_config]
81+
@OptIn(ExperimentalResumabilityFeature::class)
82+
val runner =
83+
InMemoryRunner(
84+
agent = rootAgent,
85+
appName = "my_resumable_agent",
86+
sessionService = InMemorySessionService(),
87+
resumabilityConfig = ResumabilityConfig(isResumable = true),
88+
)
89+
// --8<-- [end:resumability_config]
90+
91+
// --8<-- [start:resume_usage]
92+
fun resumeAgent(runner: InMemoryRunner) =
93+
runBlocking {
94+
runner
95+
.runAsync(
96+
userId = "user123",
97+
sessionId = "session456",
98+
invocationId = "previous-invocation-id",
99+
).collect { event ->
100+
// resume execution from previous state
101+
}
102+
}
103+
// --8<-- [end:resume_usage]

0 commit comments

Comments
 (0)