Gerenciar sessões e ciclo de vida

Os Agentic Workflows no dispositivo (usando a classe AgentRunner) oferecem sessões gerenciadas multiturno que registram automaticamente o histórico de conversas na memória em todos os turnos, para que você não precise gerenciar as transcrições manualmente. Se preferir gerenciar seu próprio histórico de chat diretamente, transmita um objeto List<Content> multiturno com os papéis USER e MODEL e um valor sessionId para um objeto GenerateContentRequest usando o acesso direto ao modelo.

Esta página aborda o gerenciamento de instâncias de AgentSession em ciclos de vida de componentes do Android, mudanças de configuração e recuperação de memória.

Sessões com várias interações

Gerencie conversas com vários turnos usando instâncias AgentSession com escopo obtidas com o método runner.getOrCreateSession(sessionId). As interações de diálogo (mensagens do usuário, invocações de ferramentas e respostas do modelo) são registradas na memória automaticamente dentro da sessão. As chamadas subsequentes para o método session.runAsync(content) preservam as interações anteriores como contexto.

Os identificadores de sessão não podem estar em branco, precisam ter no máximo 128 caracteres e conter apenas caracteres alfanuméricos, sublinhados, hifens ou pontos (^[a-zA-Z0-9_.-]+$, exceto . e ..). As strings de UUID geradas usando o método UUID.randomUUID().toString() estão em conformidade com essas restrições.

Para iniciar uma conversa multiturno, crie um identificador de sessão e receba uma instância AgentSession da sua instância AgentRunner:

val sessionId = "user_chat_${System.currentTimeMillis()}"
val session = runner.getOrCreateSession(sessionId)

Cada chamada para o método session.runAsync(content) envia um novo turno de comando dentro dessa sessão. O modelo mantém o contexto das interações anteriores na conversa.

Preservar sessões em mudanças de configuração

A interface AgentSession mantém o histórico de diálogos na memória e não implementa a interface Parcelable. Em apps Android, as atividades e os fragmentos são destruídos e recriados durante mudanças de configuração, como a rotação de tela. Se você armazenar a sessão diretamente em uma atividade, o histórico de conversas será perdido após a rotação.

Para preservar o histórico de conversas durante mudanças de configuração, retenha a instância AgentSession em uma classe ViewModel do AndroidX:

package com.example.ai.agent.ui

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.mlkit.genai.agent.AgentRunner
import com.google.mlkit.genai.agent.AgentSession
import com.google.mlkit.genai.agent.textTokens
import com.google.mlkit.genai.prompt.Content
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

class ChatViewModel(
    private val runner: AgentRunner,
    private val sessionId: String = "default_chat_session"
) : ViewModel() {

    // Retain the session inside the ViewModel to survive screen rotations
    private val session: AgentSession = runner.getOrCreateSession(sessionId)

    private val _responseText = MutableStateFlow("")
    val responseText: StateFlow<String> = _responseText.asStateFlow()

    fun sendMessage(userPrompt: String) {
        viewModelScope.launch {
            val content = Content.builder().text(userPrompt).build()
            session.runAsync(content)
                .textTokens()
                .collect { token ->
                    _responseText.update { it + token }
                }
        }
    }

    override fun onCleared() {
        super.onCleared()
        // Release session memory and cancel active coroutines when ViewModel is destroyed
        session.close()
    }
}

Gerenciamento de memória e limpeza de sessão

Mantenha o estado da conversa na memória limitado para manter o desempenho do app:

  • Exclusão explícita de sessão: quando um usuário sai de uma conversa ou toca em "Nova conversa", chame o método session.delete() ou runner.deleteSession(sessionId) para liberar de forma síncrona a alocação de memória para turnos anteriores e saídas de ferramentas. Como alternativa, chamar o método session.close() envia a remoção em segundo plano.
  • Limpeza de saída: chame o método runner.clearAllSessions() quando o usuário sair ou limpar os dados do app.
  • Limpeza da sessão no fim do ciclo de vida: chame o método session.close() quando a classe ViewModel ou o componente pai for destruído permanentemente (no método onCleared()). Isso cancela as corrotinas pendentes em andamento e envia a remoção em segundo plano para essa sessão de conversa.

Execução efêmera de uma única interação

Para tarefas únicas do agente (como gerar um resumo rápido, validar uma entrada ou responder a uma pergunta independente) em que o contexto anterior não é necessário, chame o método runner.runSingleTurnAsync(content) diretamente:

import com.google.mlkit.genai.agent.AgentEvent
import com.google.mlkit.genai.prompt.Content

val content = Content.builder()
    .text("Summarize order history for customer #1042: ...")
    .build()

runner.runSingleTurnAsync(content)
    .collect { event ->
        if (event is AgentEvent.TextMessage && !event.isPartial) {
            displaySummary(event.text)
        }
    }

Ao invocar o método runner.runSingleTurnAsync(content) diretamente, a classe AgentRunner aloca uma sessão temporária internamente e limpa automaticamente todo o estado da conversa da memória assim que o fluxo de resposta é concluído ou cancelado, evitando vazamentos de memória.

Próximas etapas