Gemini Interactions API(测试版)

ADK-Rust 为 Google 的 Interactions API 提供了专用客户端,这是 Google 为 Gemini API 探索的新方向。它以围绕类型化步骤时间线、服务器端历史记录和原生代理工作流构建的有状态 Interaction 资源,取代了 generateContent 请求/响应结构。

Interactions API 处于测试版。Google 建议在稳定的生产工作负载中使用 generateContent,并且可能会对 Interactions 架构进行不兼容更改。ADK-Rust 固定了 Api-Revision: 2026-05-20(步骤架构)契约。

概述

┌─────────────────────────────────────────────────────────────────────┐
│                  Gemini Interactions API Client                     │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│   Endpoint:  POST /v1beta/interactions                              │
│   Builder:   Gemini::create_interaction()                           │
│   Feature:   interactions (adk-gemini)                              │
│             gemini-interactions (adk-model / adk-rust)              │
│                                                                     │
│   Capabilities:                                                     │
│   • Single-turn and streaming (step.delta events)                   │
│   • Server-side history via previous_interaction_id                 │
│   • Typed step timeline (thought, function_call, model_output, …)   │
│   • Multimodal input (text, image, audio, document, video)          │
│   • Structured output (response_format JSON schema)                 │
│   • Client-side function calling + built-in server tools            │
│   • Background / long-running tasks (background = true)              │
│   • Lifecycle: get / delete / cancel a stored interaction           │
│                                                                     │
│   vs generateContent (GeminiModel):                                 │
│   • Stateful conversations (server stores history)                  │
│   • Observable execution steps for agentic UIs                      │
│   • New models & tools launch here first                            │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

何时使用哪个 API

方面generateContentGeminiModel交互 API(create_interaction
端点POST /v1beta/models/{model}:generateContentPOST /v1beta/interactions
稳定性稳定,推荐用于生产环境Beta,架构可能会更改
历史记录客户端重新发送完整记录服务端通过 previous_interaction_id
响应形态candidates + partssteps 时间线
智能体运行时(Llm trait)✅ 默认传输✅ 通过 use_interactions_api 启用
新模型 / 工具从这里优先发布

ADK agent 运行时(Llm trait、工具循环和 Runner)默认使用 generateContent。你也可以通过在 GeminiModel 上启用 use_interactions_api(true),使用同一运行时驱动 Interactions API——请参阅下文的将 Interactions 用作运行时传输。直接客户端(文档首先介绍)仍然可用,适用于希望使用服务器端历史记录、可观测步骤或仅限 beta 的模型,且不涉及 agent 的调用方。

启用

# Direct client (adk-gemini)
adk-gemini = { version = "2.1.0", features = ["interactions"] }

# Through the model facade / umbrella
adk-model = { version = "2.1.0", features = ["gemini-interactions"] }
adk-rust  = { version = "2.1.0", features = ["gemini-interactions"] }

此功能不会新增依赖项,并且完全兼容现有的 generateContent API。

快速开始

use adk_gemini::{Gemini, Model, ThinkingLevel};

let gemini = Gemini::new(std::env::var("GEMINI_API_KEY")?)?;

let interaction = gemini
    .create_interaction()
    .model(Model::Gemini35Flash)
    .system_instruction("You are concise.")
    .input_text("What is the capital of France?")
    .thinking_level(ThinkingLevel::Low)
    .send()
    .await?;

println!("{}", interaction.output_text().unwrap_or_default());

流式传输

进行流式传输时,API 会发出面向步骤的 SSE 事件模型。最常见的 方式是从 step.delta 事件中累积文本片段:

use futures::StreamExt;

let mut stream = gemini
    .create_interaction()
    .model(Model::Gemini35Flash)
    .input_text("Write a haiku about Rust.")
    .stream()
    .await?;

while let Some(event) = stream.next().await {
    if let Some(fragment) = event?.text_delta() {
        print!("{fragment}");
    }
}

事件类型包括:interaction.createdstep.startstep.deltastep.stopinteraction.status_updateinteraction.completederror。未知的 未来事件会反序列化为 InteractionSseEvent::Other,而不会导致 流失败。

服务器端多轮对话

传入之前交互的 id,即可在不重新发送 历史记录的情况下继续对话。请注意,toolssystem_instructiongeneration_config 都属于交互级别,必须在每一轮重新指定:

let first = gemini.create_interaction()
    .model(Model::Gemini35Flash)
    .input_text("My favorite color is teal.")
    .send().await?;

let second = gemini.create_interaction()
    .model(Model::Gemini35Flash)
    .previous_interaction_id(&first.id)
    .input_text("What is my favorite color?")
    .send().await?;

函数调用

Interactions API 将客户端工具调用作为带有 requires_action 状态的 function_call 步骤 提供。请在后续轮次中提交结果:

use serde_json::json;

let interaction = gemini.create_interaction()
    .model(Model::Gemini35Flash)
    .function("get_weather", "Get the weather",
        json!({"type": "object", "properties": {"location": {"type": "string"}}}))
    .input_text("Weather in Boston?")
    .send().await?;

if interaction.status.requires_action() {
    let follow_up = gemini.create_interaction()
        .model(Model::Gemini35Flash)
        .previous_interaction_id(&interaction.id);

    let mut follow_up = follow_up;
    for (call_id, name, _args) in interaction.pending_function_calls() {
        follow_up = follow_up.function_result(call_id, name, json!({"temperature": "72F"}));
    }
    let final_interaction = follow_up.send().await?;
    println!("{}", final_interaction.output_text().unwrap_or_default());
}

结构化输出

use serde_json::json;

let interaction = gemini.create_interaction()
    .model(Model::Gemini35Flash)
    .input_text("Summarize this article: ...")
    .json_schema(json!({
        "type": "object",
        "properties": { "summary": { "type": "string" } },
        "required": ["summary"]
    }))
    .send().await?;

生命周期

已存储的交互(服务器默认行为)可以被检索、删除或取消:

let fetched = gemini.get_interaction(&interaction.id, /* include_input */ true).await?;
gemini.cancel_interaction(&interaction.id).await?; // background tasks only
gemini.delete_interaction(&interaction.id).await?;

状态值

InteractionStatus 与 API 生命周期保持一致:InProgressRequiresActionCompletedFailedCancelledIncompleteBudgetExceeded。使用 is_terminal()requires_action() 进行控制流处理。

限制

Interactions API 尚不支持 Batch API 或显式缓存 (服务器端隐式缓存可通过 previous_interaction_id 使用)。ADK agent runtime 默认使用 generateContent;Interactions API 既可作为上文所述的独立客户端使用,也可作为选择加入的 runtime transport 使用(见下文)。


将 Interactions 作为 runtime transport(agents + runner)

上文介绍的是直接 wire clientadk_gemini::interactions) ——一种需要手动调用的独立功能。本节介绍构建于其之上的 runtime transportGeminiModel 上的一个开关,使普通的 LlmAgentRunner、tool loop 和 sessions 能够驱动 Interactions API, 而无需更改任何 agent 代码

