विकास दिशानिर्देश

यह दस्तावेज़ ADK-Rust में योगदान देने वाले डेवलपर्स के लिए व्यापक दिशानिर्देश प्रदान करता है। इन मानकों का पालन करने से पूरे प्रोजेक्ट में कोड की गुणवत्ता, संगति, और रखरखाव क्षमता सुनिश्चित होती है।

विषय-सूची

शुरुआत करना

पूर्वापेक्षाएँ

  • Rust: 1.95.0 या उससे अधिक (edition 2024, rustc --version के साथ जाँचें)
  • Cargo: नवीनतम स्थिर
  • Git: संस्करण नियंत्रण के लिए
  • sccache (अनुशंसित): संकलन कैश, जो rebuild समय को लगभग 70% तक कम करता है

अपना परिवेश सेट करना

# Clone the repository
git clone https://github.com/zavora-ai/adk-rust.git
cd adk-rust

# Option A: Nix/devenv (reproducible — identical on Linux, macOS, CI)
devenv shell

# Option B: Setup script (installs sccache, cmake, etc.)
./scripts/setup-dev.sh

# Option C: Manual
cargo build

# Install cargo-nextest (parallel test runner, ~10x faster)
curl -LsSf https://get.nexte.st/latest/mac | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin

# Run all tests
cargo nextest run --workspace

# Check for lints
cargo clippy --all-targets --all-features

# Format code
cargo fmt --all

परिवेश चर

API कुंजियों की आवश्यकता वाले उदाहरणों और परीक्षणों को चलाने के लिए:

# Gemini (default provider)
export GOOGLE_API_KEY="your-api-key"

# OpenAI (optional)
export OPENAI_API_KEY="your-api-key"

# Anthropic (optional)
export ANTHROPIC_API_KEY="your-api-key"

प्रोजेक्ट संरचना

ADK-Rust को एक Cargo workspace के रूप में कई crates के साथ व्यवस्थित किया गया है:

adk-rust/
├── adk-core/       # Foundational traits and types (Agent, Tool, Llm, Event)
├── adk-telemetry/  # OpenTelemetry integration
├── adk-model/      # LLM providers (Gemini, OpenAI, Anthropic)
├── adk-tool/       # Tool system (FunctionTool, MCP, AgentTool)
├── adk-session/    # Session management (in-memory, SQLite)
├── adk-artifact/   # Binary artifact storage
├── adk-memory/     # Long-term memory with search
├── adk-agent/      # Agent implementations (LlmAgent, workflow agents)
├── adk-runner/     # Execution runtime
├── adk-server/     # REST API and A2A protocol
├── adk-cli/        # Command-line launcher
├── adk-realtime/   # Voice/audio streaming agents
├── adk-graph/      # LangGraph-style workflows
├── adk-browser/    # Browser automation tools
├── adk-eval/       # Agent evaluation framework
├── adk-rust/       # Umbrella crate (re-exports all)
└── examples/       # Working examples

Crate निर्भरताएँ

Crates को निर्भरता क्रम में प्रकाशित किया जाना चाहिए:

  1. adk-core (कोई आंतरिक निर्भरता नहीं)
  2. adk-telemetry
  3. adk-model
  4. adk-tool
  5. adk-session
  6. adk-artifact
  7. adk-memory
  8. adk-agent
  9. adk-runner
  10. adk-server
  11. adk-cli
  12. adk-realtime
  13. adk-graph
  14. adk-browser
  15. adk-eval
  16. adk-rust (umbrella)

कोड शैली

सामान्य सिद्धांत

  1. चतुराई से अधिक स्पष्टता: ऐसा कोड लिखें जिसे पढ़ना और समझना आसान हो
  2. अंतर्निहित से अधिक स्पष्ट: स्पष्ट types और त्रुटि प्रबंधन को प्राथमिकता दें
  3. छोटे functions: functions को केंद्रित रखें और संभव हो तो 50 lines से कम रखें
  4. अर्थपूर्ण नाम: वर्णनात्मक variable और function नामों का उपयोग करें

स्वरूपण

डिफ़ॉल्ट settings के साथ rustfmt का उपयोग करें:

cargo fmt --all

CI pipeline स्वरूपण को लागू करती है। commit करने से पहले हमेशा cargo fmt चलाएँ।

नामकरण परंपराएँ

