0
# Live Sessions (Experimental)
1
2
**WARNING: This API is experimental and subject to change.**
3
4
Real-time bidirectional communication with AI models using WebSocket connections. Live sessions enable low-latency, streaming interactions for applications requiring immediate responses, such as voice assistants, real-time translation, or interactive chatbots.
5
6
## Core Imports
7
8
```java
9
import com.google.genai.AsyncLive;
10
import com.google.genai.AsyncSession;
11
import com.google.genai.types.LiveConnectConfig;
12
import com.google.genai.types.LiveSendClientContentParameters;
13
import com.google.genai.types.LiveSendRealtimeInputParameters;
14
import com.google.genai.types.LiveSendToolResponseParameters;
15
import com.google.genai.types.LiveServerMessage;
16
import java.util.concurrent.CompletableFuture;
17
import java.util.function.Consumer;
18
```
19
20
## AsyncLive Service
21
22
```java { .api }
23
package com.google.genai;
24
25
public class AsyncLive {
26
public CompletableFuture<AsyncSession> connect(
27
String model,
28
LiveConnectConfig config);
29
}
30
```
31
32
## AsyncSession Class
33
34
```java { .api }
35
package com.google.genai;
36
37
public final class AsyncSession {
38
// Send client content
39
public CompletableFuture<Void> sendClientContent(
40
LiveSendClientContentParameters clientContent);
41
42
// Send realtime audio input
43
public CompletableFuture<Void> sendRealtimeInput(
44
LiveSendRealtimeInputParameters realtimeInput);
45
46
// Send tool/function response
47
public CompletableFuture<Void> sendToolResponse(
48
LiveSendToolResponseParameters toolResponse);
49
50
// Register callback for server messages
51
public CompletableFuture<Void> receive(
52
Consumer<LiveServerMessage> onMessage);
53
54
// Close WebSocket connection
55
public CompletableFuture<Void> close();
56
57
// Get session ID
58
public String sessionId();
59
}
60
```
61
62
## Live Connect Config
63
64
```java { .api }
65
package com.google.genai.types;
66
67
public final class LiveConnectConfig {
68
public static Builder builder();
69
70
public Optional<GenerateContentConfig> config();
71
public Optional<HttpOptions> httpOptions();
72
}
73
```
74
75
## Live Server Message
76
77
```java { .api }
78
package com.google.genai.types;
79
80
public final class LiveServerMessage {
81
public static LiveServerMessage fromJson(String json);
82
83
public Optional<SetupComplete> setupComplete();
84
public Optional<ServerContent> serverContent();
85
public Optional<ToolCall> toolCall();
86
public Optional<ToolCallCancellation> toolCallCancellation();
87
}
88
```
89
90
## Basic Usage
91
92
### Connect to Live Session
93
94
```java
95
import com.google.genai.Client;
96
import com.google.genai.AsyncLive;
97
import com.google.genai.AsyncSession;
98
99
Client client = new Client();
100
101
// Connect to live session
102
CompletableFuture<AsyncSession> sessionFuture =
103
client.async.live.connect("gemini-2.0-flash", null);
104
105
sessionFuture.thenAccept(session -> {
106
System.out.println("Connected! Session ID: " + session.sessionId());
107
108
// Register message receiver
109
session.receive(message -> {
110
message.serverContent().ifPresent(content -> {
111
System.out.println("Server: " + content);
112
});
113
});
114
115
// Send a message
116
LiveSendClientContentParameters params =
117
LiveSendClientContentParameters.builder()
118
.turns(List.of(
119
Content.fromParts(Part.fromText("Hello from live session!"))
120
))
121
.build();
122
123
session.sendClientContent(params).thenRun(() -> {
124
System.out.println("Message sent successfully");
125
});
126
});
127
```
128
129
### Connect with Configuration
130
131
```java
132
import com.google.genai.types.LiveConnectConfig;
133
import com.google.genai.types.GenerateContentConfig;
134
135
GenerateContentConfig contentConfig = GenerateContentConfig.builder()
136
.temperature(0.7)
137
.maxOutputTokens(1024)
138
.build();
139
140
LiveConnectConfig connectConfig = LiveConnectConfig.builder()
141
.config(contentConfig)
142
.build();
143
144
CompletableFuture<AsyncSession> sessionFuture =
145
client.async.live.connect("gemini-2.0-flash", connectConfig);
146
147
sessionFuture.thenAccept(session -> {
148
System.out.println("Connected with config");
149
});
150
```
151
152
## Sending Messages
153
154
### Send Text Content
155
156
```java
157
import com.google.genai.types.LiveSendClientContentParameters;
158
import com.google.genai.types.Content;
159
import com.google.genai.types.Part;
160
import java.util.List;
161
162
AsyncSession session = /* ... */;
163
164
Content userMessage = Content.fromParts(
165
Part.fromText("What is the weather like today?")
166
);
167
168
LiveSendClientContentParameters params =
169
LiveSendClientContentParameters.builder()
170
.turns(List.of(userMessage))
171
.turnComplete(true)
172
.build();
173
174
session.sendClientContent(params).thenRun(() -> {
175
System.out.println("Content sent");
176
}).exceptionally(error -> {
177
System.err.println("Failed to send: " + error.getMessage());
178
return null;
179
});
180
```
181
182
### Send Multiple Turns
183
184
```java
185
Content turn1 = Content.fromParts(Part.fromText("Tell me about AI"));
186
Content turn2 = Content.fromParts(Part.fromText("Specifically machine learning"));
187
188
LiveSendClientContentParameters params =
189
LiveSendClientContentParameters.builder()
190
.turns(List.of(turn1, turn2))
191
.turnComplete(true)
192
.build();
193
194
session.sendClientContent(params);
195
```
196
197
### Send Realtime Audio Input
198
199
```java
200
import com.google.genai.types.LiveSendRealtimeInputParameters;
201
202
// Send audio chunks for real-time processing
203
byte[] audioData = /* audio bytes */;
204
205
LiveSendRealtimeInputParameters audioParams =
206
LiveSendRealtimeInputParameters.builder()
207
.mediaChunks(List.of(audioData))
208
.build();
209
210
session.sendRealtimeInput(audioParams).thenRun(() -> {
211
System.out.println("Audio sent");
212
});
213
```
214
215
### Send Tool Response
216
217
```java
218
import com.google.genai.types.LiveSendToolResponseParameters;
219
import com.google.genai.types.FunctionResponse;
220
221
// Respond to a tool call from the model
222
FunctionResponse functionResponse = FunctionResponse.builder()
223
.name("get_weather")
224
.response(Map.of("temperature", 72, "condition", "sunny"))
225
.build();
226
227
LiveSendToolResponseParameters toolParams =
228
LiveSendToolResponseParameters.builder()
229
.functionResponses(List.of(functionResponse))
230
.build();
231
232
session.sendToolResponse(toolParams);
233
```
234
235
## Receiving Messages
236
237
### Register Message Callback
238
239
```java
240
import com.google.genai.types.LiveServerMessage;
241
242
AsyncSession session = /* ... */;
243
244
session.receive(message -> {
245
// Handle setup complete
246
message.setupComplete().ifPresent(setup -> {
247
System.out.println("Setup complete for session: " +
248
setup.sessionId().orElse("N/A"));
249
});
250
251
// Handle server content
252
message.serverContent().ifPresent(content -> {
253
content.modelTurn().ifPresent(turn -> {
254
turn.parts().ifPresent(parts -> {
255
for (Part part : parts) {
256
part.text().ifPresent(text -> {
257
System.out.print(text);
258
});
259
}
260
});
261
});
262
});
263
264
// Handle tool calls
265
message.toolCall().ifPresent(toolCall -> {
266
toolCall.functionCalls().ifPresent(calls -> {
267
for (FunctionCall call : calls) {
268
System.out.println("Tool call: " + call.name().orElse("N/A"));
269
// Execute function and send response
270
});
271
});
272
});
273
274
// Handle tool call cancellation
275
message.toolCallCancellation().ifPresent(cancellation -> {
276
System.out.println("Tool call cancelled");
277
});
278
});
279
```
280
281
### Stream Text Response
282
283
```java
284
session.receive(message -> {
285
message.serverContent().ifPresent(content -> {
286
content.modelTurn().ifPresent(turn -> {
287
turn.parts().ifPresent(parts -> {
288
// Stream each chunk of text as it arrives
289
parts.forEach(part -> {
290
part.text().ifPresent(text -> {
291
System.out.print(text);
292
System.out.flush();
293
});
294
});
295
});
296
});
297
298
// Check if turn is complete
299
if (content.turnComplete().orElse(false)) {
300
System.out.println("\n[Turn complete]");
301
}
302
});
303
});
304
```
305
306
## Complete Interactive Example
307
308
### Real-time Chat Session
309
310
```java
311
import java.util.Scanner;
312
import java.util.concurrent.CountDownLatch;
313
314
public class LiveChatExample {
315
public static void main(String[] args) throws Exception {
316
Client client = new Client();
317
318
CompletableFuture<AsyncSession> sessionFuture =
319
client.async.live.connect("gemini-2.0-flash", null);
320
321
AsyncSession session = sessionFuture.get();
322
System.out.println("Connected! Session: " + session.sessionId());
323
324
CountDownLatch responseLatch = new CountDownLatch(1);
325
326
// Register message handler
327
session.receive(message -> {
328
message.serverContent().ifPresent(content -> {
329
content.modelTurn().ifPresent(turn -> {
330
turn.parts().ifPresent(parts -> {
331
parts.forEach(part -> {
332
part.text().ifPresent(text -> {
333
System.out.print(text);
334
});
335
});
336
});
337
});
338
339
if (content.turnComplete().orElse(false)) {
340
System.out.println();
341
responseLatch.countDown();
342
}
343
});
344
});
345
346
Scanner scanner = new Scanner(System.in);
347
348
while (true) {
349
System.out.print("\nYou: ");
350
String input = scanner.nextLine();
351
352
if ("exit".equalsIgnoreCase(input)) {
353
break;
354
}
355
356
Content userContent = Content.fromParts(Part.fromText(input));
357
358
LiveSendClientContentParameters params =
359
LiveSendClientContentParameters.builder()
360
.turns(List.of(userContent))
361
.turnComplete(true)
362
.build();
363
364
System.out.print("Bot: ");
365
session.sendClientContent(params).get();
366
367
// Wait for response to complete
368
responseLatch.await();
369
responseLatch = new CountDownLatch(1);
370
}
371
372
session.close().get();
373
scanner.close();
374
client.close();
375
}
376
}
377
```
378
379
### Voice Assistant with Audio
380
381
```java
382
// Real-time audio streaming example
383
AsyncSession session = client.async.live.connect(
384
"gemini-2.0-flash",
385
null
386
).get();
387
388
session.receive(message -> {
389
message.serverContent().ifPresent(content -> {
390
// Handle audio response from model
391
content.modelTurn().ifPresent(turn -> {
392
turn.parts().ifPresent(parts -> {
393
parts.forEach(part -> {
394
part.text().ifPresent(text -> {
395
System.out.println("Model: " + text);
396
});
397
// Handle audio output if present
398
part.inlineData().ifPresent(blob -> {
399
// Play audio response
400
});
401
});
402
});
403
});
404
});
405
});
406
407
// Stream audio input in real-time
408
try (AudioInputStream audioStream = /* microphone input */) {
409
byte[] buffer = new byte[4096];
410
int bytesRead;
411
412
while ((bytesRead = audioStream.read(buffer)) != -1) {
413
byte[] audioChunk = Arrays.copyOf(buffer, bytesRead);
414
415
LiveSendRealtimeInputParameters params =
416
LiveSendRealtimeInputParameters.builder()
417
.mediaChunks(List.of(audioChunk))
418
.build();
419
420
session.sendRealtimeInput(params);
421
}
422
}
423
```
424
425
## Function Calling in Live Sessions
426
427
### Register Functions and Handle Calls
428
429
```java
430
import com.google.genai.types.Tool;
431
import com.google.genai.types.FunctionDeclaration;
432
import com.google.genai.types.Schema;
433
434
// Define functions
435
FunctionDeclaration weatherFunction = FunctionDeclaration.builder()
436
.name("get_weather")
437
.description("Get current weather for a location")
438
.parameters(Schema.builder()
439
.type("object")
440
.properties(Map.of(
441
"location", Schema.builder().type("string").build()
442
))
443
.required(List.of("location"))
444
.build())
445
.build();
446
447
Tool tool = Tool.builder()
448
.functionDeclarations(List.of(weatherFunction))
449
.build();
450
451
GenerateContentConfig config = GenerateContentConfig.builder()
452
.tools(List.of(tool))
453
.build();
454
455
LiveConnectConfig liveConfig = LiveConnectConfig.builder()
456
.config(config)
457
.build();
458
459
AsyncSession session = client.async.live.connect(
460
"gemini-2.0-flash",
461
liveConfig
462
).get();
463
464
// Handle tool calls
465
session.receive(message -> {
466
message.toolCall().ifPresent(toolCall -> {
467
toolCall.functionCalls().ifPresent(calls -> {
468
for (FunctionCall call : calls) {
469
String functionName = call.name().orElse("");
470
JsonNode args = call.args().orElse(null);
471
472
if ("get_weather".equals(functionName)) {
473
// Execute function
474
String location = args.get("location").asText();
475
Map<String, Object> result = getWeather(location);
476
477
// Send response back
478
FunctionResponse response = FunctionResponse.builder()
479
.name(functionName)
480
.id(call.id().orElse(""))
481
.response(result)
482
.build();
483
484
LiveSendToolResponseParameters params =
485
LiveSendToolResponseParameters.builder()
486
.functionResponses(List.of(response))
487
.build();
488
489
session.sendToolResponse(params);
490
}
491
}
492
});
493
});
494
});
495
```
496
497
## Closing Sessions
498
499
### Graceful Shutdown
500
501
```java
502
AsyncSession session = /* ... */;
503
504
// Close when done
505
session.close().thenRun(() -> {
506
System.out.println("Session closed successfully");
507
}).exceptionally(error -> {
508
System.err.println("Error closing session: " + error.getMessage());
509
return null;
510
});
511
```
512
513
### Close with try-with-resources Pattern
514
515
Live sessions don't implement AutoCloseable, so manual cleanup is required:
516
517
```java
518
AsyncSession session = null;
519
try {
520
session = client.async.live.connect("gemini-2.0-flash", null).get();
521
522
// Use session...
523
524
} finally {
525
if (session != null) {
526
session.close().get();
527
}
528
}
529
```
530
531
## Error Handling
532
533
### Handle Connection Errors
534
535
```java
536
CompletableFuture<AsyncSession> sessionFuture =
537
client.async.live.connect("gemini-2.0-flash", null);
538
539
sessionFuture
540
.thenAccept(session -> {
541
System.out.println("Connected successfully");
542
})
543
.exceptionally(error -> {
544
System.err.println("Connection failed: " + error.getMessage());
545
if (error instanceof GenAiIOException) {
546
System.err.println("I/O error during connection");
547
}
548
return null;
549
});
550
```
551
552
### Handle Send Failures
553
554
```java
555
session.sendClientContent(params)
556
.thenRun(() -> {
557
System.out.println("Message sent");
558
})
559
.exceptionally(error -> {
560
System.err.println("Failed to send message: " + error.getMessage());
561
// Optionally retry or reconnect
562
return null;
563
});
564
```
565
566
## Best Practices
567
568
### Connection Management
569
570
```java
571
// Keep session alive for multiple interactions
572
AsyncSession session = client.async.live.connect(
573
"gemini-2.0-flash",
574
null
575
).get();
576
577
try {
578
// Use session for multiple messages
579
for (String userInput : userInputs) {
580
LiveSendClientContentParameters params =
581
LiveSendClientContentParameters.builder()
582
.turns(List.of(Content.fromParts(Part.fromText(userInput))))
583
.turnComplete(true)
584
.build();
585
586
session.sendClientContent(params).get();
587
// Process response...
588
}
589
} finally {
590
// Always close when done
591
session.close().get();
592
}
593
```
594
595
### Handle Reconnection
596
597
```java
598
AsyncSession session = null;
599
int maxRetries = 3;
600
int retryCount = 0;
601
602
while (retryCount < maxRetries) {
603
try {
604
session = client.async.live.connect("gemini-2.0-flash", null).get();
605
break; // Success
606
} catch (Exception e) {
607
retryCount++;
608
System.err.println("Connection attempt " + retryCount + " failed");
609
if (retryCount < maxRetries) {
610
Thread.sleep(1000 * retryCount); // Exponential backoff
611
}
612
}
613
}
614
615
if (session == null) {
616
throw new RuntimeException("Failed to connect after " + maxRetries + " attempts");
617
}
618
```
619
620
### Message Synchronization
621
622
Since callbacks are async, use synchronization primitives when needed:
623
624
```java
625
import java.util.concurrent.CountDownLatch;
626
import java.util.concurrent.TimeUnit;
627
628
CountDownLatch responseLatch = new CountDownLatch(1);
629
AtomicReference<String> response = new AtomicReference<>();
630
631
session.receive(message -> {
632
message.serverContent().ifPresent(content -> {
633
if (content.turnComplete().orElse(false)) {
634
content.modelTurn().ifPresent(turn -> {
635
// Collect response
636
response.set(extractText(turn));
637
responseLatch.countDown();
638
});
639
}
640
});
641
});
642
643
// Send message
644
session.sendClientContent(params).get();
645
646
// Wait for response (with timeout)
647
if (responseLatch.await(30, TimeUnit.SECONDS)) {
648
System.out.println("Response: " + response.get());
649
} else {
650
System.err.println("Timeout waiting for response");
651
}
652
```
653
654
## Limitations
655
656
### Experimental Status
657
658
- API is subject to change without notice
659
- May have stability issues
660
- Not recommended for production use
661
662
### WebSocket Constraints
663
664
- Single callback per session (last registered wins)
665
- No automatic reconnection
666
- Manual error handling required
667
- Connection may drop unexpectedly
668
669
### Configuration Limits
670
671
- HttpOptions not supported at request level (use client-level config)
672
- Some GenerateContentConfig options may not be supported
673
- Check documentation for supported config parameters
674
675
## Use Cases
676
677
### Real-time Voice Assistant
678
679
Low-latency audio streaming for voice conversations with minimal delay.
680
681
### Interactive Chatbot
682
683
Streaming text responses for responsive user experiences.
684
685
### Live Translation
686
687
Real-time translation of speech or text with immediate feedback.
688
689
### Collaborative Coding Assistant
690
691
Interactive code completion and explanation with streaming responses.
692
693
### Real-time Content Moderation
694
695
Live analysis of user-generated content with immediate feedback.
696