这与 ADK-Python 的设计一致,其中 Gemini(model=..., use_interactions_api=True) 保留相同的 Agent、runner 和 tools。agent 与 transport 无关: 切换模型与后端通信的方式不应要求创建新的 agent 类型。

generateContent 仍是默认方式

generateContent 仍是稳定生产工作负载的默认且推荐 transport。Interactions API 处于 beta 阶段,其 schema 可能会发生变化。 请针对每个 model 有意选择启用 transport。如果不调用 use_interactions_api(true)GeminiModel 的行为将与之前完全一致—— generateContent 路径不会发生任何行为变化。

启用 transport

该 transport 由 gemini-interactions feature 控制(从 adk-rustadk-modeladk-gemini/interactions 传递):

adk-model = { version = "2.1.0", features = ["gemini-interactions"] }
adk-rust  = { version = "2.1.0", features = ["gemini-interactions"] }

在 model 上启用该开关,并将其包装在普通的 LlmAgentRunner 中—— agent 设置的其他部分无需更改:

use adk_agent::LlmAgentBuilder;
use adk_core::{Content, Part, SessionId, UserId};
use adk_model::GeminiModel;
use adk_runner::Runner;
use adk_session::{CreateRequest, InMemorySessionService, SessionService};
use futures::StreamExt;
use std::collections::HashMap;
use std::sync::Arc;

// 1. Build a Gemini model and toggle the Interactions transport.
//    `use_interactions_api` validates the model id against the allowlist and
//    returns `Result<Self>`, so it is fallible (`?`).
let model = GeminiModel::new(std::env::var("GEMINI_API_KEY")?, "gemini-3.7-flash")?
    .use_interactions_api(true)?;