प्रकारपरंपराउदाहरण
क्रेट्सadk-* (kebab-case)adk-core, adk-agent
मॉड्यूलsnake_casellm_agent, function_tool
प्रकार/लक्षणPascalCaseLlmAgent, ToolContext
फ़ंक्शनsnake_caseexecute_tool, run_agent
स्थिरांकSCREAMING_SNAKE_CASEKEY_PREFIX_APP
टाइप पैरामीटरएकल अपरकेस या PascalCaseT, State

इम्पोर्ट्स

इम्पोर्ट्स को इस क्रम में व्यवस्थित करें:

// 1. Standard library
use std::collections::HashMap;
use std::sync::Arc;

// 2. External crates
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use tokio::sync::RwLock;

// 3. Internal crates (adk-*)
use adk_core::{Agent, Event, Result};

// 4. Local modules
use crate::config::Config;
use super::utils;

क्लिप्पी

सभी कोड बिना किसी चेतावनी के क्लिप्पी पास करने चाहिए:

cargo clippy --all-targets --all-features

क्लिप्पी चेतावनियों को दबाने के बजाय उन्हें ठीक करें। यदि दमन आवश्यक है, तो कारण दस्तावेज़ करें:

#[allow(clippy::too_many_arguments)]
// Builder pattern requires many parameters; refactoring would hurt usability
fn complex_builder(...) { }

त्रुटि प्रबंधन

संरचित त्रुटि एनवेलप

AdkError एक संरचित त्रुटि प्रकार है जिसमें component (where), category (what kind), code (machine key), message (human text), retry hint, और वैकल्पिक details शामिल हैं:

use adk_core::{AdkError, ErrorComponent, ErrorCategory, Result};

// Return Result<T> (aliased to Result<T, AdkError>)
pub async fn my_function() -> Result<String> {
    let data = fetch_data().await?;

    if data.is_empty() {
        return Err(AdkError::new(
            ErrorComponent::Tool,
            ErrorCategory::NotFound,
            "tool.data.not_found",
            "No data found for the given query",
        ));
    }

    Ok(data)
}

Component और Category चुनना

ErrorComponent यह पहचानता है कि विफलता कहाँ हुई (मूल उपप्रणाली, न कि वह trait boundary जिसके माध्यम से यह दिखाई देती है):

घटककब उपयोग करें
Agentएजेंट ऑर्केस्ट्रेशन, सब-एजेंट डिस्पैच
ModelLLM प्रदाता कॉल्स, प्रतिक्रिया पार्सिंग
Toolटूल निष्पादन, पैरामीटर सत्यापन
Sessionसत्र स्थायित्व, स्थिति प्रबंधन
Memoryमेमोरी/RAG संचालन
Graphग्राफ कार्यप्रवाह निष्पादन
Authप्रमाणीकरण, प्राधिकरण
ServerHTTP सर्वर, विन्यास

ErrorCategory वर्गीकृत करता है कि क्या गलत हुआ:

श्रेणीHTTPकब उपयोग करें
InvalidInput400गलत पैरामीटर, config, request body
Unauthorized401अनुपलब्ध या अमान्य प्रमाण-पत्र
Forbidden403मान्य क्रेडेंशियल, अपर्याप्त अनुमतियाँ
NotFound404संसाधन मौजूद नहीं है
RateLimited429अपस्ट्रीम दर सीमा (पुनः प्रयास योग्य)
Timeout408ऑपरेशन ने समय सीमा पार कर ली (पुनः प्रयास योग्य)
Unavailable503अपस्ट्रीम सेवा बंद है (पुनः प्रयास योग्य)
Cancelled499कॉलर या सिस्टम द्वारा रद्द किया गया
Internal500बग, अपरिवर्तनीयता उल्लंघन
Unsupported501सुविधा समर्थित नहीं है

सुविधाजनक कन्स्ट्रक्टर्स

सामान्य पैटर्न के लिए:

// Structured (preferred for new code)
AdkError::not_found(ErrorComponent::Session, "session.not_found", "Session xyz not found")
AdkError::rate_limited(ErrorComponent::Model, "model.openai.rate_limited", "Too many requests")
AdkError::unauthorized(ErrorComponent::Auth, "auth.token_expired", "Bearer token expired")
AdkError::timeout(ErrorComponent::Tool, "tool.execution_timeout", "Tool timed out after 30s")

