Modellanbieter (Cloud)

ADK-Rust unterstützt mehrere Cloud-LLM-Anbieter über das adk-model-Crate. Alle Anbieter implementieren das Llm-Trait, wodurch sie in Ihren Agents austauschbar sind.

Übersicht

┌─────────────────────────────────────────────────────────────────────┐
│                     Cloud Model Providers                           │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│   • Gemini (Google)    ⭐ Default    - Multimodal, large context    │
│   • OpenAI (GPT-5)    🔥 Popular    - Best ecosystem               │
│   • Anthropic (Claude) 🧠 Smart      - Best reasoning               │
│   • DeepSeek           💭 Thinking   - Chain-of-thought, cheap      │
│   • Groq               ⚡ Ultra-Fast  - Fastest inference           │
│                                                                     │
│   For local/offline models, see:                                    │
│   • Ollama     → ollama.md                                          │
│   • mistral.rs → mistralrs.md                                       │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Schnellvergleich

AnbieterAm besten fürGeschwindigkeitKostenHauptmerkmal
GeminiAllgemeine Nutzung⚡⚡⚡💰Multimodal, großer Kontext, Denken
OpenAIZuverlässigkeit⚡⚡💰💰Bestes Ökosystem
AnthropicKomplexes Schlussfolgern⚡⚡💰💰Am sichersten, am gründlichsten
DeepSeekGedankenkette⚡⚡💰Denkmodus, günstig
GroqGeschwindigkeitskritisch⚡⚡⚡⚡💰Schnellste Inferenz

Schritt 1: Installation

Fügen Sie die Anbieter hinzu, die Sie benötigen, zu Ihrem Cargo.toml:

[dependencies]
# Pick one or more providers:
adk-model = { version = "2.0.0", features = ["gemini"] }        # Google Gemini (default)
adk-model = { version = "2.0.0", features = ["openai"] }        # OpenAI GPT-5
adk-model = { version = "2.0.0", features = ["anthropic"] }     # Anthropic Claude
adk-model = { version = "2.0.0", features = ["deepseek"] }      # DeepSeek
adk-model = { version = "2.0.0", features = ["groq"] }          # Groq (ultra-fast)

# Or all cloud providers at once:
adk-model = { version = "2.0.0", features = ["all-providers"] }

Schritt 2: Legen Sie Ihren API-Schlüssel fest

export GOOGLE_API_KEY="your-key"      # Gemini
export OPENAI_API_KEY="your-key"      # OpenAI
export ANTHROPIC_API_KEY="your-key"   # Anthropic
export DEEPSEEK_API_KEY="your-key"    # DeepSeek
export GROQ_API_KEY="your-key"        # Groq

Schema-Normalisierung

Jeder Anbieter normalisiert automatisch MCP-Tool-Schemas zur Anforderungszeit. Sie müssen nichts tun — es funktioniert transparent. Aber hier ist, was unter der Haube passiert:

AnbieterSchema-AdapterVerhalten
GeminiGeminiSchemaAdapterAggressiv: löst $ref auf, reduziert Kombinatoren, entfernt nicht unterstützte Schlüsselwörter
OpenAI (strikt)OpenAiStrictSchemaAdapterBewahrt die Struktur, fügt additionalProperties: false hinzu
OpenAIOpenAiSchemaAdapterMinimale sichere Korrekturen
AnthropicAnthropicSchemaAdapterNahezu unverändert
DeepSeekGenericSchemaAdapterKonservative sichere Transformationen
OllamaGenericSchemaAdapterKonservative sichere Transformationen

Greife programmgesteuert über das Llm-Trait auf den Adapter zu:

use adk_core::{Llm, SchemaAdapter};

let adapter = model.schema_adapter();
let normalized = adapter.normalize_schema(raw_schema);

Siehe Schema Normalization für die vollständige Dokumentation.


Gemini (Google) ⭐ Standard

Am besten für: Allgemeine Zwecke, multimodale Aufgaben, große Dokumente

Wichtige Merkmale:

  • 🖼️ Natives Multimodal (Bilder, Video, Audio, PDF)
  • 📚 Bis zu 2M Token Kontextfenster
  • 🧠 Thinking-Modus: stufenbasiert (Gemini 3) und budgetbasiert (Gemini 2.5) mit Thought Signatures
  • 💰 Wettbewerbsfähige Preise
  • ⚡ Schnelle Inferenz