// 2. Wrap it in a normal LlmAgent — unchanged agent API.
let agent = Arc::new(
    LlmAgentBuilder::new("assistant")
        .instruction("You are concise.")
        .model(Arc::new(model))
        .build()?,
);

// 3. Drive it through the standard Runner.
let sessions: Arc<dyn SessionService> = Arc::new(InMemorySessionService::new());
sessions
    .create(CreateRequest {
        app_name: "assistant".into(),
        user_id: "user".into(),
        session_id: Some("session-1".into()),
        state: HashMap::new(),
    })
    .await?;
let runner = Runner::builder()
    .app_name("assistant")
    .agent(agent)
    .session_service(sessions)
    .build()?;

let mut stream = runner
    .run(
        UserId::new("user")?,
        SessionId::new("session-1")?,
        Content::new("user").with_text("What is the capital of France?"),
    )
    .await?;

while let Some(event) = stream.next().await {
    let event = event?;
    // The server-assigned interaction id is a first-class field on every event.
    if let Some(id) = event.interaction_id() {
        println!("interaction_id = {id}");
    }
    if let Some(content) = &event.llm_response.content {
        for part in &content.parts {
            if let Part::Text { text } = part {
                print!("{text}");
            }
        }
    }
}

保持一致的默认值

传输层默认采用 API的预期姿态,通过 InteractionOptions 配置(从 adk_model::gemini 重新导出):

选项默认值含义
storetrue交互存储在服务器端,因此开箱即用地支持有状态的延续和可观测性。
statefultrue多轮对话通过 previous_interaction_id 继续;进行串联时仅发送当前轮次的内容。
backgroundBackgroundMode::AgentTargetsOnlybackground=true 用于代理目标(深度研究、长时间运行);false 用于模型目标,以便聊天轮次保持低延迟。
poll_interval1s后台交互在终止前的轮询频率。

将以下任意内容替换为 interaction_options

use adk_model::gemini::{BackgroundMode, InteractionOptions};
use std::time::Duration;

let model = GeminiModel::new(api_key, "gemini-3.7-flash")?
    .use_interactions_api(true)?
    .interaction_options(InteractionOptions {
        store: true,
        stateful: true,
        background: BackgroundMode::AgentTargetsOnly,
        poll_interval: Duration::from_millis(500),
    });

BackgroundMode 有三种变体:AgentTargetsOnly(默认)、AlwaysNever

storefalse 时,API 的不兼容规则会禁用有状态的 继续执行和后台执行;随后传输会发送 transcript 输入,行为与 generateContent 完全相同。

支持的目标(允许列表)

Interactions API 支持一组固定的目标。use_interactions_api(true) 会在配置时验证模型 ID;如果该 ID 不在允许列表中,则返回类别为 InvalidInputAdkError(其中列出受支持的目标),而不是将错误延迟为 不透明的服务器拒绝。

模型目标设置请求的 model 字段;代理目标设置 agent 字段。

模型目标:

  • gemini-3.7-flash
  • gemini-3.6-flash
  • gemini-3.5-flash
  • gemini-3.5-flash-lite
  • gemini-3.1-flash-lite
  • gemini-3.1-pro-preview
  • gemini-3-flash-preview
  • gemini-2.5-pro
  • gemini-2.5-flash
  • gemini-2.5-flash-lite
  • lyria-3-clip-preview
  • lyria-3-pro-preview

这是传输层的兼容性允许列表,而不是推荐列表。 新应用应从 gemini-3.7-flash 开始;由于 Interactions 端点仍然接受较旧的 ID 和预览版 ID, 因此它们仍列在此处。

代理目标:

  • deep-research-pro-preview-12-2025
  • deep-research-preview-04-2026
  • deep-research-max-preview-04-2026
// Unsupported targets fail fast at configuration time:
let result = GeminiModel::new(api_key, "gpt-4")?.use_interactions_api(true);
assert!(result.is_err()); // AdkError { category: InvalidInput, .. }

InteractionTarget 枚举(也从 adk_model::gemini 重新导出) 表示经过验证的目标;如果需要直接检查分类,可以使用它。