// Backward-compatible (for migration — produces .legacy codes)
AdkError::tool("No data found")
AdkError::model("Provider returned 500")
AdkError::session("Session not found")

API बिल्डर

समृद्ध त्रुटि संदर्भ के लिए संरचित मेटाडेटा जोड़ें:

let err = AdkError::new(
    ErrorComponent::Model,
    ErrorCategory::RateLimited,
    "model.openai.rate_limited",
    "OpenAI rate limit exceeded",
)
.with_provider("openai")
.with_upstream_status(429)
.with_request_id("req-abc123")
.with_retry(RetryHint {
    should_retry: true,
    retry_after_ms: Some(5000),
    max_attempts: Some(3),
});

पुनः प्रयास संकेत

पुनः प्रयास योग्य श्रेणियाँ (RateLimited, Unavailable, Timeout) स्वचालित रूप से should_retry: true सेट करती हैं। err.is_retryable() के साथ पुनः प्रयास योग्यता जाँचें, जो retry.should_retry को सत्य के एकमात्र स्रोत के रूप में पढ़ता है:

if err.is_retryable() {
    if let Some(delay) = err.retry.retry_after() {
        tokio::time::sleep(delay).await;
    }
    // retry the operation
}

श्रेणी जाँच

err.is_retryable()    // retry.should_retry (RateLimited, Unavailable, Timeout by default)
err.is_not_found()    // category == NotFound
err.is_unauthorized() // category == Unauthorized
err.is_rate_limited() // category == RateLimited
err.is_timeout()      // category == Timeout

घटक जाँच (पिछली संगतता)

err.is_model()   // component == Model
err.is_tool()    // component == Tool
err.is_session() // component == Session
err.is_config()  // code == "config.legacy" (temporary bridge)

HTTP स्थिति और समस्या JSON

AdkError सीधे HTTP प्रतिक्रियाओं के साथ मैप करता है:

let status = err.http_status_code(); // u16 based on category
let body = err.to_problem_json();    // structured JSON error body
// body: { "error": { "code", "message", "component", "category", "requestId", "retryAfter", ... } }

From इम्प्लिमेंटेशनों के साथ क्रेट-स्थानीय त्रुटियाँ

डोमेन-विशिष्ट त्रुटियों वाले क्रेट्स From<CrateLocalError> for AdkError लागू करते हैं:

// In your crate
#[derive(Debug, thiserror::Error)]
pub enum MyToolError {
    #[error("connection failed: {0}")]
    ConnectionFailed(String),
    #[error("timeout after {0}ms")]
    Timeout(u64),
}

impl From<MyToolError> for AdkError {
    fn from(err: MyToolError) -> Self {
        let (category, code) = match &err {
            MyToolError::ConnectionFailed(_) => (ErrorCategory::Unavailable, "mytool.connection"),
            MyToolError::Timeout(_) => (ErrorCategory::Timeout, "mytool.timeout"),
        };
        AdkError::new(ErrorComponent::Tool, category, code, err.to_string())
            .with_source(err)
    }
}

blanket From इम्प्लिमेंटेशन नहीं

std::io::Error और serde_json::Error एकल blanket रूपांतरण के लिए बहुत अधिक सबसिस्टम सीमाएँ पार करते हैं। सही घटक के साथ स्पष्ट map_err का उपयोग करें:

// Good: explicit component and category
let data = std::fs::read_to_string(path)
    .map_err(|e| AdkError::new(
        ErrorComponent::Session,
        ErrorCategory::Internal,
        "session.io_read",
        format!("failed to read session file: {e}"),
    ).with_source(e))?;

// Good: for quick migration
let data = serde_json::from_str(&raw)
    .map_err(|e| AdkError::session(format!("JSON parse failed: {e}")))?;

त्रुटि संदेश

स्पष्ट, क्रियान्वयन योग्य त्रुटि संदेश लिखें:

// Good: specific and actionable
AdkError::new(
    ErrorComponent::Model,
    ErrorCategory::InvalidInput,
    "model.missing_api_key",
    "API key not found. Set GOOGLE_API_KEY environment variable.",
)

// Bad: vague
AdkError::model("Invalid config")

लाइब्रेरी कोड में panic नहीं

लाइब्रेरी क्रेट्स को पुनर्प्राप्ति योग्य त्रुटियों पर कभी panic नहीं करना चाहिए। unwrap(), expect(), और panic!() का src/ कोड में उपयोग करने से बचें (टेस्ट कोड इससे मुक्त है)।

