Sessões
Sessões em adk-rust fornecem gerenciamento de contexto de conversação, permitindo que os Agents mantenham o estado em várias interações. As Sessões armazenam o histórico de conversação (eventos) e dados de estado arbitrários que persistem ao longo de uma conversação.
Visão Geral
Uma Session representa uma única conversação entre um usuário e um Agent. Cada Session:
- Possui um identificador único
- Pertence a uma aplicação (
app_name) e usuário (user_id) - Contém uma lista de eventos (histórico de conversação)
- Mantém dados de estado (pares chave-valor)
- Rastreia o horário da última atualização
Trait Session
O trait Session define a interface para objetos Session:
use adk_session::{Events, State};
use chrono::{DateTime, Utc};
pub trait Session: Send + Sync {
/// Unique session identifier
fn id(&self) -> &str;
/// Application name this session belongs to
fn app_name(&self) -> &str;
/// User identifier
fn user_id(&self) -> &str;
/// Access session state
fn state(&self) -> &dyn State;
/// Access conversation events
fn events(&self) -> &dyn Events;
/// Last time the session was updated
fn last_update_time(&self) -> DateTime<Utc>;
}
Trait SessionService
O trait SessionService define operações para gerenciar Sessions:
use adk_session::{CreateRequest, GetRequest, ListRequest, DeleteRequest, Event, Session};
use adk_core::Result;
use async_trait::async_trait;
#[async_trait]
pub trait SessionService: Send + Sync {
/// Create a new session
async fn create(&self, req: CreateRequest) -> Result<Box<dyn Session>>;
/// Retrieve an existing session
async fn get(&self, req: GetRequest) -> Result<Box<dyn Session>>;
/// List all sessions for an app/user
async fn list(&self, req: ListRequest) -> Result<Vec<Box<dyn Session>>>;
/// Delete a session
async fn delete(&self, req: DeleteRequest) -> Result<()>;
/// Append an event to a session
async fn append_event(&self, session_id: &str, event: Event) -> Result<()>;
}
Tipos de Requisição
CreateRequest
use adk_session::CreateRequest;
use std::collections::HashMap;
let request = CreateRequest {
app_name: "my_app".to_string(),
user_id: "user_123".to_string(),
session_id: None, // Auto-generate UUID if None
state: HashMap::new(), // Initial state
};
GetRequest
use adk_session::GetRequest;
let request = GetRequest {
app_name: "my_app".to_string(),
user_id: "user_123".to_string(),
session_id: "session_abc".to_string(),
num_recent_events: Some(10), // Limit events returned
after: None, // Filter events after timestamp
};
ListRequest
use adk_session::ListRequest;
let request = ListRequest {
app_name: "my_app".to_string(),
user_id: "user_123".to_string(),
};
DeleteRequest
use adk_session::DeleteRequest;
let request = DeleteRequest {
app_name: "my_app".to_string(),
user_id: "user_123".to_string(),
session_id: "session_abc".to_string(),
};
Implementações do SessionService
ADK-Rust oferece duas implementações do SessionService:
InMemorySessionService
Armazena sessões na memória. Ideal para desenvolvimento, testes e implantações de instância única.
use adk_session::{InMemorySessionService, SessionService, CreateRequest};
use std::collections::HashMap;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Cria o serviço
let session_service = InMemorySessionService::new();
// Cria uma sessão
let session = session_service.create(CreateRequest {
app_name: "my_app".to_string(),
user_id: "user_123".to_string(),
session_id: None,
state: HashMap::new(),
}).await?;
println!("Session ID: {}", session.id());
println!("App: {}", session.app_name());
println!("User: {}", session.user_id());
Ok(())
}
DatabaseSessionService
Armazena sessões em um banco de dados SQLite. Adequado para implantações de produção que exigem persistência.
use adk_session::{DatabaseSessionService, SessionService, CreateRequest};
use std::collections::HashMap;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Conecta-se ao banco de dados
let session_service = DatabaseSessionService::new("sqlite:sessions.db").await?;
// Executa migrações para criar tabelas
session_service.migrate().await?;
// Cria uma sessão
let session = session_service.create(CreateRequest {
app_name: "my_app".to_string(),
user_id: "user_123".to_string(),
session_id: None,
state: HashMap::new(),
}).await?;
println!("Session persistida: {}", session.id());
Ok(())
}
Nota: O
DatabaseSessionServicerequer a feature flagdatabase:adk-session = { version = "0.2", features = ["database"] }
Ciclo de Vida da Sessão
1. Criação
Sessões são criadas com um CreateRequest. Se nenhum session_id for fornecido, um UUID é gerado automaticamente.
use adk_session::{InMemorySessionService, SessionService, CreateRequest};
use std::collections::HashMap;
let service = InMemorySessionService::new();
// Cria com ID auto-gerado
let session = service.create(CreateRequest {
app_name: "my_app".to_string(),
user_id: "user_123".to_string(),
session_id: None,
state: HashMap::new(),
}).await?;
// Cria com ID específico
let session = service.create(CreateRequest {
app_name: "my_app".to_string(),
user_id: "user_123".to_string(),
session_id: Some("my-custom-id".to_string()),
state: HashMap::new(),
}).await?;
2. Recuperação
Recupere uma sessão pelos seus identificadores:
use adk_session::GetRequest;
let session = service.get(GetRequest {
app_name: "my_app".to_string(),
user_id: "user_123".to_string(),
session_id: "session_abc".to_string(),
num_recent_events: None,
after: None,
}).await?;
println!("Sessão recuperada: {}", session.id());
println!("Eventos: {}", session.events().len());
3. Anexando Eventos
Eventos são anexados às sessões conforme a conversa progride. Isso é tipicamente gerenciado pelo Runner, mas pode ser feito manualmente:
use adk_session::Event;
let event = Event::new("invocation_123");
service.append_event(session.id(), event).await?;
4. Listagem
Liste todas as sessões para um usuário:
use adk_session::ListRequest;
let sessions = service.list(ListRequest {
app_name: "my_app".to_string(),
user_id: "user_123".to_string(),
}).await?;
for session in sessions {
println!("Sessão: {} (atualizada: {})",
session.id(),
session.last_update_time()
);
}
5. Exclusão
Exclua uma sessão quando ela não for mais necessária:
use adk_session::DeleteRequest;
service.delete(DeleteRequest {
app_name: "my_app".to_string(),
user_id: "user_123".to_string(),
session_id: "session_abc".to_string(),
}).await?;
Usando Sessions com Runner
Sessions são tipicamente gerenciadas pelo Runner ao executar agents. O Runner:
- Cria ou recupera uma session
- Passa o contexto da session para o agent
- Anexa eventos conforme a conversa progride
- Atualiza o estado da session com base nas ações do agent
use adk_rust::prelude::*;
use adk_runner::{Runner, RunnerConfig};
use adk_session::InMemorySessionService;
use std::sync::Arc;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenvy::dotenv().ok();
let api_key = std::env::var("GOOGLE_API_KEY")?;
let model = Arc::new(GeminiModel::new(&api_key, "gemini-2.0-flash")?);
let agent = LlmAgentBuilder::new("assistant")
.model(model)
.instruction("You are a helpful assistant.")
.build()?;
let session_service = Arc::new(InMemorySessionService::new());
// Create runner with session service
let runner = Runner::new(RunnerConfig {
app_name: "my_app".to_string(),
agent: Arc::new(agent),
session_service,
artifact_service: None,
memory_service: None,
run_config: None,
})?;
// Run with user and session IDs
let user_content = Content::new("user").with_text("Hello!");
let stream = runner.run(
"user_123".to_string(),
"session_abc".to_string(),
user_content,
).await?;
Ok(())
}
Events
A trait Events fornece acesso ao histórico da conversa:
pub trait Events: Send + Sync {
/// Get all events
fn all(&self) -> Vec<Event>;
/// Get number of events
fn len(&self) -> usize;
/// Get event at index
fn at(&self, index: usize) -> Option<&Event>;
/// Check if empty
fn is_empty(&self) -> bool;
}
Acesse events de uma session:
let events = session.events();
println!("Total events: {}", events.len());
for event in events.all() {
println!("Event {} by {} at {}",
event.id,
event.author,
event.timestamp
);
}
Exemplo Completo
use adk_session::{
InMemorySessionService, SessionService,
CreateRequest, GetRequest, ListRequest, DeleteRequest,
Event, KEY_PREFIX_USER,
};
use serde_json::json;
use std::collections::HashMap;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let service = InMemorySessionService::new();
// Create session with initial state
let mut initial_state = HashMap::new();
initial_state.insert(format!("{}name", KEY_PREFIX_USER), json!("Alice"));
initial_state.insert("topic".to_string(), json!("Getting started"));
let session = service.create(CreateRequest {
app_name: "demo".to_string(),
user_id: "alice".to_string(),
session_id: None,
state: initial_state,
}).await?;
println!("Created session: {}", session.id());
// Check state
let state = session.state();
println!("User name: {:?}", state.get("user:name"));
println!("Topic: {:?}", state.get("topic"));
// Append an event
let event = Event::new("inv_001");
service.append_event(session.id(), event).await?;
// Retrieve session with events
let session = service.get(GetRequest {
app_name: "demo".to_string(),
user_id: "alice".to_string(),
session_id: session.id().to_string(),
num_recent_events: None,
after: None,
}).await?;
println!("Events: {}", session.events().len());
// List all sessions
let sessions = service.list(ListRequest {
app_name: "demo".to_string(),
user_id: "alice".to_string(),
}).await?;
println!("Total sessions: {}", sessions.len());
// Delete session
service.delete(DeleteRequest {
app_name: "demo".to_string(),
user_id: "alice".to_string(),
session_id: session.id().to_string(),
}).await?;
println!("Session deleted");
Ok(())
}
Relacionado
- Gerenciamento de Estado - Gerenciando o estado da sessão com prefixos
- Eventos - Estrutura e ações de eventos
- Runner - Execução de Agent com sessões
Anterior: ← Ferramentas MCP | Próximo: Gerenciamento de Estado →