रनर
adk-runner से प्राप्त निष्पादन रनटाइम, जो एजेंट निष्पादन का समन्वय करता है।
अवलोकन
Runner एजेंट निष्पादन के संपूर्ण जीवनचक्र का प्रबंधन करता है:
- सत्र प्रबंधन (सत्र बनाना/पुनर्प्राप्त करना)
- मेमोरी इंजेक्शन (प्रासंगिक मेमोरी खोजना और इंजेक्ट करना)
- आर्टिफ़ैक्ट प्रबंधन (स्कोप किए गए आर्टिफ़ैक्ट तक पहुँच)
- इवेंट स्ट्रीमिंग (इवेंट संसाधित करना और अग्रेषित करना)
- एजेंट ट्रांसफ़र (बहु-एजेंट हैंडऑफ़ संभालना)
इंस्टॉलेशन
[dependencies]
adk-runner = "2.1.0"
RunnerConfig
आवश्यक सेवाओं के साथ रनर को कॉन्फ़िगर करें:
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,
plugin_manager: None,
run_config: None,
compaction_config: None,
context_cache_config: None,
cache_capable: None,
request_context: None,
cancellation_token: None,
};
let runner = Runner::new(config)?;
RunnerConfigBuilder (अनुशंसित)
Runner बनाने के लिए typestate builder का उपयोग करें। builder आवश्यक फ़ील्ड को कंपाइल समय पर लागू करता है और सभी वैकल्पिक फ़ील्ड के लिए डिफ़ॉल्ट मान निर्धारित करता है, इसलिए भविष्य के रिलीज़ में नए फ़ील्ड जोड़ने से आपका कोड प्रभावित नहीं होगा:
use adk_runner::Runner;
let runner = Runner::builder()
.app_name("my_app")
.agent(Arc::new(my_agent))
.session_service(Arc::new(InMemorySessionService::new()))
// Optional fields — only set what you need
.artifact_service(Arc::new(InMemoryArtifactService::new()))
.build()?;
builder के लिए तीन फ़ील्ड आवश्यक हैं: app_name, agent, और session_service। बाकी सब वैकल्पिक हैं और इनके लिए उपयुक्त डिफ़ॉल्ट मान हैं। build() विधि तभी उपलब्ध होती है जब सभी तीन आवश्यक फ़ील्ड सेट हो जाएँ — किसी एक के छूट जाने पर रनटाइम त्रुटि नहीं, बल्कि कंपाइल-टाइम त्रुटि होती है।
कॉन्फ़िगरेशन फ़ील्ड kry vel
| फ़ील्ड | प्रकार | आवश्यक | विवरण |
|---|---|---|---|
app_name | String | हाँ | एप्लिकेशन पहचानकर्ता |
agent | Arc<dyn Agent> | हाँ | निष्पादित किया जाने वाला रूट एजेंट |
session_service | Arc<dyn SessionService> | हाँ | सत्र संग्रहण बैकएंड |
artifact_service | Option<Arc<dyn ArtifactService>> | नहीं | आर्टिफैक्ट संग्रहण |
memory_service | Option<Arc<dyn Memory>> | नहीं | दीर्घकालिक मेमोरी |
plugin_manager | Option<Arc<PluginManager>> | नहीं | प्लगइन जीवनचक्र हुक |
compaction_config | Option<EventsCompactionConfig> | नहीं | संदर्भ संक्षिप्तीकरण सेटिंग्स |
run_config | Option<RunConfig> | नहीं | निष्पादन विकल्प |
context_cache_config | Option<ContextCacheConfig> | नहीं | रनर-स्तरीय संदर्भ कैश जीवनचक्र (प्रायोगिक — नीचे देखें) |
cache_capable | Option<Arc<dyn CacheCapable>> | नहीं | कैश-सक्षम मॉडल संदर्भ (प्रायोगिक — नीचे देखें) |
request_context | Option<RequestContext> | नहीं | प्रमाणीकरण मिडलवेयर संदर्भ |
cancellation_token | Option<CancellationToken> | नहीं | सहकारी रद्दीकरण |
प्रॉम्प्ट कैशिंग
कैशिंग प्रदाता-स्तरीय चिंता है और इसके लिए Runner कॉन्फ़िगरेशन की आवश्यकता नहीं होती। प्रत्येक प्रदाता एकीकरण इसे वहीं संभालता है जहाँ अनुरोध तैयार किया जाता है:
| प्रदाता | तंत्र | डिफ़ॉल्ट |
|---|---|---|
| Anthropic / Bedrock | cache_control ब्रेकपॉइंट | चालू (AnthropicConfig::prompt_caching, with_prompt_caching(false) से ऑप्ट आउट करें) |
| OpenAI | सर्वर-साइड प्रॉम्प्ट कैशिंग, रिटेंशन के लिए PromptCacheRetention | स्वचालित |
| Gemini | 2.5/3.x पर निहित कैशिंग — साझा प्रीफ़िक्स पर बिना कोड परिवर्तन के छूट मिलती है | स्वचालित |
कैश हिट बिना किसी अतिरिक्त वायरिंग के देखे जा सकते हैं: Gemini एकीकरण प्रत्येक प्रतिक्रिया पर cachedContentTokenCount रिकॉर्ड करता है।
context_cache_configऔरcache_capableप्रयोगात्मक हैं और इन्हें सेट नहीं किया जाना चाहिए। ये Runner से Gemini के explicitcachedContentsAPI को संचालित करते हैं। वह API कैश के लिएsystem_instruction,tools, औरtool_configको प्रतिस्थापित करना आवश्यक बनाता है — इनमें से किसी के साथ कैश भेजनाINVALID_ARGUMENTके साथ अस्वीकार कर दिया जाता है। Runner एजेंट द्वारा अपने टूल्स का समाधान करने से पहले कैश चुनता है, इसलिए वह अनुरोध तैयार नहीं कर सकता, और इन फ़ील्ड्स को सक्षम करने पर वर्तमान में कैश हिट उत्पन्न नहीं होते। Gemini के लिए गारंटीकृत (सर्वोत्तम-प्रयास के बजाय) कैशिंग मॉडल एकीकरण में होनी चाहिए, ठीक वैसे ही जैसे अन्य प्रोवाइडर इसे करते हैं।
एजेंट चलाना
उपयोगकर्ता इनपुट के साथ एजेंट चलाएँ:
use adk_core::{Content, SessionId, UserId};
use futures::StreamExt;
let user_content = Content::new("user").with_text("Hello!");
let mut stream = runner.run(
UserId::new("user-123")?,
SessionId::new("session-456")?,
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),
}
}
स्ट्रिंग सुविधा विधि
सरल कॉल साइट्स के लिए, run_str() सादे &str तर्क स्वीकार करता है और नएटाइप रूपांतरण को आंतरिक रूप से संभालता है:
let mut stream = runner.run_str(
"user-123",
"session-456",
Content::new("user").with_text("Hello!"),
).await?;
यदि स्ट्रिंग सत्यापन में विफल होती है (खाली है, इसमें नल बाइट्स हैं, या लंबाई सीमा से अधिक है), तो run_str() एजेंट लूप शुरू करने से पहले एक त्रुटि लौटाता है। टाइप किए गए UserId/SessionId के साथ मौजूदा run() विधि अपरिवर्तित रहती है।
व्यवधान और रन पृथक्करण
जैसे ही run() अपनी स्ट्रीम लौटाता है, रन पंजीकृत हो जाता है, और
उस स्ट्रीम के ड्रॉप होने पर — जिसमें बिना कभी पोल किए ड्रॉप किया जाना भी शामिल है — उसका पंजीकरण रद्द कर दिया जाता है।
| विधि | दायरा |
|---|---|
interrupt(session_id) | उस सत्र ID के लिए सभी ऐप्स और उपयोगकर्ताओं में हर चल रहे रन को रद्द करता है |
interrupt_identity(app_name, user_id, session_id) | एक सटीक पहचान के लिए रन रद्द करता है |
active_runs() | प्रत्येक जारी रन की पहचान; दोहराई गई पहचान समवर्ती रन दर्शाती है |
active_session_ids() | जारी रन के डुप्लिकेट हटाए गए सेशन ID |
// Cancel one tenant's run without touching another that shares the session ID
let cancelled = runner.interrupt_identity("my-app", "user-1", "session-1");
एक session ID केवल किसी app और user के भीतर अद्वितीय होता है, इसलिए interrupt(session_id) व्यापक रूप है और interrupt_identity सटीक रूप। जब एक Runner एक से अधिक app या user के लिए कार्य करता हो, तो interrupt_identity को प्राथमिकता दें।
Runs को session ID के बजाय एक अद्वितीय run ID द्वारा ट्रैक किया जाता है, इसलिए एक ही identity के लिए दो runs को अलग-अलग ट्रैक किया जाता है और प्रत्येक केवल स्वयं का deregister करता है।
Persistence identity से बंधी है
Runner द्वारा persist किया गया प्रत्येक event — user turns, model responses, transfer events,
plugin events और compaction events — पूर्ण
(app_name, user_id, session_id) triple के साथ SessionService::append_event_for_identity के माध्यम से लिखा जाता है। इसलिए एक SessionService जिसकी natural key composite हो, प्रत्येक event को उसके tenant से बाँध सकता है और raw-session-ID append_event path को पूरी तरह अस्वीकार या अनदेखा कर सकता है।
Execution Flow
┌─────────────────────────────────────────────────────────────┐
│ Runner.run() │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 1. Session Retrieval │
│ │
│ SessionService.get(app_name, user_id, session_id) │
│ → Creates new session if not exists │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 2. Agent Selection │
│ │
│ Check session state for active agent │
│ → Use root agent or transferred agent │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 3. Context Creation │
│ │
│ InvocationContext with: │
│ - Session (mutable) │
│ - Artifacts (scoped to session) │
│ - Memory (if configured) │
│ - Run config │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 4. Agent Execution │
│ │
│ agent.run(ctx) → EventStream │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 5. Event Processing │
│ │
│ For each event: │
│ - Update session state │
│ - Handle transfers │
│ - Forward to caller │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 6. Session Save │
│ │
│ SessionService.append_event(session, events) │
└─────────────────────────────────────────────────────────────┘
InvocationContext
Execution के दौरान agents को प्रदान किया जाने वाला context:
pub trait InvocationContext: CallbackContext {
/// The agent being executed
fn agent(&self) -> Arc<dyn Agent>;
/// Memory service (if configured)
fn memory(&self) -> Option<Arc<dyn Memory>>;
/// Current session
fn session(&self) -> &dyn Session;
/// Execution configuration
fn run_config(&self) -> &RunConfig;
/// Signal end of invocation
fn end_invocation(&self);
/// Check if invocation has ended
fn ended(&self) -> bool;
}
RunConfig
Execution options:
pub struct RunConfig {
/// Streaming mode for responses
pub streaming_mode: StreamingMode,
// ... other fields (tool_confirmation_decisions, cached_content, etc.)
}
ToolExecutionStrategy
यह नियंत्रित करता है कि एकल LLM response से की गई multiple tool calls को कैसे dispatch किया जाए:
| रणनीति | व्यवहार |
|---|---|
Sequential (डिफ़ॉल्ट) | LLM द्वारा लौटाए गए क्रम में टूल को एक-एक करके निष्पादित करें |
Parallel | सभी टूल को समवर्ती रूप से निष्पादित करें; सुरक्षा की ज़िम्मेदारी कॉलर की है |
Auto | सुरक्षित केवल-पठन उपसमुच्चय को समवर्ती रूप से निष्पादित करें, फिर शेष सभी कॉल क्रमिक रूप से |
प्रति-एजेंट LlmAgentBuilder के माध्यम से सेट करें:
use adk_core::ToolExecutionStrategy;
let agent = LlmAgentBuilder::new("fast_agent")
.model(model)
.tool_execution_strategy(ToolExecutionStrategy::Auto)
.tool(Arc::new(
search_tool
.with_read_only(true)
.with_concurrency_safe(true),
))
.tool(Arc::new(save_tool)) // runs after the concurrent safe subset
.build()?;
Auto मोड में, डिस्पैच लूप is_read_only() और is_concurrency_safe() दोनों से जानकारी प्राप्त करता है। जिन कॉल में चुने गए टूल दोनों विधियों के लिए true लौटाते हैं, वे पहले समवर्ती रूप से चलते हैं; शेष सभी कॉल इसके बाद क्रमिक रूप से चलती हैं। Parallel स्पष्ट कॉलर ओवरराइड के रूप में इन मेटाडेटा जाँचों को छोड़ देता है। रणनीति चाहे जो भी हो, परिणाम हमेशा मूल LLM-द्वारा लौटाए गए क्रम में पुनः संयोजित किए जाते हैं। विफल टूल बैच को रद्द किए बिना JSON त्रुटि प्रतिक्रिया उत्पन्न करते हैं।
pub enum StreamingMode {
/// No streaming, return complete response
None,
/// Server-Sent Events (default)
SSE,
/// Bidirectional streaming (realtime)
Bidi,
}
एजेंट स्थानांतरण
Runner बहु-एजेंट स्थानांतरण को स्वचालित रूप से संभालता है:
// In an agent's tool or callback
if should_transfer {
// Set transfer in event actions
ctx.set_actions(EventActions {
transfer_to_agent: Some("specialist_agent".to_string()),
..Default::default()
});
}
Runner:
- इवेंट में स्थानांतरण अनुरोध का पता लगाएगा
- sub_agents में लक्ष्य एजेंट खोजेगा
- नए सक्रिय एजेंट के साथ सत्र स्थिति अपडेट करेगा
- नए एजेंट के साथ निष्पादन जारी रखेगा
संदर्भ संक्षिप्तीकरण
लंबे समय तक चलने वाले सत्रों के लिए, LLM संदर्भ विंडो को सीमित रखने हेतु स्वचालित संदर्भ संक्षिप्तीकरण सक्षम करें:
use adk_runner::{Runner, RunnerConfig, EventsCompactionConfig};
use adk_agent::LlmEventSummarizer;
use std::sync::Arc;
let summarizer = LlmEventSummarizer::new(model.clone());
let config = RunnerConfig {
// ... other fields ...
compaction_config: Some(EventsCompactionConfig {
compaction_interval: 3, // Compact every 3 invocations
overlap_size: 1, // Keep 1 event overlap for continuity
summarizer: Arc::new(summarizer),
}),
// ...
};
जब संक्षिप्तीकरण शुरू होता है, तो पुराने इवेंट को एक सारांश इवेंट से प्रतिस्थापित कर दिया जाता है। conversation_history() मूल इवेंट के बजाय सारांश का स्वचालित रूप से उपयोग करता है।
पूरे दस्तावेज़ के लिए संदर्भ संक्षिप्तीकरण देखें।
Launcher के साथ एकीकरण
Launcher आंतरिक रूप से Runner का उपयोग करता है:
// Launcher creates Runner with default services
Launcher::new(agent)
.app_name("my_app")
.run()
.await?;
// Equivalent to using the builder:
let runner = Runner::builder()
.app_name("my_app")
.agent(agent)
.session_service(Arc::new(InMemorySessionService::new()))
.build()?;
कस्टम Runner का उपयोग
उन्नत परिदृश्यों के लिए, Runner का सीधे उपयोग करें:
use adk_runner::Runner;
// Production configuration using the builder
let runner = Runner::builder()
.app_name("production_app")
.agent(my_agent)
.session_service(Arc::new(SqliteSessionService::new(db_pool)))
.artifact_service(Arc::new(S3ArtifactService::new(s3_client)))
.memory_service(Arc::new(QdrantMemoryService::new(qdrant_client)))
.build()?;
// Use in HTTP handler with run_str() for convenience
async fn chat_handler(runner: &Runner, request: ChatRequest) -> Response {
let stream = runner.run_str(
&request.user_id,
&request.session_id,
request.content,
).await?;
// Stream events to client
Response::sse(stream)
}
पिछला: ← कोर प्रकार | अगला: Launcher →