Gemini Interactions API (बीटा)
ADK-Rust Google के Interactions API के लिए एक समर्पित क्लाइंट प्रदान करता है — जो Gemini API के लिए Google की नई दिशा है। यह generateContent अनुरोध/प्रतिक्रिया संरचना को एक स्थिति-आधारित Interaction संसाधन से प्रतिस्थापित करता है, जो टाइप की गई चरण समयरेखा, सर्वर-साइड इतिहास और मूल एजेंटिक वर्कफ़्लो पर आधारित है।
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 का उपयोग कब करें
| पहलू | generateContent (GeminiModel) | इंटरैक्शन API (create_interaction) |
|---|---|---|
| एंडपॉइंट | POST /v1beta/models/{model}:generateContent | POST /v1beta/interactions |
| स्थिरता | स्थिर, उत्पादन के लिए अनुशंसित | बीटा, स्कीमा बदल सकता है |
| इतिहास | क्लाइंट पूरा प्रतिलेख फिर से भेजता है | previous_interaction_id के माध्यम से सर्वर-साइड |
| प्रतिक्रिया संरचना | candidates + parts | steps टाइमलाइन |
एजेंट रनटाइम (Llm trait) | ✅ डिफ़ॉल्ट ट्रांसपोर्ट | ✅ use_interactions_api के माध्यम से वैकल्पिक |
| नए मॉडल / टूल | — | पहले यहीं लॉन्च करें |
ADK एजेंट रनटाइम (Llm trait, tool loop, और Runner) डिफ़ॉल्ट रूप से generateContent का उपयोग करता है। आप use_interactions_api(true) को GeminiModel पर सक्षम करके उसी रनटाइम के माध्यम से Interactions API को भी चला सकते हैं — नीचे रनटाइम ट्रांसपोर्ट के रूप में Interactions देखें। प्रत्यक्ष क्लाइंट (जिसका दस्तावेज़ीकरण पहले दिया गया है) उन कॉलर के लिए उपलब्ध रहता है जो एजेंट को शामिल किए बिना सर्वर-साइड इतिहास, निरीक्षण योग्य चरण, या केवल बीटा मॉडल चाहते हैं।
सक्षम करना
# 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.created, step.start, step.delta, step.stop,
interaction.status_update, interaction.completed, और error। अज्ञात
भविष्य के इवेंट स्ट्रीम को विफल करने के बजाय InteractionSseEvent::Other में
डीसीरियलाइज़ हो जाते हैं।
सर्वर-साइड मल्टी-टर्न
बातचीत को इतिहास दोबारा भेजे बिना जारी रखने के लिए पिछली interaction का id पास करें। ध्यान दें कि tools, system_instruction, और generation_config
interaction-स्कोप वाले हैं और प्रत्येक टर्न में फिर से निर्दिष्ट किए जाने चाहिए:
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 क्लाइंट-साइड tool calls को 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?;
जीवनचक्र
संग्रहीत interactions (सर्वर का डिफ़ॉल्ट) को प्राप्त, हटाया या रद्द किया जा सकता है:
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 जीवनचक्र को प्रतिबिंबित करता है: InProgress, RequiresAction,
Completed, Failed, Cancelled, Incomplete, BudgetExceeded। नियंत्रण प्रवाह के लिए
is_terminal() और requires_action() का उपयोग करें।
सीमाएँ
Interactions API अभी Batch API या स्पष्ट caching का समर्थन नहीं करता
(सर्वर-साइड implicit caching, previous_interaction_id के माध्यम से उपलब्ध है)।
ADK agent runtime डिफ़ॉल्ट रूप से generateContent का उपयोग करता है; Interactions API
ऊपर दिए गए standalone client के रूप में और opt-in
runtime transport के रूप में, दोनों रूपों में उपलब्ध है (देखें
नीचे)।
runtime transport के रूप में Interactions (agents + runner)
ऊपर का पूरा भाग direct wire client (adk_gemini::interactions)
— एक standalone capability का दस्तावेज़ीकरण करता है, जिसे आप स्वयं कॉल करते हैं। यह अनुभाग
इसके ऊपर निर्मित runtime transport का दस्तावेज़ीकरण करता है: GeminiModel पर एक
toggle, जो एक सामान्य LlmAgent, Runner, tool loop और sessions को Interactions API
चलाने देता है, और इसके लिए आपके agent code में कोई बदलाव नहीं करना पड़ता।
यह ADK-Python के समान है, जहाँ Gemini(model=..., use_interactions_api=True)
वही Agent, runner और tools बनाए रखता है। कोई agent transport-agnostic होता है:
model के backend से बात करने का तरीका बदलने पर नए agent type की आवश्यकता नहीं होनी चाहिए।
generateContent अभी भी डिफ़ॉल्ट है
generateContent स्थिर
production workloads के लिए डिफ़ॉल्ट और अनुशंसित transport बना रहता है। Interactions API beta है और इसका schema बदल सकता है।
प्रत्येक model के लिए transport को सोच-समझकर opt in करें। जब आप
use_interactions_api(true) को कॉल नहीं करते हैं, तो GeminiModel पहले की तरह ही
व्यवहार करता है — generateContent path में कोई व्यवहारगत बदलाव नहीं होता।
transport सक्षम करना
यह transport gemini-interactions feature के पीछे gated है (adk-rust → adk-model → adk-gemini/interactions से
forwarded):
adk-model = { version = "2.1.0", features = ["gemini-interactions"] }
adk-rust = { version = "2.1.0", features = ["gemini-interactions"] }
model पर switch चालू करें और उसे सामान्य LlmAgent तथा Runner में wrap करें —
agent setup में इसके अलावा कुछ भी बदलने की आवश्यकता नहीं है:
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 से पुनः निर्यातित):
| विकल्प | डिफ़ॉल्ट | अर्थ |
|---|---|---|
store | true | इंटरैक्शन सर्वर-साइड संग्रहीत किए जाते हैं, ताकि स्थिति-आधारित निरंतरता और ऑब्ज़र्वेबिलिटी बिना किसी अतिरिक्त व्यवस्था के काम करें। |
stateful | true | बहु-टर्न वार्तालाप previous_interaction_id के माध्यम से जारी रहते हैं; चेनिंग के दौरान केवल वर्तमान टर्न की सामग्री भेजी जाती है। |
background | BackgroundMode::AgentTargetsOnly | एजेंट लक्ष्यों (Deep Research, लंबे समय तक चलने वाले) के लिए background=true; मॉडल लक्ष्यों के लिए false, ताकि चैट टर्न की विलंबता कम रहे। |
poll_interval | 1s | किसी पृष्ठभूमि इंटरैक्शन को टर्मिनल होने तक कितनी बार पोल किया जाता है। |
इनमें से किसी को भी 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 (डिफ़ॉल्ट), Always और
Never।
जब
store,falseहोता है, तो API के असंगतता नियम स्थिति-युक्त निरंतरता और बैकग्राउंड निष्पादन को अक्षम कर देते हैं; इसके बाद ट्रांसपोर्ट transcript इनपुट भेजता है, ठीक generateContent की तरह।
समर्थित लक्ष्य (अनुमत सूची)
Interactions API लक्ष्यों के एक निश्चित समूह का समर्थन करता है। use_interactions_api(true)
कॉन्फ़िगरेशन के समय मॉडल आईडी का सत्यापन करता है और जब आईडी अनुमत सूची में
नहीं होती, तब श्रेणी InvalidInput वाला AdkError लौटाता है (समर्थित लक्ष्यों के
नाम सहित) — इसे अस्पष्ट सर्वर अस्वीकृति पर छोड़ने के बजाय।
मॉडल लक्ष्य अनुरोध का model फ़ील्ड सेट करता है; एजेंट लक्ष्य
agent फ़ील्ड सेट करता है।
मॉडल लक्ष्य:
gemini-3.7-flashgemini-3.6-flashgemini-3.5-flashgemini-3.5-flash-litegemini-3.1-flash-litegemini-3.1-pro-previewgemini-3-flash-previewgemini-2.5-progemini-2.5-flashgemini-2.5-flash-litelyria-3-clip-previewlyria-3-pro-preview
यह ट्रांसपोर्ट की संगतता संबंधी अनुमत सूची है, अनुशंसा सूची नहीं।
नए एप्लिकेशन को gemini-3.7-flash से शुरू करना चाहिए; पुराने और प्रीव्यू आईडी
अब भी सूचीबद्ध हैं क्योंकि Interactions एंडपॉइंट अभी भी उन्हें स्वीकार करता है।
एजेंट लक्ष्य:
deep-research-pro-preview-12-2025deep-research-preview-04-2026deep-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 enum (adk_model::gemini से फिर से एक्सपोर्ट किया गया) किसी सत्यापित गंतव्य
का प्रतिनिधित्व करता है, यदि आपको वर्गीकरण का सीधे निरीक्षण करना हो।
बिल्ट-इन और कस्टम टूल का मिश्रण (bypass_multi_tools_limit)
Interactions API एक ही अनुरोध में बिल्ट-इन (सर्वर-साइड) टूल और कस्टम
फ़ंक्शन टूल के मिश्रण को प्रतिबंधित करता है। उदाहरण के लिए, Google Search
के साथ अपना फ़ंक्शन टूल उपयोग करने के लिए, बिल्ट-इन टूल को फ़ंक्शन-कॉलिंग
टूल में बदलें, ताकि पूरा टूल सेट एकसमान हो। यह ADK-Python के
bypass_multi_tools_limit=True के अनुरूप है।
रूपांतरण BypassMultiToolsLimit trait में मौजूद है, जिसे अंतर्निहित tool wrappers (GoogleSearchTool, UrlContextTool,
GeminiFileSearchTool) द्वारा कार्यान्वित किया गया है। with_bypass_multi_tools_limit(agent) एक आंतरिक
single-turn grounded-search agent — एक साधारण LlmAgent, जिसे
अंतर्निहित tool और Gemini model के साथ कॉन्फ़िगर किया गया है — लेता है और एक Arc<dyn Tool> लौटाता है, जो
is_builtin() == false की रिपोर्ट करता है और अंतर्निहित व्यवहार को आंतरिक रूप से चलाता है, तथा
सामान्य function response लौटाता है।
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 के अंतर्गत function tools के साथ मिलाते समय किसी अंतर्निहित tool को un-bypassed छोड़ देते हैं, तो request building एक AdkError लौटाता है, जिसकी
category InvalidInput होती है और जो आपको with_bypass_multi_tools_limit की ओर निर्देशित करती है।
function call id tool loop के माध्यम से बिना किसी परिवर्तन के round-trip होता है, ठीक
generateContent की तरह।
स्थिति-युक्त निरंतरता और retention fallback
interaction_id एक प्रथम-श्रेणी फ़ील्ड है, कोई side channel नहीं। प्रत्येक
LlmResponse में interaction_id: Option<String> शामिल होता है (Interactions transport द्वारा
भरा जाता है, और अन्यथा None होता है), तथा Event इसे
event.interaction_id() accessor के माध्यम से सामने लाता है — ADK-Python के
event.interaction_id के अनुरूप।
निरंतरता provider-neutral है। LlmRequest में एक अतिरिक्त
previous_response_id: Option<String> फ़ील्ड होता है, जिसे LlmAgent
सबसे हालिया event के interaction_id से भरता है। Interactions transport इसे
request के previous_interaction_id में map करता है और केवल वर्तमान turn की
contents भेजता है (पूरे transcript के बजाय)। adk-agent में Gemini-विशिष्ट
glue मौजूद नहीं है; generateContent और अन्य providers के लिए यह फ़ील्ड
उपयोग नहीं होती (no-op)।
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 लौटाता है। यह
ट्रांसपोर्ट इसे पारदर्शी रूप से संभालता है: यह पूरी ट्रांस्क्रिप्ट भेजने पर वापस आ जाता है और एक नया इंटरैक्शन शुरू करता है — कोई त्रुटि एजेंट या रनर को दिखाई नहीं जाती। आपका कोड किसी विशेष प्रबंधन के बिना रिटेंशन सीमा के पार भी मल्टी-टर्न वार्तालापों को जारी रखता है।
पुनः-निर्यातित प्रकार
gemini-interactions फ़ीचर के अंतर्गत, निम्नलिखित adk_model::gemini से उपलब्ध हैं:
GeminiTransport—GenerateContent(डिफ़ॉल्ट) याInteractions।InteractionOptions—store,stateful,background,poll_interval।BackgroundMode—AgentTargetsOnly(डिफ़ॉल्ट),Always,Never।InteractionTarget— एक मान्यीकृत मॉडल/एजेंट गंतव्य।
बायपास सतह adk-tool में स्थित है (adk_tool या अम्ब्रेला के माध्यम से उपलब्ध):
BypassMultiToolsLimitट्रेट, जिसमेंwith_bypass_multi_tools_limit(agent)है।GoogleSearchTool,UrlContextTool,GeminiFileSearchToolद्वारा कार्यान्वित।
अतिरिक्त LlmResponse.interaction_id और LlmRequest.previous_response_id
कोर फ़ील्ड हमेशा मौजूद रहते हैं (फ़ीचर-गेटेड नहीं होते), इसलिए event.interaction_id()
ऐक्सेसर संकलित होता है, चाहे कोई भी प्रदाता सक्षम हों।