RwLock / Mutex: unwrap() के बजाय graceful degradation का उपयोग करें। एक poisoned lock का मतलब है कि किसी अन्य thread ने panic किया था — वर्तमान thread को भी crash कराना चीज़ों को और खराब बना देता है।

// Bad: panics if lock is poisoned
let state = self.state.write().unwrap();

// Good: log and return a safe default
let Ok(state) = self.state.write() else {
    tracing::error!("state lock poisoned — returning default");
    return Default::default();
};

// Good: recover through the poison (data may be stale but won't crash)
let state = self.state.read().unwrap_or_else(|e| e.into_inner());

कन्स्ट्रक्टर्स: जब initialization विफल हो सकता हो (जैसे, बाहरी सेवाओं से कनेक्ट करना), तो Result लौटाएँ।

// Bad: panics if Docker is not running
pub fn new(config: Config) -> Self {
    let client = connect().expect("connection failed");
    Self { client }
}

// Good: caller decides how to handle the failure
pub fn new(config: Config) -> Result<Self, MyError> {
    let client = connect().map_err(|e| MyError::Init(e.to_string()))?;
    Ok(Self { client })
}

बिल्डर विधियाँ: Arc::get_mut() के लिए expect() के बजाय if let Some का उपयोग करें:

// Bad: panics if Arc is shared
pub fn add_callback(mut self, cb: Callback) -> Self {
    Arc::get_mut(&mut self.callbacks).expect("not shared").push(cb);
    self
}

// Good: silent no-op (builder pattern guarantees single ownership)
pub fn add_callback(mut self, cb: Callback) -> Self {
    if let Some(callbacks) = Arc::get_mut(&mut self.callbacks) {
        callbacks.push(cb);
    }
    self
}

Async पैटर्न

Tokio का उपयोग करें

सभी async कोड Tokio runtime का उपयोग करते हैं:

use tokio::sync::{Mutex, RwLock};

// Prefer RwLock for read-heavy data
let state: Arc<RwLock<State>> = Arc::new(RwLock::new(State::default()));

// Use Mutex for write-heavy or simple cases
let counter: Arc<Mutex<u32>> = Arc::new(Mutex::new(0));

Tokio फीचर कन्वेंशन

लाइब्रेरी क्रेट्स (adk-*) को केवल वही न्यूनतम tokio features घोषित करने चाहिए जिन्हें वे वास्तव में उपयोग करते हैं:

# Library crates — minimal features
tokio = { workspace = true, features = ["rt", "sync", "time"] }

# Binary crates only (adk-cli, examples) — full is acceptable
tokio = { workspace = true, features = ["full"] }

लाइब्रेरी क्रेट में कभी भी features = ["full"] का उपयोग न करें। इससे सभी downstream consumers को हर tokio subsystem compile करना पड़ता है, चाहे उन्हें उसकी आवश्यकता हो या नहीं।

Async Traits

async trait methods के लिए async_trait का उपयोग करें:

use async_trait::async_trait;

#[async_trait]
pub trait MyTrait: Send + Sync {
    async fn do_work(&self) -> Result<()>;
}

स्ट्रीमिंग

streaming responses के लिए EventStream का उपयोग करें:

use adk_core::EventStream;
use async_stream::stream;
use futures::Stream;

fn create_stream() -> EventStream {
    let s = stream! {
        yield Ok(Event::new("inv-1"));
        yield Ok(Event::new("inv-2"));
    };
    Box::pin(s)
}

थ्रेड सुरक्षा

सभी public types Send + Sync होने चाहिए:

// Good: Thread-safe
pub struct MyAgent {
    name: String,
    tools: Vec<Arc<dyn Tool>>,  // Arc for shared ownership
}

// Verify with compile-time checks
fn assert_send_sync<T: Send + Sync>() {}
fn _check() {
    assert_send_sync::<MyAgent>();
}

परीक्षण

टेस्ट रनर

ADK-Rust परीक्षण निष्पादन के लिए cargo-nextest का उपयोग करता है। Nextest प्रत्येक test binary को parallel scheduling के साथ एक अलग process में चलाता है, जिससे इस workspace पर cargo test की तुलना में लगभग 10x गति मिलती है।

# Install (one-time)
curl -LsSf https://get.nexte.st/latest/mac | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin

