Runner

adk-runner からの実行ランタイムで、Agent の実行を調整します。

概要

Runner は Agent 実行のライフサイクル全体を管理します。

  • セッション管理(セッションの作成/取得)
  • メモリの注入(関連するメモリの検索と注入)
  • アーティファクトの処理(スコープ付きアーティファクトアクセス)
  • イベントストリーミング(イベントの処理と転送)
  • Agent の転送(マルチ Agent ハンドオフの処理)

インストール

[dependencies]
adk-runner = "0.2.0"

RunnerConfig

必要なサービスで Runner を構成します。

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)?;

構成フィールド

フィールド必須説明
app_nameStringYesアプリケーション識別子
agentArc<dyn Agent>Yes実行するルート Agent
session_serviceArc<dyn SessionService>Yesセッションストレージバックエンド
artifact_serviceOption<Arc<dyn ArtifactService>>Noアーティファクトストレージ
memory_serviceOption<Arc<dyn Memory>>No長期記憶
run_configOption<RunConfig>No実行オプション

Agent の実行

ユーザー入力で Agent を実行します。

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),
    }
}

実行フロー

┌─────────────────────────────────────────────────────────────┐
│                     Runner.run()                            │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                  1. セッションの取得                        │
│                                                             │
│   SessionService.get(app_name, user_id, session_id)        │
│   → 存在しない場合は新しいセッションを作成します            │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                  2. Agentの選択                             │
│                                                             │
│   アクティブなAgentについてセッションの状態を確認します     │
│   → ルートAgentまたは転送されたAgentを使用します            │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                3. コンテキストの作成                        │
│                                                             │
│   InvocationContext (以下を含む):                           │
│   - Session (可変)                                          │
│   - Artifacts (セッションにスコープ指定)                    │
│   - Memory (構成されている場合)                             │
│   - Run config                                              │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                  4. Agentの実行                             │
│                                                             │
│   agent.run(ctx) → EventStream                             │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                 5. イベント処理                             │
│                                                             │
│   各イベントについて:                                       │
│   - セッションの状態を更新します                            │
│   - 転送を処理します                                        │
│   - 呼び出し元に転送します                                  │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                  6. セッションの保存                        │
│                                                             │
│   SessionService.append_event(session, events)             │
└─────────────────────────────────────────────────────────────┘

InvocationContext

実行中にAgentに提供されるコンテキスト:

pub trait InvocationContext: CallbackContext {
    /// 実行中のAgent
    fn agent(&self) -> Arc<dyn Agent>;
    
    /// メモリサービス(設定されている場合)
    fn memory(&self) -> Option<Arc<dyn Memory>>;
    
    /// 現在のSession
    fn session(&self) -> &dyn Session;
    
    /// 実行設定
    fn run_config(&self) -> &RunConfig;
    
    /// 呼び出しの終了を通知
    fn end_invocation(&self);
    
    /// 呼び出しが終了したかを確認
    fn ended(&self) -> bool;
}

RunConfig

実行オプション:

pub struct RunConfig {
    /// レスポンスのストリーミングモード
    pub streaming_mode: StreamingMode,
}

pub enum StreamingMode {
    /// ストリーミングなし、完全なレスポンスを返す
    None,
    /// Server-Sent Events(デフォルト)
    SSE,
    /// 双方向ストリーミング(リアルタイム)
    Bidi,
}

: max_turnsinclude_historyなどの追加フィールドは、将来のリリースで計画されています。

Agentの転送

RunnerはマルチAgent転送を自動的に処理します:

// AgentのToolまたはコールバック内
if should_transfer {
    // イベントアクションで転送を設定
    ctx.set_actions(EventActions {
        transfer_to_agent: Some("specialist_agent".to_string()),
        ..Default::default()
    });
}

Runnerは以下を行います:

  1. イベント内の転送リクエストを検出する
  2. sub_agentsからターゲットAgentを見つける
  3. 新しいアクティブなAgentでSessionの状態を更新する
  4. 新しいAgentで実行を継続する

Launcherとの統合

Launcherは内部的にRunnerを使用します:

// LauncherはデフォルトのサービスでRunnerを作成します
Launcher::new(agent)
    .app_name("my_app")
    .run()
    .await?;

// 以下と同等:
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,
})?;

カスタムRunnerの使用

高度なシナリオでは、Runnerを直接使用します:

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

// 本番環境の設定
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,  // デフォルトのSSEストリーミングを使用
};

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

// HTTPハンドラーでの使用
async fn chat_handler(runner: &Runner, request: ChatRequest) -> Response {
    let stream = runner.run(
        request.user_id,
        request.session_id,
        request.content,
    ).await?;
    
    // クライアントにイベントをストリーミング
    Response::sse(stream)
}

前へ: ← コアタイプ | 次へ: Launcher →