Vollständiges funktionsfähiges Beispiel

use adk_rust::prelude::*;
use adk_rust::Launcher;
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    dotenvy::dotenv().ok();
    
    let api_key = std::env::var("GOOGLE_API_KEY")?;
    let model = GeminiModel::new(&api_key, "gemini-2.5-flash")?;

    let agent = LlmAgentBuilder::new("gemini_assistant")
        .description("Gemini-powered assistant")
        .instruction("You are a helpful assistant powered by Google Gemini. Be concise.")
        .model(Arc::new(model))
        .build()?;

    Launcher::new(Arc::new(agent)).run().await?;
    Ok(())
}

Verfügbare Modelle

ModellBeschreibungKontext
gemini-3.1-pro-previewStärkste Schlussfolgerungsfähigkeit für komplexe agentische Workflows2 Mio. Tokens
gemini-3-flash-previewSchnell und effizient für Code und Agents1 Mio. Tokens
gemini-3.1-flash-lite-previewGünstigste, schnellste Weiterleitung und Aufgaben mit hohem Volumen1M tokens
gemini-2.5-proErweiterte Schlussfolgerung und multimodal1M tokens
gemini-2.5-flashAusgewogene Geschwindigkeit und Leistungsfähigkeit (empfohlen)1M tokens

Denkmodus

Gemini 3-Modelle unterstützen ein auf Ebenen basierendes Denken, während Gemini 2.5 ein auf Budget basierendes Denken verwendet. Wenn der Denkmodus mit Funktionsaufrufen verwendet wird, geben Gemini 2.5+- und 3.x-Modelle thoughtSignature-Werte zurück, die in späteren Turns zurückgesendet werden müssen, um den Reasoning-Kontext zu erhalten. ADK-Rust übernimmt dies automatisch — Signaturen werden serialisiert, wenn vorhanden, und ausgelassen, wenn None.

use adk_gemini::{Gemini, ThinkingLevel};

// Gemini 3: level-based thinking
let response = client.generate_content()
    .with_user_message("Solve this step by step")
    .with_thinking_level(ThinkingLevel::High)
    .with_thoughts_included(true)
    .execute().await?;

// Gemini 2.5: budget-based thinking
let response = client.generate_content()
    .with_user_message("Solve this step by step")
    .with_thinking_budget(2048)
    .with_thoughts_included(true)
    .execute().await?;

Beispielausgabe

👤 User: What's in this image? [uploads photo of a cat]

🤖 Gemini: I can see a fluffy orange tabby cat sitting on a windowsill. 
The cat appears to be looking outside, with sunlight illuminating its fur. 
It has green eyes and distinctive striped markings typical of tabby cats.

Am besten für: Produktions-Apps, zuverlässige Leistung, breite Funktionen

Wichtige Highlights:

  • 🏆 Industriestandard
  • 🔧 Hervorragendes Tool-/Funktionsaufrufen
  • 📖 Beste Dokumentation und Ökosystem
  • 🎯 Konsistente, vorhersagbare Ausgaben
  • 📋 Strukturierte Ausgabe mit JSON-Schema-Durchsetzung
  • 🧠 Kontrolle des Reasoning-Aufwands für o1/o3-Reasoning-Modelle
  • 🆕 Responses API — dedizierter Client für /v1/responses mit Reasoning-Zusammenfassungen, integrierten Tools und serverseitigem Zustand

Vollständiges funktionierendes Beispiel

use adk_rust::prelude::*;
use adk_rust::Launcher;
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    dotenvy::dotenv().ok();
    
    let api_key = std::env::var("OPENAI_API_KEY")?;
    let model = OpenAIClient::new(OpenAIConfig::new(&api_key, "gpt-5-mini"))?;

    let agent = LlmAgentBuilder::new("openai_assistant")
        .description("OpenAI-powered assistant")
        .instruction("You are a helpful assistant powered by OpenAI GPT-5. Be concise.")
        .model(Arc::new(model))
        .build()?;

    Launcher::new(Arc::new(agent)).run().await?;
    Ok(())
}

Strukturierte Ausgabe (JSON-Schema)

