Runner

O tempo de execução de adk-runner que orquestra a execução do Agent.

Visão Geral

O Runner gerencia o ciclo de vida completo da execução do Agent:

  • Gerenciamento de Session (criar/recuperar Sessions)
  • Injeção de memória (pesquisar e injetar memórias relevantes)
  • Manipulação de artefatos (acesso a artefatos com escopo)
  • Streaming de eventos (processar e encaminhar eventos)
  • Transferências de Agent (lidar com repasses multi-Agent)

Instalação

[dependencies]
adk-runner = "0.2.0"

RunnerConfig

Configure o Runner com os serviços necessários:

use adk_runner::{Runner, RunnerConfig};
use adk_session::InMemorySessionService;
use adk_artifact::InMemoryArtifactService;
use std::sync::Arc;

let config = RunnerConfig {
    app_name: "my_app".to_string(),
    agent: Arc::new(my_agent),
    session_service: Arc::new(InMemorySessionService::new()),
    artifact_service: Some(Arc::new(InMemoryArtifactService::new())),
    memory_service: None,
    run_config: None,
};

let runner = Runner::new(config)?;

Campos de Configuração

CampoTipoObrigatórioDescrição
app_nameStringSimIdentificador da aplicação
agentArc<dyn Agent>SimAgent raiz a ser executado
session_serviceArc<dyn SessionService>SimBackend de armazenamento de Session
artifact_serviceOption<Arc<dyn ArtifactService>>NãoArmazenamento de artefatos
memory_serviceOption<Arc<dyn Memory>>NãoMemória de longo prazo
run_configOption<RunConfig>NãoOpções de execução

Executando Agents

Execute um Agent com entrada do usuário:

use adk_core::Content;
use futures::StreamExt;

let user_content = Content::new("user").with_text("Hello!");

let mut stream = runner.run(
    "user-123".to_string(),
    "session-456".to_string(),
    user_content,
).await?;

while let Some(event) = stream.next().await {
    match event {
        Ok(e) => {
            if let Some(content) = e.content() {
                for part in &content.parts {
                    if let Some(text) = part.text() {
                        print!("{}", text);
                    }
                }
            }
        }
        Err(e) => eprintln!("Error: {}", e),
    }
}

Fluxo de Execução

┌─────────────────────────────────────────────────────────────┐
│                     Runner.run()                            │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                  1. Recuperação da Sessão                   │
│                                                             │
│   SessionService.get(app_name, user_id, session_id)        │
│   → Cria nova sessão se não existir                         │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                  2. Seleção do Agent                        │
│                                                             │
│   Verifica o estado da sessão para o Agent ativo            │
│   → Usa o Agent raiz ou o Agent transferido                 │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                3. Criação do Contexto                       │
│                                                             │
│   InvocationContext com:                                    │
│   - Session (mutável)                                       │
│   - Artefatos (com escopo na sessão)                       │
│   - Memória (se configurado)                                │
│   - Run config                                              │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                  4. Execução do Agent                       │
│                                                             │
│   agent.run(ctx) → EventStream                             │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                 5. Processamento de Eventos                 │
│                                                             │
│   Para cada evento:                                         │
│   - Atualiza o estado da sessão                             │
│   - Lida com as transferências                              │
│   - Encaminha para o chamador                               │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                  6. Salvamento da Sessão                    │
│                                                             │
│   SessionService.append_event(session, events)             │
└─────────────────────────────────────────────────────────────┘

Contexto de Invocação

O contexto fornecido aos agents durante a execução:

pub trait InvocationContext: CallbackContext {
    /// O agent sendo executado
    fn agent(&self) -> Arc<dyn Agent>;
    
    /// Serviço de memória (se configurado)
    fn memory(&self) -> Option<Arc<dyn Memory>>;
    
    /// Session atual
    fn session(&self) -> &dyn Session;
    
    /// Configuração de execução
    fn run_config(&self) -> &RunConfig;
    
    /// Sinaliza o fim da invocação
    fn end_invocation(&self);
    
    /// Verifica se a invocação terminou
    fn ended(&self) -> bool;
}

RunConfig

Opções de execução:

pub struct RunConfig {
    /// Modo de streaming para respostas
    pub streaming_mode: StreamingMode,
}

pub enum StreamingMode {
    /// Sem streaming, retorna a resposta completa
    None,
    /// Server-Sent Events (padrão)
    SSE,
    /// Streaming bidirecional (em tempo real)
    Bidi,
}

Nota: Campos adicionais como max_turns e include_history estão planejados para futuras versões.

Transferências de Agent

O Runner lida com transferências multi-agent automaticamente:

// Em uma tool ou callback de um agent
if should_transfer {
    // Define a transferência nas ações do evento
    ctx.set_actions(EventActions {
        transfer_to_agent: Some("specialist_agent".to_string()),
        ..Default::default()
    });
}

O Runner irá:

  1. Detectar a solicitação de transferência no evento
  2. Encontrar o agent alvo em sub_agents
  3. Atualizar o estado da session com o novo agent ativo
  4. Continuar a execução com o novo agent

Integração com o Launcher

O Launcher usa o Runner internamente:

// O Launcher cria o Runner com serviços padrão
Launcher::new(agent)
    .app_name("my_app")
    .run()
    .await?;

// Equivalente a:
let runner = Runner::new(RunnerConfig {
    app_name: "my_app".to_string(),
    agent,
    session_service: Arc::new(InMemorySessionService::new()),
    artifact_service: Some(Arc::new(FileArtifactService::new("./artifacts")?)),
    memory_service: None,
    run_config: None,
})?;

Uso Customizado do Runner

Para cenários avançados, use o Runner diretamente:

use adk_runner::{Runner, RunnerConfig};
use adk_session::DatabaseSessionService;
use adk_artifact::S3ArtifactService;
use adk_memory::QdrantMemoryService;

// Configuração de produção
let config = RunnerConfig {
    app_name: "production_app".to_string(),
    agent: my_agent,
    session_service: Arc::new(DatabaseSessionService::new(db_pool)),
    artifact_service: Some(Arc::new(S3ArtifactService::new(s3_client))),
    memory_service: Some(Arc::new(QdrantMemoryService::new(qdrant_client))),
    run_config: None,  // Usa streaming SSE padrão
};

let runner = Runner::new(config)?;

// Usar em handler HTTP
async fn chat_handler(runner: &Runner, request: ChatRequest) -> Response {
    let stream = runner.run(
        request.user_id,
        request.session_id,
        request.content,
    ).await?;
    
    // Fazer streaming de eventos para o cliente
    Response::sse(stream)
}

Anterior: ← Core Types | Próximo: Launcher →