세션
adk-rust의 세션은 대화 컨텍스트 관리를 제공하여 Agent가 여러 상호작용에 걸쳐 상태를 유지할 수 있도록 합니다. 세션은 대화 기록(이벤트)과 대화 전체에 걸쳐 지속되는 임의의 상태 데이터를 저장합니다.
개요
세션은 사용자 및 Agent 간의 단일 대화를 나타냅니다. 각 세션은 다음을 가집니다:
- 고유 식별자를 가집니다.
- 애플리케이션 (
app_name) 및 사용자 (user_id)에 속합니다. - 이벤트 목록 (대화 기록)을 포함합니다.
- 상태 데이터 (키-값 쌍)를 유지합니다.
- 마지막 업데이트 시간을 추적합니다.
Session 트레이트
Session 트레이트는 세션 객체의 인터페이스를 정의합니다:
use adk_session::{Events, State};
use chrono::{DateTime, Utc};
pub trait Session: Send + Sync {
/// 고유 세션 식별자
fn id(&self) -> &str;
/// 이 세션이 속한 애플리케이션 이름
fn app_name(&self) -> &str;
/// 사용자 식별자
fn user_id(&self) -> &str;
/// 세션 상태에 접근
fn state(&self) -> &dyn State;
/// 대화 이벤트에 접근
fn events(&self) -> &dyn Events;
/// 세션이 마지막으로 업데이트된 시간
fn last_update_time(&self) -> DateTime<Utc>;
}
SessionService 트레이트
SessionService 트레이트는 세션 관리를 위한 작업을 정의합니다:
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 {
/// 새 세션 생성
async fn create(&self, req: CreateRequest) -> Result<Box<dyn Session>>;
/// 기존 세션 검색
async fn get(&self, req: GetRequest) -> Result<Box<dyn Session>>;
/// 앱/사용자의 모든 세션 목록
async fn list(&self, req: ListRequest) -> Result<Vec<Box<dyn Session>>>;
/// 세션 삭제
async fn delete(&self, req: DeleteRequest) -> Result<()>;
/// 세션에 이벤트 추가
async fn append_event(&self, session_id: &str, event: Event) -> Result<()>;
}
요청 유형
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, // None인 경우 UUID 자동 생성
state: HashMap::new(), // 초기 상태
};
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), // 반환되는 이벤트 제한
after: None, // 타임스탬프 이후의 이벤트 필터링
};
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(),
};
SessionService 구현
adk-rust는 두 가지 SessionService 구현을 제공합니다:
InMemorySessionService
세션을 메모리에 저장합니다. 개발, 테스트 및 단일 인스턴스 배포에 적합합니다.
use adk_session::{InMemorySessionService, SessionService, CreateRequest};
use std::collections::HashMap;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Create the service
let session_service = InMemorySessionService::new();
// Create a session
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
세션을 SQLite 데이터베이스에 저장합니다. 영속성이 필요한 프로덕션 배포에 적합합니다.
use adk_session::{DatabaseSessionService, SessionService, CreateRequest};
use std::collections::HashMap;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Connect to database
let session_service = DatabaseSessionService::new("sqlite:sessions.db").await?;
// Run migrations to create tables
session_service.migrate().await?;
// Create a session
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 persisted: {}", session.id());
Ok(())
}
참고:
DatabaseSessionService는database기능 플래그를 필요로 합니다:adk-session = { version = "0.2", features = ["database"] }
Session 수명 주기
1. 생성
Session은 CreateRequest로 생성됩니다. session_id가 제공되지 않으면 UUID가 자동으로 생성됩니다.
use adk_session::{InMemorySessionService, SessionService, CreateRequest};
use std::collections::HashMap;
let service = InMemorySessionService::new();
// Create with auto-generated ID
let session = service.create(CreateRequest {
app_name: "my_app".to_string(),
user_id: "user_123".to_string(),
session_id: None,
state: HashMap::new(),
}).await?;
// Create with specific ID
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. 조회
Session을 식별자로 조회합니다:
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!("Retrieved session: {}", session.id());
println!("Events: {}", session.events().len());
3. 이벤트 추가
대화가 진행됨에 따라 이벤트가 Session에 추가됩니다. 이는 일반적으로 Runner에 의해 처리되지만, 수동으로 수행할 수도 있습니다:
use adk_session::Event;
let event = Event::new("invocation_123");
service.append_event(session.id(), event).await?;
4. 목록
사용자의 모든 Session 목록을 가져옵니다:
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!("Session: {} (updated: {})",
session.id(),
session.last_update_time()
);
}
5. 삭제
더 이상 필요 없는 Session을 삭제합니다:
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?;
Runner와 함께 Session 사용하기
Session은 일반적으로 Agent를 실행할 때 Runner에 의해 관리됩니다. Runner는 다음을 수행합니다.
- Session을 생성하거나 검색합니다.
- Session 컨텍스트를 Agent에 전달합니다.
- 대화가 진행됨에 따라 이벤트를 추가합니다.
- Agent 작업에 따라 Session 상태를 업데이트합니다.
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
Events trait은 대화 기록에 대한 접근을 제공합니다:
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;
}
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
);
}
전체 예시
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(())
}
관련
- State Management - 접두사를 사용하여 Session 상태 관리
- Events - 이벤트 구조 및 액션
- Runner - Agent와 Session을 사용한 실행
이전: ← MCP Tools | 다음: State Management →