OpenAI unterstützt garantierte JSON-Ausgabe über output_schema. ADK-Rust bindet dies automatisch an das OpenAI-response_format-API an:

use adk_rust::prelude::*;
use serde_json::json;
use std::sync::Arc;

let model = OpenAIClient::new(OpenAIConfig::new(&api_key, "gpt-5-mini"))?;

let agent = LlmAgentBuilder::new("data_extractor")
    .model(Arc::new(model))
    .instruction("Extract person information from the text.")
    .output_schema(json!({
        "type": "object",
        "properties": {
            "name": { "type": "string" },
            "age": { "type": "number" },
            "email": { "type": "string" }
        },
        "required": ["name", "age"]
    }))
    .build()?;

// Response is guaranteed to be valid JSON matching the schema

Für den strikten Modus mit verschachtelten Objekten füge auf jeder Ebene additionalProperties: false hinzu:

.output_schema(json!({
    "type": "object",
    "properties": {
        "title": { "type": "string" },
        "metadata": {
            "type": "object",
            "properties": {
                "author": { "type": "string" },
                "tags": { "type": "array", "items": { "type": "string" } }
            },
            "required": ["author"],
            "additionalProperties": false  // Required for nested objects
        }
    },
    "required": ["title", "metadata"],
    "additionalProperties": false  // Auto-injected at root level
}))

Reasoning-Aufwand (o1, o3-Modelle)

Für OpenAI-Reasoning-Modelle kannst du steuern, wie viel Reasoning-Aufwand das Modell anwendet:

use adk_model::openai::{OpenAIClient, OpenAIConfig, ReasoningEffort};

let config = OpenAIConfig::new(&api_key, "o3-mini")
    .with_reasoning_effort(ReasoningEffort::High);
let model = OpenAIClient::new(config)?;

Verfügbare Stufen: Low, Medium, High. Höherer Aufwand führt zu gründlicherem Reasoning, allerdings auf Kosten von Latenz und Tokens.

OpenAI-kompatibler lokaler APIs

Verwende OpenAIConfig::compatible(), um eine Verbindung zu lokalen Servern herzustellen (Ollama, vLLM, LM Studio):

// Ollama exposes OpenAI-compatible API at /v1
let config = OpenAIConfig::compatible(
    "not-needed",                      // API key (ignored by Ollama)
    "http://localhost:11434/v1",       // Base URL
    "llama3.2"                         // Model name
);
let model = OpenAIClient::new(config)?;

Hinweis: Strukturierte Ausgabe (output_schema) erfordert Backend-Unterstützung. Native OpenAI unterstützt dies vollständig; lokale Server können nur eingeschränkte Unterstützung bieten.

Gemini über den OpenAI-kompatiblen Endpunkt

Gemini-Modelle sind über das OpenAI-Chat-Completions-Wire-Format unter https://generativelanguage.googleapis.com/v1beta/openai erreichbar. Verwende das OpenAICompatibleConfig::gemini(...)-Preset (unter dem openai-Feature) mit einem GEMINI_API_KEY, um Gemini über denselben OpenAI-kompatiblen Client auszuführen, den du für jeden anderen Anbieter verwendest:

use adk_model::openai_compatible::{OpenAICompatible, OpenAICompatibleConfig};

let api_key = std::env::var("GEMINI_API_KEY")?;
let model = OpenAICompatible::new(
    OpenAICompatibleConfig::gemini(api_key, "gemini-3.5-flash"),
)?;

Dieser Pfad unterstützt Chat, Streaming, Funktionsaufrufe, strukturierte Ausgabe und Reasoning-Aufwand (OpenAIs reasoning_effort ordnet sich den Gemini-Thinking- Stufen/Budgets zu). Gemini-spezifische Optionen — z. B. thinking_config mit include_thoughts oder cached_content — werden über die extensions["openai"]["extra_body"]["google"]-Map der Anfrage übergeben, die der Client unverändert in den Request-Body zusammenführt.

Wann dies statt GeminiModel verwenden: Für native Gemini-Funktionen (serverseitige Tools, die Interactions API, native ThinkingConfig, multimodal-first Ergonomie) verwende bevorzugt GeminiModel. Verwende das OpenAI-kompatible Preset, wenn du einen einzigen, einheitlichen Client über alle Anbieter hinweg möchtest.