# Or via devenv (included automatically)
devenv shell

कॉन्फ़िगरेशन .config/nextest.toml में दो profiles के साथ मौजूद है:

  • default — स्थानीय विकास (fail-fast, कोई retries नहीं)
  • ci — CI runs (flaky tests के लिए retries, slow-test warnings)

परीक्षण संगठन

crate/
├── src/
│   ├── lib.rs          # Unit tests at bottom of file
│   └── module.rs       # Module-specific tests
└── tests/
    └── integration.rs  # Integration tests

Unit Tests

unit tests को कोड के उसी file में रखें:

pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_add() {
        assert_eq!(add(2, 3), 5);
    }

    #[tokio::test]
    async fn test_async_function() {
        let result = async_function().await;
        assert!(result.is_ok());
    }
}

Integration Tests

tests/ directory में रखें:

// tests/integration_test.rs
use adk_core::*;

#[tokio::test]
async fn test_full_workflow() {
    // Setup
    let service = InMemorySessionService::new();

    // Execute
    let session = service.create(request).await.unwrap();

    // Assert
    assert_eq!(session.id(), "test-session");
}

Mock Testing

API calls के बिना परीक्षण के लिए MockLlm का उपयोग करें:

use adk_model::MockLlm;

#[tokio::test]
async fn test_agent_with_mock() {
    let mock = MockLlm::new(vec![
        "First response".to_string(),
        "Second response".to_string(),
    ]);

    let agent = LlmAgentBuilder::new("test")
        .model(Arc::new(mock))
        .build()
        .unwrap();

    // Test agent behavior
}

टेस्ट कमांड्स

# Run all tests (nextest — parallel, fast)
cargo nextest run --workspace

# Run specific crate tests
cargo nextest run -p adk-core

# Run with CI profile (retries flaky tests)
cargo nextest run --workspace --profile ci

# Run doctests (nextest doesn't run these — use cargo test)
cargo test --workspace --doc

# Run ignored tests (require API keys)
cargo nextest run --workspace -- --run-ignored

# Run with output (nextest shows output for failing tests by default)
cargo nextest run --workspace --no-capture

# Devenv shortcuts
devenv shell ws-test          # nextest, default profile
devenv shell ws-test-ci       # nextest, CI profile
devenv shell ws-test-slow     # cargo test fallback (includes doctests)

दस्तावेज़ीकरण

Doc Comments

public items के लिए /// का उपयोग करें:

/// Creates a new LLM agent with the specified configuration.
///
/// # Arguments
///
/// * `name` - A unique identifier for this agent
/// * `model` - The LLM provider to use for reasoning
///
/// # Examples
///
/// ```rust
/// use adk_agent::LlmAgentBuilder;
///
/// let agent = LlmAgentBuilder::new("assistant")
///     .model(Arc::new(model))
///     .build()?;
/// ```
///
/// # Errors
///
/// Returns an error with component `Agent` if the model is not set.
pub fn new(name: impl Into<String>) -> Self {
    // ...
}

Module Documentation

lib.rs के शीर्ष पर module-level docs जोड़ें:

//! # adk-core
//!
//! Core types and traits for ADK-Rust.
//!
//! ## Overview
//!
//! This crate provides the foundational types...

README Files

प्रत्येक crate में एक README.md होना चाहिए जिसमें:

  1. संक्षिप्त विवरण
  2. स्थापना निर्देश
  3. त्वरित उदाहरण
  4. पूर्ण दस्तावेज़ीकरण का लिंक

Documentation Tests

सुनिश्चित करें कि doc उदाहरण compile हों:

cargo test --doc --all

Pull Request प्रक्रिया

जमा करने से पहले

  1. पूरा test suite चलाएँ:

    cargo nextest run --workspace
  2. clippy चलाएँ:

    cargo clippy --all-targets --all-features
  3. कोड format करें:

    cargo fmt --all
  4. public API जोड़ने/बदलने पर दस्तावेज़ीकरण अपडेट करें

  5. नई functionality के लिए tests जोड़ें

PR दिशानिर्देश

  • शीर्षक: परिवर्तन का स्पष्ट, संक्षिप्त विवरण
  • विवरण: क्या और क्यों समझाएँ (कैसे नहीं)
  • आकार: PRs को केंद्रित रखें; बड़े बदलावों को विभाजित करें
  • Tests: नई functionality के लिए tests शामिल करें
  • Breaking changes: विवरण में स्पष्ट रूप से दस्तावेज़ित करें

