Build intelligent Android apps with Google's AI
Android Developers
0:00 [MUSIC PLAYING] JOLANDA VERHOEF: Let's get started.
0:07 My name is Jolanda Verhoef, and I will be joined later by my colleague Thomas.
0:13 Our approach to AI on Android is based on three core pillars.
0:18 So first of all, the Android operating
0:21 system is evolving into an intelligent system,
0:24 and you can expose your app's capabilities to that system.
0:28 Second, you can bring intelligence
0:30 into your app using Cloud and on-device models.
0:33 And finally, you can use developer productivity
0:38 to use intelligence to build your apps.
0:40 Now, together, these three pillars represent our commitment
0:44 to embedding intelligence throughout the Android ecosystem.
0:48 And while all three of them are crucial to the future of Android,
0:52 today, I want to focus on this middle pillar.
0:55 So together with Thomas, we're going to make sure that you
0:58 learn everything about in-app intelligence today.
1:01 Now, if you want to learn more about the other two pillars,
1:04 you can watch "What's new in Android" to learn more about the first pillar,
1:09 the intelligence system.
1:11 Or you can watch "What's new in Android development
1:13 tools" if you want to learn more about developer productivity.
1:18 Now, for today, we're going to, at a high level, cover five different areas.
1:22 So I will start with on-device inference, and then Thomas will be here to talk
1:28 about cloud and to talk about hybrid inference.
1:30 And I'll be back again to talk about agents running
1:33 in the cloud and how you can connect to them.
1:35 And then finally, we'll have a sneak preview into running agents on device.
1:41 So how are we going to talk about those?
1:45 Well, what we want to do is we want to take a travel app called Jetpacker,
1:48 which our team has been building over the past weeks/months.
1:52 And we're going to start with a very basic travel app.
1:55 And throughout the talk,
1:56 we're going to make that more personalized, intelligent, and agentic.
2:01 And so right now, the app already looks quite nice,
2:04 but it isn't yet using the newest intelligence APIs.
2:08 So I actually have the app running on my device.
2:11 So without further ado, let's have a look at it.
2:15 So let's have a look.
2:17 We should see my phone.
2:17 There we go.
2:19 And as you can see, we have the Jetpacker app running there.
2:22 So let's open it up.
2:23 And you can also see in the right top
2:25 of my screen that I'm actually currently in airplane mode,
2:28 so I don't have any internet connection.
2:30 And as you can see, I have my current California trip right here.
2:34 We can look at our upcoming trips.
2:36 I'm going to Ireland later.
2:38 And then later this year, I'll be in Paris.
2:40 And we can have a quick look at our past trips as well.
2:43 So here, we have an overview of all our trips.
2:46 We can go to our Itinerary screen to have
2:49 a deeper look at what each of the days looks like.
2:52 And then we can also go to the Detail screen as well.
2:55 So far, so good.
2:57 Basic app, but it isn't yet using any form of intelligent APIs.
3:02 So let's go back to our slides and have
3:04 a look at the first feature that we want to build.
3:09 So during today's session, we're going to walk you through not one,
3:13 not two, but seven different intelligent features.
3:17 And so I think we should just get going with the first one.
3:21 So for our first feature, we're going to look at our Itinerary screen.
3:24 We know from our users that that screen can actually be quite overwhelming,
3:28 especially when you have a long trip coming up.
3:30 There's a lot of stuff happening.
3:32 So what we want to do,
3:33 we want to create a card at the top of the screen that summarizes the upcoming
3:38 trip and that includes some information on how
3:40 the user can best prepare for that trip.
3:43 So for this, what we'll do is we'll access a model
3:47 and we'll give it some input and we will get some outputs.
3:50 So in this case, we will give it the full trip itinerary.
3:53 And then as outputs, we will get a short summary and we will get
3:57 some tips on things to pack and phrases to learn.
4:01 So this setup is actually a great candidate for using an on-device model.
4:07 It has shorter inputs.
4:09 It has shorter outputs,
4:10 making sure that that on-device model can run really fast.
4:15 Now, when you use an on-device model, of course,
4:17 you have no additional cloud inference costs,
4:21 and we don't have to worry about internet connectivity,
4:23 since the model is going to be consistently working even when we
4:26 have spotty internet or if we have no internet connection at all.
4:29 And given that we're traveling, that's quite a nice feature to have.
4:34 So if we're going to want to build with on-device features,
4:37 we're going to have to use Gemini Nano.
4:40 Gemini Nano is Google's most efficient
4:43 model that is optimized for mobile devices.
4:46 We first introduced Nano a few years ago, and by now,
4:50 we have over 140 million devices running versions of Nano.
4:56 And our latest version, Nano 4, is based on the same architectural foundation
5:01 as the recently released Gemma 4 model,
5:04 and then got further optimized for maximum battery and performance efficiency.
5:10 Now, Gemini Nano 4 is coming to consumer devices later this year,
5:13 but as a developer, you can already preview and prototype with it.
5:19 And so for today's demos,
5:21 we're going to use Gemini Nano 4 for our use cases and show
5:25 you how capable that model actually is in a whole range of different scenarios.
5:31 So let's dive right into our code using the ML Kit GenAI Prompt API.
5:36 This API gives us access to that Gemini Nano model that runs on-device.
5:42 So with this API, we simply take our trip
5:45 itinerary and then we add it to our prompt,
5:48 and we ask our model to generate a summary of our trip,
5:51 along with tips on preparing for the trip.
5:54 Now, here, what I did is I just wrote a prompt myself.
5:57 I just sat down and thought, what would I ask this model?
6:01 And that's great, but we kind of want to iterate on that.
6:04 It's always good to test out a prompt before you bring it to production
6:07 and kind of see how you can make it fit well with your use case.
6:11 So let's switch back to our phone and let's do just that.
6:15 So in order to do that, I'm going
6:17 to actually close my Jetpacker app for a second,
6:19 and I'm going to go into the AICore app.
6:22 So as you can see, there's an app here that's called AICore.
6:26 And you can get that app if you join the AICore developer preview.
6:29 So this is not something that every Android user sees,
6:32 but if you join the developer preview, you get access to this app.
6:36 It is available on all devices that support AICore.
6:39 And if you don't have a physical device with that model running,
6:42 what you can do is you can actually also go
6:45 to Android Studio and you can use the Gemma 4 model there.
6:49 So let's have a look at the AICore app.
6:51 As you can see, we have Gemini Nano 3 there,
6:54 but we also have Nano 4 Fast and we have Nano 4 Full.
6:58 So here, we can choose which of the models.
7:00 Now, I already downloaded them just to make sure
7:02 that this talk isn't taking an hour on this Wi-Fi.
7:06 So let me open the fast model and have a look.
7:09 So let's start with the prompt that I thought of myself originally.
7:13 So I just copied it over and I put in my Paris trip.
7:18 So when we do this, as you can see,
7:20 this is generating a response, but it's generating quite a long response.
7:27 This is taking quite some time.
7:29 There's a lot of information.
7:30 And we were trying to make things easier
7:32 to parse for our users, not more difficult.
7:35 So we want to make sure that we're
7:36 not spending this much time generating this much text.
7:40 So this is where we start iterating.
7:42 Now, I did some of that iteration and I actually came up
7:44 with the final prompt that might be useful for us to look at.
7:49 So here, what I did is— let's first take a look.
7:52 We got a very fast response.
7:54 And as you can see, I added a little bit more guiding for the model.
7:58 So I told it to use one sentence, less than 15 words, et cetera.
8:02 And this is kind of a good way to guide
8:04 the model into the response that we actually want to have.
8:07 And with that, you could see that it started immediately generating a response.
8:11 And it took only, what is it?
8:13 1.6 seconds to generate it.
8:15 Now, let's have a look at that in our Jetpacker app.
8:18 So I'll go back to the app.
8:20 I'll go to my secret debug menu, turn on the feature,
8:24 and I'll go to my upcoming Paris trip.
8:27 And pay good notice, because this is going to be fast.
8:30 So there we go.
8:33 We immediately have it coming up.
8:35 [APPLAUSE] Amazing.
8:40 Let's switch back to our slides.
8:44 With that, we can mentally prepare for our trip
8:47 and we can move on to our next feature.
8:50 And for me, if I'm traveling,
8:52 one of the things that I really don't like to do that much is budgeting.
8:57 And it's managing how much I'm spending on souvenirs,
8:59 on food, on all those things.
9:01 So I usually end up with a whole bunch of receipts
9:05 that are all in my backpack and in my pockets,
9:08 and then I have to sort through and tally all of them.
9:11 So for such a tedious task,
9:13 wouldn't it be nice if we had AI to help us with that?
9:18 And since receipts might contain sensitive
9:20 information like credit card numbers and addresses,
9:22 this is another great use case for using
9:25 an on-device solution so users can be confident that private
9:29 information will actually be processed locally on the device
9:32 without any of their data being sent to the cloud.
9:36 Nano 4 excels at multimodality,
9:38 and so this especially includes image understanding
9:41 for tasks like OCR and visual data extraction.
9:46 So naturally, it will excel at extracting information for our receipts as well.
9:51 So let's have a look at how this works.
9:55 In our last example, we only passed in a text prompt.
9:59 But in this example, we'll pass in both a text and an image to be processed.
10:05 And then for our text prompt, we will specify that we want three
10:08 pieces of information here based on the receipt.
10:11 We want a generated title.
10:12 We want to get an amount and a category.
10:16 And to make sure that the returned result is consistent,
10:19 we'll also tell the model that we want it to return a certain JSON object.
10:25 So let's see this feature in action before we continue with the slides.
10:29 Let's go to our phone, and let me quickly turn on this extra new feature.
10:35 I have to shake my phone in order to go to the debug menu.
10:38 There we go.
10:39 I'll turn on the expense management and I'll go to my current trip.
10:43 So we'll go to the California trip.
10:45 And actually, this morning, I was very,
10:48 very tired because I'm from the Netherlands and I got jet lag.
10:51 So I got someone to bring me a coffee and I actually got the receipt.
10:55 So let's take an image of that receipt.
10:58 So I, here, have my expense menu.
10:59 I already went for dinner.
11:00 I already did some stuff while I was here in San Francisco.
11:04 But now, let's take a picture of our receipt.
11:08 Here we go.
11:08 Say hi, everyone.
11:09 Yay.
11:11 And let's take a picture.
11:12 There we go.
11:15 And this is taking a little bit longer because
11:17 for this, I'm actually using the Gemini full model.
11:20 So you saw that we had a fast and we had a full model.
11:23 And in this case, we want to have that full image recognition,
11:26 so we're using that more complex model for us.
11:29 And as you can see, it recognizes that we
11:32 did an espresso blend purchase, which was $5.94.
11:36 That is correct.
11:37 Amazing.
11:38 Cool, let's go back to the slides.
11:40 [APPLAUSE] I'm always so happy when demos actually work.
11:47 [LAUGHS] This one was the scariest one, but hey, there we go.
11:50 And as you saw, this is already working pretty well, right?
11:53 But you might have noticed that we had to explain
11:55 to the model what kind of fields that we need,
11:58 and we had to give it a JSON example of what that then actually looks like.
12:03 And then after we wrote that whole prompt,
12:05 we then had to go and parse the return data,
12:07 which we hope is that JSON, into a data class that we can use in our app.
12:13 This is a lot of manual steps, and all of those manual steps can go wrong.
12:17 So it's kind of scary.
12:19 And this is why we're introducing a Structured Output API.
12:23 This API is going to land soon,
12:25 but let me give you a quick sneak preview into what it will look like.
12:30 So with our Structured Output API, we can mark any data class as generable.
12:35 And then we can further describe the class
12:38 using guides for each of the properties.
12:41 So these annotations basically guide the model and tell
12:44 it what kind of data it should generate.
12:48 If we do this, we can actually now, for our request, simplify our prompt.
12:54 We don't have to guide it anymore there.
12:57 And then we can use the method called generateTypedContentRequest that takes
13:01 the parsed receipt class name to restrict what the expected output should be.
13:06 Let's make sure I don't lose my receipt.
13:10 And now, our response simply contains this parsed receipt instance,
13:14 or it will return null if it wasn't able to find one.
13:18 So with structured output, we can be more confident about consistent outputs,
13:22 and our code is much, much simpler, with Kotlin data classes
13:26 that integrate seamlessly with the Android code base.
13:31 Now, during this talk, we prototyped some pretty cool features with on-device
13:34 APIs using the latest Gemini Nano 4 preview model, but this is just the start.
13:40 We already have seen lots of apps using the Prompt API in production
13:44 to leverage the power of Gemini Nano for use cases such as classification,
13:49 summarization, content inspiration, those kind of things.
13:54 If you want to learn more about how you can get the latest in on-device Android,
13:59 you can check out this talk, where we are going to go more in depth
14:02 on how you can ship on-device use cases to production.
14:06 Next, I will hand it off to Thomas,
14:08 who will walk you through the next couple of features.
14:11 [APPLAUSE] THOMAS EZAN: Thank you, Jolanda.
14:15 So yeah, Gemini Nano 4 is pretty impressive,
14:19 and it's really exciting to see how on-device
14:22 models are getting better and better every year.
14:25 So we talked about Gemini Nano that is
14:28 basically optimized to run on your Android device efficiently,
14:32 but sometimes you have use cases that require an AI model
14:37 that has either a greater world knowledge or a much larger context window,
14:43 or sometimes even greater ability in handling complex tasks.
14:48 So let's take a look at what we can build with these cloud models.
14:53 So we are going to use them to build our next feature in the Jetpacker app.
14:58 So we are going to build a museum assistant.
15:01 So it will be a chatbot that is powered by Gemini Flash
15:04 and enables you to ask questions to plan your next visit to, let's say,
15:10 the Louvre Museum in Paris.
15:13 So first, you need to add the Firebase AI Logic to your project.
15:18 And once you do that, with just a few lines of Kotlin code,
15:23 you can directly call the Gemini models that are running in the cloud.
15:29 You will start by instantiating a generative model,
15:32 and you will pass the specific version of Gemini that you want to use.
15:37 And then you basically just have to call start chat to create a chat.
15:43 And the cool thing about the SDK is
15:45 that it will actually manage the chat history for you.
15:50 So the communication between your app and the model
15:53 is actually fully handled by the Firebase SDK.
15:57 There are three series of Gemini AI models
16:01 that are running in Google Cloud that you can use.
16:04 So there is Gemini Pro, which is really good for complex tasks.
16:08 There is Gemini Flash, which has a very low latency.
16:12 And Gemini Flash Lite, which offers a really good intelligence cost ratio,
16:18 and also has a very low latency.
16:23 So we want to build a chatbot that is really knowledgeable about the museum.
16:28 And earlier, I mentioned that cloud
16:31 models store massive amounts of world knowledge.
16:34 So you can assume that Gemini already knows quite a lot about the Louvre,
16:40 but it doesn't necessarily know everything there is to know about it.
16:45 So for example, if you ask the model about
16:48 the current temporary exhibitions that are happening at the Louvre,
16:52 the chatbot will basically tell us to go
16:55 to the website and search for it ourselves.
16:58 So it's not super helpful.
17:01 So what we can do to prevent this is use a technique called grounding.
17:06 So in the context window, which is the full input that is passed to the model,
17:10 we are going to add some relevant content
17:13 to help the model answer the user's query better.
17:17 So grounding techniques are also used
17:19 in the context of Retrieval-Augmented Generation, or RAG.
17:25 So you can implement it yourself,
17:27 but we also made it easy for you with the following APIs.
17:32 There is URL grounding,
17:34 which enables you to use a document at a specific URL, there is maps grounding,
17:41 which uses the data from Google Maps,
17:44 and there is web grounding that is using real-time web data.
17:49 So let's see how we can use them.
17:51 We are going to start with URL grounding.
17:54 So let's imagine that you want to prioritize some data
17:58 from a specific page that is hosted on the web.
18:01 So you will start by adding the URL context tool
18:05 to the list of tools when you instantiate the model.
18:09 And then in the user prompt, we will tell the model to look at the specific
18:14 page at the URL to grant the response.
18:18 And so you can see that here, we are actually using the FAQ URL of the museum.
18:23 So here, we are only using one URL,
18:26 but you can actually use up to 20 URLs per request.
18:31 And so now, if we ask the chatbot about,
18:34 for instance, criteria to get discounted tickets,
18:38 for example, Gemini is going to actually use
18:41 the content of the FAQ page to answer.
18:43 So if I say, for example, if having a cat named Mona Lisa grants you
18:48 a discount to get a ticket at the Louvre,
18:51 you will see that basically, the chatbot is saying no.
18:55 And as accurately outlined in the FAQ, that is not enough to get a discount.
19:02 If we want to give the chatbot
19:04 the ability to retrieve some information from Google Maps,
19:07 we can use the Google Maps tool.
19:10 So that will, for instance, enable the chatbot to search for cafes
19:15 or restaurants around the museum after our visit.
19:19 So if, after adding the tool, when I ask,
19:23 what are the best restaurants that are good for children next to the Louvre,
19:28 we will actually get a pretty comprehensive response from the chatbot.
19:32 It will query the data from Google Maps and return a list of restaurants,
19:39 and it's actually anchoring on restaurants that are
19:43 clearly known for having a children's menu.
19:47 And so we can also use web search grounding to, for instance,
19:51 let the chatbot search for more recent information on the web.
19:56 So we now have a pretty competent museum
19:59 chatbot to enable us to prepare the visit.
20:03 And so the cool thing is that we built
20:05 all of that with Gemini Flash in Firebase AI Logic.
20:10 And actually, the Gemini Pro and Gemini Flash models are perfect to build,
20:14 let's say, the first iteration of your AI feature.
20:18 So whether you need multimodal understanding,
20:21 JSON generation, function calling, or even image generation,
20:26 you can quickly build everything in Kotlin without
20:29 really needing any server code or any backend resources.
20:35 And the cool thing is that if your feature
20:37 actually doesn't rely on your own backend infrastructure,
20:41 you can really go to production with it and scale it.
20:44 You can use AI monitoring features in the Firebase AI Logic SDK.
20:50 You can use server prompt templates and App
20:52 Check and basically scale to your whole user audience.
20:58 And if you think about it, you probably already have some features in your app
21:01 that are good candidates to use Gemini in Firebase AI Logic,
21:05 so I strongly encourage you to look into it.
21:10 So it's actually used already by hundreds of apps in production.
21:13 So for instance, the redBus application, which is a ticketing platform,
21:18 uses the Gemini audio understanding capabilities to create a voice-first,
21:24 multilingual review system.
21:27 It's also used by Karrot, which is a marketplace app that basically uses
21:32 it to translate messages between buyers and sellers.
21:37 Gratitude, a journaling app, is using it to suggest journal entries.
21:43 And finally, UltraHuman, which is a fitness tracker app,
21:47 is using it to build a food
21:50 logging feature using the Gemini image understanding capabilities.
21:55 So a lot of interesting use cases.
22:00 OK, so let's take a step back for a second.
22:03 So we saw that many of you want to build
22:06 with Gemini Flash and Gemini Pro using cloud inference.
22:10 And earlier, Jolanda showed all the cool
22:12 things you can build with Gemini Nano on-device.
22:15 But we also heard some feedback from you.
22:18 You basically need to support users on devices
22:21 that don't necessarily support Gemini Nano just yet.
22:26 So what if we could just combine both, right?
22:29 That's actually the promise of hybrid inference.
22:32 And I think I have a really good use case for it.
22:35 So reviews are a pretty key element in most Android applications today.
22:41 So in your app, maybe you're asking your users to write other users,
22:46 or write a business,
22:47 or even a piece of content, like, I don't know, a song or a show.
22:52 And so you're often asking your users to basically write a review,
22:56 or sometimes you're even asking users to post
22:59 a review for your application in Google Play.
23:02 And it's important for you, but it can be sometimes tedious for your users.
23:06 So we think Gemini Nano can actually be super helpful for that.
23:11 But you also need to have this feature available
23:14 on devices that don't support Gemini Nano just yet.
23:19 So in the Jetpacker app, earlier, the chatbot museum recommended restaurants.
23:25 And so what if we were to implement a restaurant review feature in the app?
23:31 So here, you can see that we have a list
23:33 of topics to choose from about how we felt about the restaurant.
23:38 And we will let the model draft the short review for us.
23:42 And the user is always going to be able to edit it later before posting it.
23:47 So here, you can see we are selecting some topics.
23:50 And once we are done, we are clicking on generating the review.
23:55 And basically, if Gemini Nano is available on the device,
24:00 the review will be generated by Gemini Nano.
24:04 But if not, it will default to Gemini Flash Lite in the cloud.
24:07 So it's completely transparent for the users,
24:10 and it's also very easy for you to build as a developer.
24:14 So to build this, we are actually using the latest API from Firebase AI Logic.
24:20 So to do that, you need to add
24:23 the on-device Gradle app dependency to your project.
24:27 And then— so you can see here that we basically generate
24:30 a review with a prompt that is interpolating the selected topics.
24:37 And then when we instantiate the model,
24:40 you can see that we are passing an onDeviceConfig object,
24:43 where we define the inference mode that we want to use.
24:47 So here, you see that we are saying prefer on-device,
24:51 so we will prioritize on-device inference.
24:55 So this API supports four inference modes.
24:59 So there is prefer on device, prefer Cloud.
25:02 And there is also only on device and only cloud.
25:07 And it's actually available today, so you can try it out and you
25:11 can learn more about it in the Firebase documentation.
25:16 So we just talked about a very simple routing logic.
25:20 Here, it's basically two criteria.
25:23 Is Gemini Nano available on the device?
25:25 And is the device online?
25:28 But sometimes you want to build something that is a little bit more complex,
25:33 so you can imagine having a pretty advanced custom routing logic.
25:38 So for instance, you can monitor the system health of the device,
25:43 and you can decide to use a cloud model if,
25:46 let's say, the CPU is overloaded or if
25:51 the battery of the device is below a specific threshold.
25:56 And another thing worth checking is also the latency.
25:59 So if the latency is above a specific threshold,
26:02 you can decide to focus on on-device.
26:06 Another thing, too, to keep in mind,
26:07 is that not every single query requires a very
26:12 advanced model running in the cloud, and some do.
26:17 So it can be interesting sometimes to use a lightweight LLM, like for instance,
26:22 the Gemma 3 model that is only 270 million parameters,
26:28 to basically route those queries based on their complexity.
26:32 And at the end of the day, I'm just listing three criterias here,
26:35 but there are many other criteria that you want to take into account based
26:40 on your app's needs or also the user experience that you want to provide.
26:47 So if we go back to the Jetpacker app,
26:50 let's say that we now want to implement instant messaging translation
26:53 for a chat feature between the hotel staff and the customers.
26:58 So the customers and the hotel staff
27:00 will basically use their own language to chat,
27:03 and we'll use the AI for translation.
27:06 So let's see how we can use hybrid here.
27:09 So let's imagine that we want
27:12 to prioritize on-device to save on inference costs.
27:15 We also want low latency.
27:18 So we provide a really real-time experience to the users.
27:22 And we also want to make sure that we
27:26 basically support as many languages on as many devices possible.
27:32 So we know that on-device translation capabilities
27:35 are getting better with Gemini Nano models,
27:39 but we also want to be able to fall back
27:41 to the cloud if the model doesn't support the language.
27:45 And so in this case, we'll use TranslateGemma,
27:48 which is an open-weight model based off of the Gemma
27:51 model that can be potentially fine-tuned if you want.
27:57 And so here is the inference stack that we are going to use.
28:00 So for on-device inference,
28:02 we will use Gemini Nano models through the ML Kit Prompt API.
28:07 And for the cloud inference,
28:08 we will use TranslateGemma that will be hosted on Google Cloud.
28:12 And we will also use the on-device ML Kit Language Identification API
28:16 that will be able to detect the language used in the conversation.
28:23 So we will implement the appropriate routing logic based
28:27 on the version of the model that is available on the device,
28:30 the language that is used, and also the latency of the network.
28:35 And so here, in this diagram,
28:37 we are basically implementing the routing logic in code.
28:40 But there are already experiments to use AI to actually define the routing.
28:45 And in a minute, Jolanda is going to show
28:48 us how the agentic approach can help us with that.
28:52 So let's see the translation feature in action.
28:55 So let's say that I'm typing in Dutch,
28:58 but I'm basically talking to a hotel in France,
29:01 and the staff speaks mainly in French.
29:04 So I will send my message and I will receive
29:08 a response that basically enables me to translate— using hybrid inference,
29:16 translate the message in Dutch.
29:18 And on the other end, the staff can also have the same setup,
29:22 where they can basically translate the message
29:26 that was sent by the user to their language.
29:28 And so here, the translation will either be on the device or on the cloud,
29:33 based on the criteria that we talked about before.
29:36 It will be, again, completely transparent for the users,
29:39 but we'll have a very high-quality translation
29:42 feature that is running via hybrid inference.
29:47 So this custom hybrid inference approach is
29:50 already used by several applications in production.
29:53 For instance, the Gboard app is using that.
29:56 It's also used in the Pixel Screenshots application.
29:59 And the Kakao mobility app also started using it.
30:04 And so with that, I will pass it back to Jolanda to talk about agentic systems.
30:10 JOLANDA VERHOEF: Thank you, Thomas.
30:12 [APPLAUSE] OK.
30:15 For our next feature, we want to take our app to the next level
30:20 and we want to connect it to our cloud backend.
30:24 So we have a Jetpacker backend running
30:27 in the cloud that is able to reserve flights,
30:30 hotels and activities on our user's behalf.
30:33 Now, in our app, we simply want the user to be able to go to the booking screen
30:37 and then automatically kick off that booking process.
30:40 And it will automatically book all the things that that user wants to do.
30:44 And then the booking process will be running fully autonomously.
30:48 And our Android app is just showing the progress
30:50 of all of these different booking agents working.
30:54 And it will let the user provide input when needed.
30:58 So before we show how we can build this, let's
31:01 go back to the phone and look at it in action.
31:05 So in order to run this, let me first turn off my airplane mode,
31:09 because we have a backend this time around.
31:12 So we have internet going on, I hope.
31:15 And we'll open our Jetpacker app again, and we'll turn on the Booking Assistant.
31:20 There we go.
31:22 Now, if I open my current app, let's say, or my current trip,
31:26 I can go to the booking screen and I can start our booking.
31:30 And as you can see, it is connecting to our booking server.
31:35 Now, while this is connecting, as you can see,
31:37 this is taking a little while because I need to connect
31:40 to this server that is running that is doing a whole bunch of stuff.
31:44 I do hope it will connect in time, before the end of the talk.
31:48 It might be that my Wi-Fi is not as strong as I was hoping it would be.
31:52 Look, there it is.
31:52 OK, amazing.
31:54 So as you can see, what we did is we basically just sent
31:56 our itinerary to that server and it started up a session for us.
32:00 And it's then kicking off all of these different booking agents for me.
32:04 So it's kicking off four agents to book activities.
32:08 So here, I see my lunch and my dinner and all kinds of bookings there.
32:13 Same for my hotel, and then the same for the flights.
32:16 But all of those need some kind of information from me.
32:19 So for example, let's say that for my SFO to Amsterdam flight,
32:23 I will confirm that indeed that is the right time frame for me.
32:27 I can confirm the selection and I get to choose a chair.
32:31 However, in the meantime, while all of these agents are running,
32:35 if I'm not doing anything else, I quit the app.
32:37 I go do something else, and I come back tomorrow.
32:40 And I come back into the app.
32:41 I can reconnect to that existing session.
32:43 So now if I go back to my ongoing connection, as you can see,
32:48 it will just reconnect and it will find all of those agents that were running.
32:52 And surely, it should show all of them.
32:56 It is, again, maybe not the fastest Wi-Fi here.
32:59 But in the meantime, as you can see,
33:01 it's still asking me— it still remembers where I was in the process,
33:04 so it's still asking me for that seat number.
33:07 So I can confirm that seat number.
33:08 I can say I confirm my whole booking.
33:11 And there we go.
33:13 As you can see, I think my internet is fully out now,
33:15 but this would normally show the full confirmation and we'd be done.
33:20 There's not a full talk that you can do without having one demo hiccup, right?
33:24 So this is the one.
33:25 [APPLAUSE] I already assumed it would be
33:30 the one where I'm actually using the internet.
33:34 So this is why we have on-device inference, people.
33:36 [LAUGHS] OK.
33:39 So before, Thomas was already speaking
33:41 to you about Firebase using a managed backend.
33:44 And this is ideal for getting started or when,
33:47 as a mobile team, you want to develop in isolation.
33:50 And it provides and focuses on direct client-to-model inference,
33:54 which makes it kind of, fundamentally, stateless.
33:58 And so for our trip booking, we instead use a custom self-hosted backend.
34:02 This server, which we fully control and gives us full flexibility.
34:07 And so when we book sessions, even when the user closes the app,
34:11 that system can just continue running in the cloud.
34:14 It also gives us complex multi-step orchestration.
34:17 And because it's running in our own backend,
34:19 it gives us access to our company's data.
34:23 So how would we architect such a solution?
34:25 Well, if we go and take it all the way back to its core,
34:28 we basically have a cloud backend and we have an Android app,
34:31 and they somehow communicate with each other.
34:34 Now, we want that to be, basically,
34:36 a server or an event-driven communication that goes both directions.
34:41 So some ways of doing that transportation would
34:44 be to use server-sent events or to use WebSockets.
34:47 Then, we have our connection set up between the two,
34:49 but then what do we run in the backend?
34:52 So we wanted to have a complex, multi-agent booking system,
34:55 and we chose to use the Google build ADK, or Agent Development Kit,
35:00 which is a flexible and open-source
35:02 framework for developing and deploying AI agents.
35:06 Now, for Android developers like you and I,
35:08 it might be a little bit scary to look at backend systems,
35:12 and it might be a little bit intimidating.
35:14 But just to give you an idea,
35:15 let's actually look at the implementation of the backend that we wrote.
35:20 So we can define an agent by setting their name, giving them the model that they
35:25 should communicate with, giving them an instruction,
35:28 and then giving them a set of tools.
35:31 That's all we need to set up one simple agent using ADK.
35:35 Then we can make a top-level orchestrator
35:38 that can delegate work to several subagents.
35:41 So here, for the restaurants, for the hotels and for the museums,
35:44 I'm making a bunch of different subagents.
35:47 So when we have such a backend set up, there's one question that remains.
35:51 It's running in the clouds.
35:53 We have an Android app.
35:54 How do we communicate?
35:55 What kind of messaging protocol do we use?
35:58 Now, we could be making our own.
36:00 We could set up our own kind of communication pattern,
36:03 decide what are the requests that we're sending, what are the responses?
36:07 However, once you start adding more complexities to such a backend system,
36:11 it can become quite unwieldy and difficult to deal with.
36:16 So instead, we can use the AG-UI protocol.
36:19 This standardizes communication between agents and UI clients.
36:23 So the protocol predefines a set of message types
36:27 that have been designed to best represent agent-to-client interactions.
36:32 So the agent can inform the client about, for example,
36:35 its lifecycle events, text messages, tool calls, state management, et cetera.
36:39 And the other way around,
36:41 we can have our Android app that is sending text messages,
36:44 providing tool call results, and sending custom events.
36:49 Now, most agent frameworks have an AG-UI adapter module.
36:54 So that allows them to interact using that AG-UI protocol.
36:57 And similarly, there's also several AG-UI libraries for clients.
37:01 So for example, for Android, there's a Kotlin SDK that gives you a great
37:05 Kotlin API to communicate with any AG-UI-enabled backends.
37:10 So as an Android developer, at that point,
37:13 all that you need to do is set up the connection to your backend and then
37:18 decide how you want to visualize those AG-UI
37:21 messages that are coming in from your server.
37:24 So in our use case, we're parsing the messages that are
37:26 coming in and we're showing them in our nice UI.
37:31 This is already quite great, but I believe we can do better.
37:36 So if we're deciding— so the step two that we just mentioned,
37:40 deciding how to visualize the events coming in, that is actually quite
37:44 a lot of work and quite a lot of kind of figuring out, right?
37:49 It doesn't really scale that well
37:51 and there's some version dependency complexities.
37:53 Like, what if my backend is updated
37:55 but my Android app is still older, et cetera?
37:58 So what if, instead,
38:00 we could have our app describe a set of UI components that it is able to render,
38:05 and then let our AI model speak UI instead?
38:10 So what do I mean with that?
38:12 So A2UI is a protocol that allows agents to render UI in a client.
38:17 It works really well together with AG-UI as a transfer protocol,
38:21 but the client simply informs the agent which components it can render,
38:25 and then the agent that's running on the server decides,
38:28 what is the best UI component that I can use, the best tree, the best hierarchy,
38:33 to then do what I want to do,
38:35 or ask the user for input, or to reach my goal, basically?
38:40 And as an Android developer, that means that the only thing that we still
38:43 have to do is define our set of components,
38:46 which might be composables that you already have in your app,
38:49 provide them to your server, and then render them.
38:54 So let's have a look of an example of what that communication looks like.
38:58 You can see the component tree being passed from the server
39:01 to the client to be rendered at a given point in time.
39:04 And you can see that A2UI supports both basic components,
39:07 like we have column and text here, but it also supports custom components.
39:12 So for example, here, I added support for a my progress spinner.
39:16 You can also see that we're not actually passing actual data at this point.
39:21 Instead, the server is just passing variable names.
39:24 And then in a separate message, after it's sent the components,
39:28 it can actually gives you data associated with those variables.
39:32 So all of this is pretty cool.
39:33 But at this point, we're just passing JSON, right?
39:36 It's just JSON coming in, JSON going out.
39:38 What does that actually mean?
39:40 That's not UI on a screen yet.
39:43 So how are we going to render that, specifically on Android?
39:46 So on Android, we are currently building a Jetpack Compose Renderer.
39:52 It will allow you to automatically render those A2UI
39:55 messages that are coming in from your server.
39:59 [APPLAUSE] This A2UI renderer has a set of basic components
40:05 that will give you great out of the box experiences,
40:08 so you don't have to do anything special here.
40:11 And when needed, you will also be able to provide
40:13 your own custom components based on the composables in your app.
40:18 So that's what we did in the app
40:19 to constrain our model to generate our custom booking-related components.
40:24 So now we can build beautiful UI
40:26 and let the agent show specific components when,
40:28 for example, we're choosing a seat.
40:32 Now, in our code, we create an A2UI
40:34 message processor and pass our custom catalog to it.
40:37 From that processor, we then retrieve active surfaces.
40:41 And in our UI, we simply retrieve the surfaces that are coming
40:44 in and display them in a column using the material A2UI surface composable.
40:51 So to summarize, we have A2UI on the one hand,
40:53 which is our transport layer communication protocol,
40:56 and it provides an event-based
40:58 communication pipeline between agents and clients.
41:02 And A2UI is our independent protocol that helps an agent speak UI,
41:06 which can then be rendered into native components on the client side.
41:11 Now, A2UI is just message passing and it works over any transport.
41:14 So it could also use REST, MCP, A2A, or AG-UI.
41:19 Now, we're at the start of these protocols, so please,
41:21 please do give a look at a2ui.org to learn more and stay posted.
41:29 OK, let's get to our final, final feature.
41:32 So we already saw how we can connect to an agent running in the cloud.
41:35 What if we want to instead run an agentic system on our device?
41:40 Now, this is very, very, very early and experimental,
41:43 but I did want to give you a heads-up of what we're
41:46 thinking about and what we're developing
41:47 and what we're moving towards as Android.
41:51 So let's see if we can build an agentic system
41:53 that hosts multiple agents that all communicate with each other,
41:57 orchestrated from within our Android app.
41:59 Let's switch to our app and quickly show it in action.
42:04 Hoping that the Wi-Fi is fixed by this point.
42:07 So I'll turn the feature on.
42:09 This is called the Genius Assistant.
42:10 And our Genius Assistant is going to help
42:12 us during our trip to understand what's going on.
42:16 Now, it will first go to our cloud,
42:18 and it will go and try to understand what's going on in the trip.
42:22 So it parses the itinerary,
42:23 and then it understands that I have a hotel and a car reservation.
42:27 So let me check my hotel reservation.
42:30 What it will do is it will
42:32 actually understand that there is multiple agents running,
42:35 and it can understand that it can transfer to our hotel agent.
42:40 Now, our hotel agent is a subagent that runs on-device,
42:43 because I have my personal data running on my device as well.
42:47 So I have some personal information here.
42:50 I have my passport and I have the hotel reservation.
42:53 And the model will actually compare the two.
42:55 So here, there's multiple agents running.
42:57 And I'll show you later how this is set up.
43:00 But this is pretty cool.
43:01 And we have a way to understand that for my hotel reservation,
43:04 actually, I provided the wrong passport number.
43:08 So there's a lot going on here.
43:09 And I'll show you how that actually works.
43:12 So let's go back to the slides and dive into it.
43:17 So one way of doing this on Android is using ADK for Androids.
43:24 [APPLAUSE] This is a brand-new library.
43:28 We just released version 0.1 this week.
43:32 And it takes all the learnings that we had from ADK on the cloud,
43:35 which we've seen in our previous section, and it applies them to Androids.
43:40 ADK manages all the complex orchestration,
43:42 context handling, and error handling for you.
43:45 It allows you to build an agent with just a few lines of code,
43:50 easily swap out models, et cetera.
43:53 Now, for our trip assistant feature,
43:55 we first designed a main orchestrator that uses Cloud Intelligence.
43:59 It then calls tools to get information about the trip,
44:02 chooses to offload work to a subagent that we run fully on-device,
44:06 and then each of the subagents runs a set
44:10 of agents in a sequence and shares the data between them.
44:14 So we only ever return the final results
44:16 to the orchestrator that are stripped of any privacy-sensitive data.
44:20 So in our code, what this looks like is we have our trip assistant orchestrator,
44:24 which uses a cloud model for its intelligence and has a set of subagents.
44:31 And we give it a tool, as we saw before,
44:34 and we give it some top-level instructions so
44:36 it knows when to offload to which agent.
44:39 Then each subagent is defined as an on-device sequential agent,
44:45 and we have various retrieval agents that can use the device
44:48 Nano model to retrieve the correct data from our user's document.
44:53 Separately, we have that last validation agent that we saw
44:56 that can compare the data coming in from those retrieval agents.
44:59 And together, we have a whole set of agents
45:01 set up with just a few lines of code, using both on-device and cloud,
45:07 working to build something that is highly intelligent for your user.
45:12 Now, as I said, ADK for Android is just starting,
45:15 and we're looking forward to see what you build with it.
45:17 Check out adk.dev for more.
45:21 Now, with that, we completed all seven features
45:23 and we made our app so much more useful.
45:26 So while we're working on making
45:28 the Jetpacker source code available to you soon,
45:30 in the meantime, please go to developer.android.com/ai to learn more.
45:36 And with that, thank you for joining, and have a great I/O.
45:38 [APPLAUSE] [MUSIC PLAYING]