Beispiele (erfordern GEMINI_API_KEY oder GOOGLE_API_KEY):

# Direct client: chat, reasoning effort, extra_body thinking, streaming,
# function calling, structured output.
cargo run -p adk-model --features openai --example gemini_openai_compat

# The same compat client driving a normal LlmAgent in a Runner.
# (Lives in adk-agent: it exercises the agent layer, which sits above adk-model.)
cargo run -p adk-agent --example gemini_openai_compat_agent

Reasoning-Aufwand (o1, o3-Modelle)

Steuere mit ReasoningEffort, wie viel Reasoning-Aufwand das Modell anwendet:

use adk_model::openai::{OpenAIClient, OpenAIConfig, ReasoningEffort};

let config = OpenAIConfig::new(&api_key, "o3-mini")
    .with_reasoning_effort(ReasoningEffort::High);
let model = OpenAIClient::new(config)?;

Verfügbare Stufen: Low (am schnellsten), Medium (ausgewogen), High (am gründlichsten).

Verfügbare Modelle

ModellBeschreibungKontext
gpt-5Hochmodernes einheitliches Modell mit adaptivem Denken256K tokens
gpt-5-miniEffiziente Version für die meisten Aufgaben (empfohlen)128K tokens
gpt-5-nanoRouting und Klassifizierung mit den niedrigsten Kosten128K Tokens
gpt-4.1Stabiles Produktionsmodell für ältere GPT-4.1-Bereitstellungen1 Mio. Tokens

Beispielausgabe

👤 User: Write a haiku about Rust programming

🤖 GPT-5: Memory so safe,
Ownership guards every byte—
Compiler, my friend.

Anthropic (Claude) 🧠 Intelligent

Am besten für: Komplexes Schlussfolgern, sicherheitskritische Anwendungen, lange Dokumente

Wichtige Highlights:

  • 🧠 Außergewöhnliche Schlussfolgerungsfähigkeit
  • 🛡️ Am stärksten auf Sicherheit ausgerichtet
  • 📚 200K Token Kontext
  • ✍️ Hervorragende Schreibqualität

Vollständiges funktionsfähiges Beispiel

use adk_rust::prelude::*;
use adk_rust::Launcher;
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    dotenvy::dotenv().ok();
    
    let api_key = std::env::var("ANTHROPIC_API_KEY")?;
    let model = AnthropicClient::new(AnthropicConfig::new(&api_key, "claude-sonnet-4-6"))?;

    let agent = LlmAgentBuilder::new("anthropic_assistant")
        .description("Anthropic-powered assistant")
        .instruction("You are a helpful assistant powered by Anthropic Claude. Be concise and thoughtful.")
        .model(Arc::new(model))
        .build()?;

    Launcher::new(Arc::new(agent)).run().await?;
    Ok(())
}

Verfügbare Modelle

ModellBeschreibungKontext
claude-opus-4-7Das leistungsfähigste GA-Modell, nur adaptives Denken1M tokens
claude-opus-4-6Früheres Flaggschiff für komplexe autonome Aufgaben1M tokens
claude-sonnet-4-6Ausgewogene Intelligenz und Kosten (empfohlen)1 Mio. Tokens
claude-haiku-4-5-20251001Ultrahocheffizient für Arbeitslasten mit hohem Volumen200K Tokens
claude-opus-4-20250514Hybrides Modell mit erweitertem Denken200K Tokens
claude-sonnet-4-20250514Ausgewogenes Modell mit erweitertem Denken1 Mio. Tokens

Beispielausgabe

👤 User: Explain quantum entanglement to a 10-year-old

🤖 Claude: Imagine you have two magic coins. When you flip them, they always 
land the same way - both heads or both tails - even if one coin is on Earth 
and the other is on the Moon! Scientists call this "entanglement." The coins 
are connected in a special way that we can't see, like invisible best friends 
who always make the same choice at the exact same time.

DeepSeek 💭 Denken

Am besten für: Komplexe Problemlösung, Mathematik, Programmierung, Schlussfolgerungsaufgaben