混合使用内置工具和自定义工具(bypass_multi_tools_limit

Interactions API 禁止在单个请求中混合使用内置(服务器端)工具和自定义 函数工具。例如,如果要同时使用 Google Search 和自己的函数工具,请将内置工具 转换为函数调用工具,使整个工具集保持统一。这与 ADK-Python 的 bypass_multi_tools_limit=True 相似。

转换逻辑位于 BypassMultiToolsLimit trait 上,由内置工具包装器(GoogleSearchToolUrlContextToolGeminiFileSearchTool)实现。with_bypass_multi_tools_limit(agent) 接收一个内部的单轮 grounded-search agent——一个配置了内置工具和 Gemini 模型的普通 LlmAgent——并返回一个 Arc<dyn Tool>,用于报告 is_builtin() == false,同时在内部运行内置行为并返回普通的函数响应。

use adk_agent::LlmAgentBuilder;
use adk_tool::{BypassMultiToolsLimit, FunctionTool, GoogleSearchTool};
use adk_model::GeminiModel;
use std::sync::Arc;

// The grounded-search agent the bypass tool delegates to: a normal LlmAgent
// with the built-in GoogleSearchTool + a Gemini model.
let search_agent = Arc::new(
    LlmAgentBuilder::new("grounded-search")
        .instruction("Answer the query using Google Search. Be factual and concise.")
        .model(Arc::new(GeminiModel::new(&api_key, "gemini-3.7-flash")?))
        .tool(Arc::new(GoogleSearchTool::new()))
        .build()?,
);

// Convert the built-in search tool into a function tool (is_builtin() == false).
let search_tool = GoogleSearchTool::new().with_bypass_multi_tools_limit(search_agent);

// A custom function tool to mix alongside it.
let weather_tool: Arc<dyn adk_core::Tool> = Arc::new(/* your FunctionTool */);

// Now the tool set is uniform (all function tools) and the Interactions
// transport accepts it.
let model = GeminiModel::new(&api_key, "gemini-3.7-flash")?.use_interactions_api(true)?;
let agent = Arc::new(
    LlmAgentBuilder::new("assistant")
        .model(Arc::new(model))
        .tool(search_tool)
        .tool(weather_tool)
        .build()?,
);

如果在 Interactions transport 下将内置工具与函数工具混用时,让内置工具保持未绕过状态,则请求构建会返回一个 AdkError,其类别为 InvalidInput,并指向 with_bypass_multi_tools_limit。函数调用 id 会在工具循环中原样往返传递,与 generateContent 完全相同。

有状态的连续性与保留回退机制

interaction_id 是一个一等字段,而不是旁路通道。每个 LlmResponse 都携带 interaction_id: Option<String>(由 Interactions transport 填充,否则为 None),而 Event 通过 event.interaction_id() 访问器提供该字段——与 ADK-Python 的 event.interaction_id 相对应。

连续性与提供商无关。LlmRequest 携带一个附加的 previous_response_id: Option<String> 字段,该字段由 LlmAgent 根据最近事件的 interaction_id 填充。Interactions transport 会将其映射到请求的 previous_interaction_id,并且仅发送当前轮次的内容(而不是完整记录)。adk-agent 中不存在 Gemini 专用的粘合逻辑;对于 generateContent 和其他提供商,该字段未被使用(即无操作)。

Turn 1:  request (transcript)        → interaction v1_abc   → event.interaction_id() == "v1_abc"
Turn 2:  request previous_response_id = "v1_abc"
         → previous_interaction_id = "v1_abc", sends only the new turn
         → interaction v1_def        → event.interaction_id() == "v1_def"

保留窗口回退。 存储的交互会过期。如果提供的 previous_interaction_id 已失效或过期,服务器会返回 NotFound。传输层会透明地处理这一情况:它会回退到发送完整的会话记录,并开始一次新的交互——不会向 agent 或 runner 暴露错误。多轮对话可以跨越保留边界持续工作,无需在代码中进行特殊处理。

重新导出的类型

在启用 gemini-interactions 特性后,以下内容可从 adk_model::gemini 获取:

  • GeminiTransportGenerateContent(默认)或 Interactions
  • InteractionOptionsstorestatefulbackgroundpoll_interval
  • BackgroundModeAgentTargetsOnly(默认)、AlwaysNever
  • InteractionTarget — 经过验证的模型/agent 目标。

绕过接口位于 adk-tool 中(可通过 adk_tool 或 umbrella 访问):

  • 带有 with_bypass_multi_tools_limit(agent)BypassMultiToolsLimit trait。
  • GoogleSearchToolUrlContextToolGeminiFileSearchTool 实现。

附加的 LlmResponse.interaction_idLlmRequest.previous_response_id 核心字段始终存在(不受特性门控),因此无论启用了哪些 provider, event.interaction_id() 访问器都能编译。

Gemini Interactions API(测试版) - ADK-Rust 文档 | ADK-Rust