Commit Messages

conventional commits का पालन करें:

feat: add OpenAI streaming support
fix: correct tool parameter validation
docs: update quickstart guide
refactor: simplify session state management
test: add integration tests for A2A protocol

Project Scaffolding

नए projects को scaffold करने के लिए Composable Template System के साथ cargo adk new का उपयोग करें। अंतर्निर्मित registry 12 templates, 9 add-ons, और 5 enterprise patterns प्रदान करती है:

# Basic agent (default)
cargo adk new my-agent

# Agent with tools and Docker support
cargo adk new my-agent --template tools --addon docker

# A2A protocol agent with CI and telemetry
cargo adk new my-agent --template a2a --addon ci --addon telemetry

# Graph workflow with enterprise observability
cargo adk new my-agent --template graph --addon telemetry --addon docker --addon ci

--addon flag composable है — किसी भी base template को किसी भी संख्या में addons के साथ combine करें। templates, addons, और enterprise patterns की पूरी सूची के लिए Composable Templates documentation देखें।

सामान्य कार्य

नया Tool जोड़ना

  1. tool बनाएँ:
use adk_core::{Tool, ToolContext, Result};
use async_trait::async_trait;
use serde_json::Value;

pub struct MyTool {
    // fields
}

#[async_trait]
impl Tool for MyTool {
    fn name(&self) -> &str {
        "my_tool"
    }

    fn description(&self) -> &str {
        "Does something useful"
    }

    fn parameters_schema(&self) -> Option<Value> {
        Some(serde_json::json!({
            "type": "object",
            "properties": {
                "input": { "type": "string" }
            },
            "required": ["input"]
        }))
    }

    async fn execute(&self, ctx: Arc<dyn ToolContext>, args: Value) -> Result<Value> {
        let input = args["input"].as_str().unwrap_or_default();
        Ok(serde_json::json!({ "result": input }))
    }
}
  1. agent में जोड़ें:
let agent = LlmAgentBuilder::new("agent")
    .model(model)
    .tool(Arc::new(MyTool::new()))
    .build()?;

नया Model Provider जोड़ना

  1. adk-model/src/ में module बनाएँ:
// adk-model/src/mymodel/mod.rs
mod client;
pub use client::MyModelClient;
  1. Llm trait लागू करें:
use adk_core::{Llm, LlmRequest, LlmResponse, LlmResponseStream, Result};

pub struct MyModelClient {
    api_key: String,
}

#[async_trait]
impl Llm for MyModelClient {
    fn name(&self) -> &str {
        "my-model"
    }

    async fn generate_content(
        &self,
        request: LlmRequest,
        stream: bool,
    ) -> Result<LlmResponseStream> {
        // Implementation
    }
}
  1. adk-model/Cargo.toml में feature flag जोड़ें:
[features]
mymodel = ["dep:mymodel-sdk"]
  1. शर्तानुसार export करें:
#[cfg(feature = "mymodel")]
pub mod mymodel;
#[cfg(feature = "mymodel")]
pub use mymodel::MyModelClient;

नया Agent Type जोड़ना

  1. adk-agent/src/ में module बनाएँ:
// adk-agent/src/my_agent.rs
use adk_core::{Agent, EventStream, InvocationContext, Result};
use async_trait::async_trait;

pub struct MyAgent {
    name: String,
}

#[async_trait]
impl Agent for MyAgent {
    fn name(&self) -> &str {
        &self.name
    }

    fn description(&self) -> &str {
        "My custom agent"
    }

    async fn run(&self, ctx: Arc<dyn InvocationContext>) -> Result<EventStream> {
        // Implementation
    }
}
  1. adk-agent/src/lib.rs में export करें:
mod my_agent;
pub use my_agent::MyAgent;

Debugging Tips

  1. tracing सक्षम करें:

    adk_telemetry::init_telemetry();
  2. events जाँचें:

    while let Some(event) = stream.next().await {
        eprintln!("Event: {:?}", event);
    }
  3. RUST_LOG का उपयोग करें:

    RUST_LOG=debug cargo run --example myexample

पिछला: ← Access Control

प्रश्न? GitHub पर issue खोलें।

विकास दिशानिर्देश - ADK-Rust दस्तावेज़ीकरण | ADK-Rust