Wichtige Highlights:

  • 💭 Denkmodus - zeigt schrittweise Schlussfolgerungsprozesse
  • 💰 Sehr kosteneffektiv (10x günstiger als GPT-4)
  • 🔄 Kontext-Caching für wiederholte Präfixe
  • 🧮 Stark in Mathematik und Programmierung

Vollständiges funktionsfähiges Beispiel

use adk_rust::prelude::*;
use adk_rust::Launcher;
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    dotenvy::dotenv().ok();
    
    let api_key = std::env::var("DEEPSEEK_API_KEY")?;
    
    // Standard chat model
    let model = DeepSeekClient::chat(&api_key)?;
    
    // OR: Reasoning model with thinking mode
    // let model = DeepSeekClient::reasoner(&api_key)?;

    let agent = LlmAgentBuilder::new("deepseek_assistant")
        .description("DeepSeek-powered assistant")
        .instruction("You are a helpful assistant powered by DeepSeek. Be concise.")
        .model(Arc::new(model))
        .build()?;

    Launcher::new(Arc::new(agent)).run().await?;
    Ok(())
}

Verfügbare Modelle

ModellBeschreibungBesonderheit
deepseek-r1-0528Neuestes Reasoning-ModellErhöhte Denkentiefe
deepseek-r1Fortschrittliches ReasoningVergleichbar mit o1
deepseek-v3.1Neuestes 671B MoE ModellAllgemeine Aufgaben
deepseek-chat671B MoE Modell (V3)Allzweck, günstig
deepseek-vl2Vision-SprachmodellMultimodal

Beispielausgabe (Reasoner mit Denkmodus)

👤 User: What's 17 × 23?

🤖 DeepSeek: <thinking>
Let me break this down:
17 × 23 = 17 × (20 + 3)
       = 17 × 20 + 17 × 3
       = 340 + 51
       = 391
</thinking>

The answer is 391.

Groq ⚡ Ultrahohe Geschwindigkeit

Am besten für: Echtzeit-Anwendungen, Chatbots, zeitkritische Aufgaben

Wichtige Highlights:

  • Schnellste Inferenz - 10x schneller als die Konkurrenz
  • 🔧 LPU (Language Processing Unit)-Technologie
  • 💰 Wettbewerbsfähige Preise
  • 🦙 Führt LLaMA-, Mixtral- und Gemma-Modelle aus

Vollständiges funktionsfähiges Beispiel

use adk_rust::prelude::*;
use adk_rust::Launcher;
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    dotenvy::dotenv().ok();
    
    let api_key = std::env::var("GROQ_API_KEY")?;
    let model = GroqClient::llama70b(&api_key)?;

    let agent = LlmAgentBuilder::new("groq_assistant")
        .description("Groq-powered assistant")
        .instruction("You are a helpful assistant powered by Groq. Be concise and fast.")
        .model(Arc::new(model))
        .build()?;

    Launcher::new(Arc::new(agent)).run().await?;
    Ok(())
}

Verfügbare Modelle

ModellMethodeBeschreibung
llama-4-scoutGroqClient::new(GroqConfig::new(key, "llama-4-scout"))Llama 4 Scout (17Bx16E)
llama-3.2-90b-text-previewGroqClient::new(GroqConfig::new(key, "llama-3.2-90b-text-preview"))Großes Textmodell
llama-3.1-70b-versatileGroqClient::llama70b()Vielseitiges großes Modell
llama-3.1-8b-instantGroqClient::llama8b()Am schnellsten
mixtral-8x7b-32768GroqClient::mixtral()Gute Balance
Beliebiges ModellGroqClient::new(GroqConfig::new(key, "model"))Benutzerdefiniertes Modell

Beispielausgabe

👤 User: Quick! Name 5 programming languages

🤖 Groq (in 0.2 seconds): 
1. Rust
2. Python
3. JavaScript
4. Go
5. TypeScript

Anbieter wechseln

Alle Anbieter implementieren denselben Llm-Trait, daher ist der Wechsel einfach:

use adk_agent::LlmAgentBuilder;
use std::sync::Arc;

// Just change the model - everything else stays the same!
let model: Arc<dyn adk_core::Llm> = Arc::new(
    // Pick one:
    // GeminiModel::new(&api_key, "gemini-2.5-flash")?
    // OpenAIClient::new(OpenAIConfig::new(&api_key, "gpt-5-mini"))?
    // AnthropicClient::new(AnthropicConfig::new(&api_key, "claude-sonnet-4-6"))?
    // DeepSeekClient::chat(&api_key)?
    // GroqClient::llama70b(&api_key)?
);

let agent = LlmAgentBuilder::new("assistant")
    .instruction("You are a helpful assistant.")
    .model(model)
    .build()?;

Beispiele

Verwende cargo-adk, um anbieterspezifische Projekte mit validierten 0.8-Abhängigkeiten zu generieren:

cargo adk new gemini_agent --provider gemini
cargo adk new openai_agent --template openai
cargo adk new anthropic_agent --provider anthropic

Die generierten Projekte werden in CI von scripts/check-cargo-adk-templates.sh kompiliert. Die vollständige Beispielgalerie können Sie im in diese Website eingebetteten ADK-Rust Playground durchsuchen und ausführen.



Vorherige: ← Realtime Agents | Nächste: Ollama (Lokal) →

Was passiert mit Inhalten, die ein Anbieter nicht transportieren kann

Content kann mehr ausdrücken, als ein einzelnes Anbieter-Transportmittel akzeptiert, daher muss jeder Adapter entscheiden, was mit dem Rest geschehen soll. Diese Entscheidungen werden jetzt aufgezeichnet, statt unsichtbar angewendet. Jeder Teil wird klassifiziert:

DispositionBedeutung
ConvertedIm entsprechenden nativen Format an den Anbieter übergeben
DowngradedIn einer verlustbehafteteren Form übergeben — ein Dateiverweis, der als beschreibender Text dargestellt wird, den das Modell lesen, aber nicht abrufen kann
OmittedGar nicht mitgeführt

Downgrades und Auslassungen erzeugen beim Erfasstwerden eine tracing-Warnung, die den Teiltyp, den MIME-Typ und den Grund nennt, sodass keines von beiden stillschweigend bleibt.

Um das Ergebnis vor dem Absenden einer Anfrage zu sehen:

use adk_core::{Content, Part};
use adk_model::bedrock::convert::report_for_contents;

let content = Content {
    role: "user".to_string(),
    parts: vec![Part::inline_data("audio/wav", vec![0u8; 16])],
};
let report = report_for_contents(std::slice::from_ref(&content));

for omission in report.omitted_parts() {
    println!("{} was dropped: {}", omission.kind, omission.detail);
}

Um eine Anfrage abzulehnen, die das Modell unvollständig erreichen würde, statt eine Antwort über Material zu erhalten, das das Modell nie gesehen hat:

use adk_core::{Content, Part};
use adk_model::bedrock::convert::report_for_contents;

let content = Content {
    role: "user".to_string(),
    parts: vec![Part::inline_data("video/mp4", vec![0u8; 16])],
};

if let Some(error) = report_for_contents(std::slice::from_ref(&content)).into_error() {
    return Err(error);
}

into_error betrifft nur Auslassungen. Eine Downgrade erreicht das Modell dennoch, und ihn abzulehnen würde den dokumentierten textuellen Fallback verweigern.

Hinweis: Das Ledger ist per Konstruktion vollständig. Jeder Teil, der einen Adapter ohne ein erfasstes Schicksal verlässt — einschließlich eines, das durch eine zukünftige Änderung hinzugefügt wird — wird als Auslassung mit einem expliziten "no recorded reason" erfasst, und adk-model/tests/part_conversion_matrix_tests.rs schlägt dabei fehl.

Bedrock Converse Abdeckung

TeilAnordnung
Text, FunctionCall, FunctionResponse, DenkenConverted
InlineData mit JPEG, PNG, GIF, WebPConverted als ein Bildblock
InlineData mit einem unterstützten Dokumenttyp (PDF und ähnlichen)Converted als Dokumentblock
InlineData mit Audio, Video oder beliebigen BinärdatenOmitted
FileData für ein Bild oder unterstütztes DokumentDowngraded zu Text — Converse nimmt S3 URIs, nicht beliebige URLs
FileData für jeden anderen TypOmitted
ServerToolCall, ServerToolResponseOmitted — Gemini-spezifisch
EmbeddedResource-Text oder ein Blob eines unterstützten TypsConverted
EmbeddedResource Blob eines nicht unterstützten TypsOmitted