Lernpfad
Du schickst ein Bild an eine Vision-API und bittest sie, ein kleines Preisschild zu lesen. Die Antwort kommt selbstbewusst – und falsch. Gleiches Spiel beim Zählen von Objekten in einem unübersichtlichen Foto: Das Modell wirft einen Blick auf das Gesamtbild und rät eine Zahl, die deutlich danebenliegt.
Gemini 3 Flash geht anders vor. Mit aktivierter Codeausführung kann es mitten in der Antwort Python schreiben und ausführen, um Bilder zuzuschneiden, zu zoomen und zu annotieren, bevor es sich auf eine Antwort festlegt. Google nennt das Agentic Vision und berichtet von einem Qualitätsplus von 5–10 % bei Vision-Benchmarks.
Dieses Tutorial führt dich durch vier Beispiele mit steigender Schwierigkeit: Kleingedrucktes im Supermarktregal lesen, Getränkenamen von einer schwach beleuchteten Bar-Karte ziehen, verstreute Münzen zählen und Tabellendaten in ein Diagramm überführen.
Was ist Agentic Vision? Der "Think, Act, Observe"-Loop
Die Idee ist simpel. Mit aktivierter Codeausführung Gemini 3 kann die Antwort unterbrechen, in einer Sandbox Python schreiben und ausführen, sich ansehen, was der Code erzeugt hat, und dann entscheiden, wie es weitergeht.
Für Vision-Aufgaben heißt das meist: Bildbereiche ausschneiden, vergrößern, Bounding Boxes zeichnen oder den Kontrast anpassen, um Details sichtbar zu machen, die in der Originalauflösung untergehen.
Das läuft in einem Dreiphasen-Loop ab.

In der Phase Think schaut das Modell, was vorliegt (das Originalbild oder eine bereits zugeschnittene/annotierte Version) und plant den nächsten Schritt. Es könnte entscheiden, dass ein Preisschild zu klein ist und zugeschnitten sowie vergrößert werden muss.
Act setzt diesen Plan in Python um. Die Sandbox bringt 43 vorinstallierte Bibliotheken mit (PIL, OpenCV, matplotlib und mehr), sodass das Modell den nötigen Bildverarbeitungscode schreiben kann.
Nach der Codeausführung schließt Observe den Loop. Die Ausgaben (neue Bilder, Konsolentext, berechnete Werte) fließen zurück in den Kontext. Von dort beantwortet das Modell entweder oder startet in eine weitere Runde.
Ein einzelner API-Call kann diesen Loop mehrfach durchlaufen. In den folgenden Beispielen siehst du, wie in einer Anfrage sieben Regalbereiche zugeschnitten werden. In einem anderen extrahiert es Tabellendaten in ein pandas DataFrame und erzeugt ein Balkendiagramm – alles im selben Call.
Wenn dir das Agentic-Loop-Konzept neu ist: Der AI Agent Fundamentals Lernpfad von DataCamp beleuchtet es im Detail.
Grenzen und Einschränkungen
- Codeausführung und Custom Function Calling können nicht in derselben Anfrage genutzt werden.
- Laut Google-Dokumentation kann die Codeausführung die Performance bei nicht-visuellen Aufgaben verschlechtern. Aktiviere sie nur, wenn Bildmanipulation dem Ziel dient.
- Pixelgenaue Segmentierung (Masken, Konturen) gehört nicht zu Agentic Vision und bleibt bei Gemini 2.5.
- Das Modell überspringt manchmal die Codeausführung, wenn ein einzelner Blick genügt. Das ist Absicht, kein Bug.
Deine Umgebung für Agentic Vision einrichten
Hol dir einen API-Schlüssel von ai.google.dev und speichere ihn als GOOGLE_API_KEY in deiner Umgebung oder einer .env-Datei. Installiere anschließend das SDK und die Bildbibliotheken:
pip install google-genai python-dotenv Pillow matplotlib opencv-python
Starte mit dem Anlegen des Clients:
from google import genai
from google.genai import types
from dotenv import load_dotenv
load_dotenv()
client = genai.Client(
http_options=types.HttpOptions(timeout=600_000)
)
MODEL = "gemini-3-flash-preview"
Dieses timeout=600_000 ist wichtig. Agentic-Vision-Calls umfassen mehrere Runden Codegenerierung und -ausführung in der Sandbox; eine einzelne Anfrage kann rund vier Minuten dauern.
Das Standard-Timeout von httpx beendet die Verbindung deutlich früher – zurück bleibt ein stiller ReadTimeout ohne Hinweis, was passiert ist.
Als Nächstes richtest du die Agentic-Konfiguration ein:
agentic_config = types.GenerateContentConfig(
tools=[types.Tool(code_execution=types.ToolCodeExecution())],
thinking_config=types.ThinkingConfig(
thinking_level="HIGH",
include_thoughts=True
),
media_resolution=types.MediaResolution.MEDIA_RESOLUTION_HIGH,
)
tools ist der Einschalter für die Codeausführung. Er gibt dem Modell eine Python-Sandbox mit 43 Bibliotheken (numpy, pandas, PIL, matplotlib, OpenCV u. a.). Jeder Codeblock hat 30 Sekunden Laufzeit, die Sandbox versucht es bei Fehlern bis zu fünfmal erneut.
thinking_level="HIGH" gibt dem Modell mehr Raum zum Planen, bevor es Code schreibt. Für mehrstufige Vision-Aufgaben macht das spürbar etwas aus. Mit include_thoughts=True wird diese Überlegung in den Response-Parts sichtbar – hilfreich fürs Debugging.
media_resolution legt fest, wie viele Tokens das Eingabebild schon vor dem Loop bekommt. MEDIA_RESOLUTION_HIGH ist ein guter Standard. Für sehr dichte Bilder kannst du auf MEDIA_RESOLUTION_ULTRA_HIGH hochschalten oder auf MEDIA_RESOLUTION_LOW reduzieren, wenn Geschwindigkeit wichtiger ist als Detailtiefe.
Das Setup funktioniert mit geringfügigen Anpassungen auch auf Vertex AI. Für einen umfassenderen Überblick über die Gemini 3 API jenseits von Vision sieh dir das begleitende Tutorial an.
Agentic Vision in Gemini 3: Feine Details mit Zuschnitt und Zoom lesen
Das Bild zeigt ein deutsches Supermarktregal mit drei Produktreihen. An jeder Regalfront sind Preisschilder, und unten sitzt ein Hinweis „Liebe Kunden“. Wenn du selbst hineinzoomst, sind die Labels lesbar – aber im Gesamtbild so klein, dass ein Modell entscheiden muss, was es erkennen kann und was nicht.

Die mehrteilige Antwort auswerten
Agentic-Antworten sind keine einzelnen Textblöcke. Sie kommen als Liste von Parts: Überlegungen, vom Modell geschriebener Code, Ausführungsergebnisse, generierte Bilder und die finale Antwort. Dieser Helper geht sie durch:
def print_response(response, show_thoughts=False):
for part in response.candidates[0].content.parts:
if part.thought and show_thoughts:
print("[THINK]", part.text[:500])
elif part.executable_code:
print("[CODE]")
print(part.executable_code.code)
elif part.code_execution_result:
print(f"[RESULT] ({part.code_execution_result.outcome})")
print(part.code_execution_result.output)
elif part.inline_data:
print(f"[IMAGE] {part.inline_data.mime_type}, "
f"{len(part.inline_data.data):,} bytes")
elif part.text:
print("[ANSWER]", part.text)
Jedes Beispiel in diesem Tutorial nutzt die gleiche Funktion – definiere sie einmal und verwende sie wieder.
Lade nun das Regalbild und schreibe einen Prompt, der das Modell bittet, den Hinweis zu lesen und alle Produkte mit Preis aufzulisten.
from pathlib import Path
image_path = Path("images/grocery_shelf.jpg")
image_part = types.Part.from_bytes(
data=image_path.read_bytes(), mime_type="image/jpeg"
)
prompt = (
"Read the 'Liebe Kunden' sign at the bottom of the shelf. "
"What does it say? Also list all visible product names "
"and their prices from the shelf labels."
)
Führe es zunächst ohne Codeausführung aus:
standard_config = types.GenerateContentConfig(
media_resolution=types.MediaResolution.MEDIA_RESOLUTION_HIGH,
)
standard_response = client.models.generate_content(
model=MODEL,
contents=[image_part, prompt],
config=standard_config,
)
print_response(standard_response)
Hier ist eine gekürzte Ausgabe:
[ANSWER] Based on the image provided, here is the information requested:
### The 'Liebe Kunden' Sign
> "Dear Customers, unfortunately, we must inform you that due to
> increased demand, we cannot currently offer all products..."
### Product Names and Prices (from shelf labels)
**Top Row Labels:**
* Uncle Ben's Express Reis Mexi-Scharf 250g: 1,69
* Uncle Ben's Express Reis Griechisch 250g: 1,69
* Uncle Ben's Express Reis Curry 250g: 1,69
* Channa Masala 300g (partially obscured): 2,49
* (Label obscured): 2,49
* (Label obscured): 1,29
* (Label obscured): 0,99
...
**Second Row Labels:**
* Uncle Ben's Express Reis Chili con Carne 250g: 2,49
* Uncle Ben's Spitzen-Langkorn Reis 10 Min 500g: 1,79
* (Label obscured): 2,99
* (Label obscured): 2,79
...
Die Übersetzung des Hinweises passt, und das Modell liest die erkennbaren Uncle-Ben’s-Labels. Aber rund ein Drittel der Einträge ist „(Label obscured)“, und Marken wie Oryza, Reis-fit und Reiskugeln fehlen komplett.
Jetzt derselbe Prompt mit der Agentic-Konfiguration:
agentic_response = client.models.generate_content(
model=MODEL,
contents=[image_part, prompt],
config=agentic_config,
)
print_response(agentic_response, show_thoughts=True)
Die Struktur ist anders. Statt einer einzelnen [ANSWER]-Ausgabe läuft sie den kompletten Think/Act/Observe-Loop durch:
[THINK] Okay, so the primary goal here is twofold: First, I need to
decipher that "Liebe Kunden" sign down there. Then, I need to build a
comprehensive list of what's on this shelf...
[CODE]
import PIL.Image
img = PIL.Image.open('input_file_0.jpeg')
width, height = img.size
crops = [
{'box_2d': [630, 447, 887, 559], 'label': 'liebe_kunden_sign'},
{'box_2d': [80, 40, 240, 560], 'label': 'shelf1_left'},
{'box_2d': [190, 550, 310, 980], 'label': 'shelf1_right'},
{'box_2d': [400, 0, 480, 450], 'label': 'shelf2_left'},
{'box_2d': [410, 450, 480, 1000], 'label': 'shelf2_right'},
{'box_2d': [630, 130, 760, 460], 'label': 'shelf3_left'},
{'box_2d': [550, 600, 660, 990], 'label': 'shelf3_right'},
]
# ... crops and saves each region
[IMAGE] image/png, 135,953 bytes
[IMAGE] image/png, 90,395 bytes
[IMAGE] image/png, 125,816 bytes
[IMAGE] image/png, 102,288 bytes
[IMAGE] image/png, 173,606 bytes
[IMAGE] image/png, 283,263 bytes
[IMAGE] image/png, 100,522 bytes
Die sieben Zuschnitte, die das Modell erzeugt hat:


![]()




Nach der Beobachtung dieser Zuschnitte liefert das Modell eine vollständige Antwort:
[ANSWER]
**Top Shelf (Left to Right):**
* Uncle Ben's Express Reis Mexi. Scharf 250g: 1,69 €
* Channa Masala 285g: 2,49 €
* Madras Curry 285g: 2,49 €
* Steam Basmati Reis Kochbeutel 250g: 1,99 €
* Reiskugeln Pur 4x2 St: 1,99 €
...
**Middle Shelf (Left to Right):**
* Uncle Ben's Express Reis Chili con Carne 250g: 2,49 €
* Oryza Langkorn & Wildreis 500g Kochbeutel: 2,99 €
* Oryza Basmati & Wildreis 500g Kochbeutel: 2,79 €
* Oryza Jasmin Reis 500g Kochbeutel: 2,79 €
...
**Bottom Shelf (Left to Right):**
* Uncle Ben's Natur Reis 10-Min. Kochbeutel 1kg: 3,69 €
* Reis-fit 10 Minuten Natur-Reis 500g: 1,89 €
* Reis-fit Langkorn & Wildreis 500g: 1,89 €
...
Die vollständigen, ungekürzten Ausgaben beider Calls findest du in diesem Gist.
Die Agentic-Antwort liest 30+ Produkte über alle drei Regale. Die Oryza-, Reis-fit-, Madras-Curry-, Reiskugeln- und Steam-Basmati-Artikel, die Standard-Vision als „(obscured)“ markiert hatte, tauchen mit Namen und Preis auf.
Der Unterschied ist nicht Halluzination vs. Genauigkeit; Standard-Vision ist ehrlich damit, was es nicht lesen kann. Agentic Vision akzeptiert dieses Limit nicht und zoomt so lange, bis es geht.
Auch der Prompt spielt mit rein. „Liste alle sichtbaren Produktnamen und ihre Preise auf“ setzt eine Vollständigkeitslatte, die das Modell Richtung Zuschnitt schiebt.
Ein vagerer Prompt wie „Beschreibe dieses Bild“ würde vermutlich eine Single-Pass-Antwort liefern – selbst mit aktivierter Codeausführung –, weil das Modell keinen Grund sieht, weiterzugehen.
Lesen trotz wenig Licht und Verdeckungen
Dieses Bild zeigt eine brasilianische Bar-Karte in schummerigem Licht. Drei Glasscheiben listen Getränke in goldener Schrift. Pendelleuchten verdecken Teile der linken Tafel, die rechte ist am Bildrand kaum sichtbar, und Glasreflexe ziehen sich über die Oberfläche.

Der Prompt erwähnt weder Helligkeit noch Zuschnitt oder eine bestimmte Technik. Er fragt nur nach dem Inhalt:
image_path = Path("images/bar_menu.jpg")
image_part = types.Part.from_bytes(
data=image_path.read_bytes(), mime_type="image/jpeg"
)
prompt = (
"Read every drink listed on this menu board, including the ones "
"partially hidden behind the lamps and on the side panels. For "
"each drink, give me the name and beer style."
)
Standard-Vision liest die gut ausgeleuchtete mittlere Tafel problemlos und zieht acht Biere aus „FRUTADAS“ und vier aus „CHOPP“. Die linke Tafel kommt so zurück:
[ANSWER]
### Left Panel (Partially visible)
* **[Unreadable] LAGER** | [Style unreadable]
* **RED LAGER** | [Style unreadable]
* **[Unreadable] LAGER** | [Style unreadable]
* **[Unreadable]GER** | [Style unreadable]
* **HONKERS ALE** | [Style unreadable]
* **[Unreadable]SELLE** | [Style unreadable]
Sechs Einträge, die meisten mit unleserlichen Namen und alle ohne Stilangaben. Das Modell erkennt Text, kann ihn aber nicht entziffern.
Der Agentic-Call läuft in zwei Code-Runden. Zuerst schneidet er alle drei Tafeln aus:
[CODE]
middle_panel = [200, 320, 950, 780]
left_panel = [200, 0, 950, 260]
right_panel = [200, 840, 700, 1000]
# ... crops and saves each region

Nach der Beobachtung dieser Zuschnitte entscheidet das Modell, dass linke und rechte Tafel mehr Zoom brauchen. Es startet eine zweite Runde:
[CODE]
left_panel_top = [100, 0, 500, 250]
left_panel_bottom = [500, 0, 980, 250]
right_panel_top = [100, 800, 600, 1000]

Mit dem extra Zoom rekonstruiert das Modell Namen, die Standard-Vision als unleserlich markiert hatte: Amber Lager, Honkers Ale (Goose Island) und Demoiselle (Colorado) von der linken Tafel sowie Wals Dubbel, Tripel, Quadrupel und Petroleum von der rechten. Außerdem erkennt es die Überschrift links als „MISTURAS“ und rechts als „ALCOÓLICAS“.
Der Prompt sagte nie „Schneide die Tafeln zu“ oder „Zoome in die dunklen Bereiche“. Er fragte nach den Getränken und ihren Stilen – und das Modell arbeitete rückwärts von diesem Ziel.
Der Unterschied zum Supermarktregal ist die zweite Runde. Nach der ersten Crop-Runde schaute das Modell auf die Ergebnisse, entschied, dass links und rechts noch zu schwer zu lesen sind, und startete ohne Aufforderung engere Zuschnitte.
Der Loop hat sich selbst korrigiert.
Das ist der Vorteil, die Methode offenzulassen: Das Modell preprocesset nicht nur einmal, sondern iteriert, bis das Ergebnis dem im Prompt gesetzten Anspruch genügt.
Zählen und Annotieren mit Agentic Vision in Gemini 3
Bei der Bar-Karte hat es funktioniert, weil der Prompt die Methode offenließ und das Modell selbst entscheiden konnte. Das klappt nicht immer. Manchmal braucht das Modell klare Hinweise, welches Werkzeug es nutzen soll – das nächste Beispiel zeigt, wo diese Grenze liegt.
Das folgende Bild zeigt Münzen, die über einen Schreibtisch und eine schwarze Mappe verstreut sind. Einige überlappen, ein paar sind teilweise verdeckt, und durch das Gemisch aus Kupfer und Silber verliert man leicht den Überblick.

Ein naheliegender Ansatz ist, das Modell zu bitten, jede Münze zu annotieren, damit es anhand der eigenen Markierungen zählen kann. Laut Google-Dokumentation kann Agentic Vision mit PIL und OpenCV in der Sandbox Bounding Boxes und Labels direkt aufs Bild zeichnen. Also:
image_path = Path("images/coins.jpg")
image_part = types.Part.from_bytes(
data=image_path.read_bytes(), mime_type="image/jpeg"
)
prompt_v1 = (
"Count every coin in this image. Draw a bounding box or circle "
"around each one and number them. Check for overlapping or "
"partially hidden coins. Give me the final count."
)
response_v1 = client.models.generate_content(
model=MODEL,
contents=[image_part, prompt_v1],
config=agentic_config,
)
print_response(response_v1, show_thoughts=True)
Das Modell schneidet fünf Regionen zu, analysiert jede und liefert eine Zahl von 34. Aber schau dir das Antwortformat an:
[ANSWER] Final Count: 34 coins in total.
[
{"box_2d": [387, 175, 451, 236], "label": "1"},
{"box_2d": [356, 196, 407, 248], "label": "2"},
{"box_2d": [319, 231, 375, 274], "label": "3"},
...
]
Es gibt Bounding-Box-Koordinaten als JSON zurück, statt etwas aufs Bild zu zeichnen. Der Prompt sagte „draw“, das Modell hat das aber als Beschreibungsaufgabe verstanden und strukturierte Textausgabe geliefert.
Die Codeausführungs-Dokus deuten den Grund an: „Während das Modell das Zoomen für kleine Details automatisch handhabt, solltest du es für andere Aufgaben ausdrücklich anweisen, Code zu verwenden.“ Das Wort „draw“ ist mehrdeutig genug, dass das Modell den Textweg gewählt hat.
Wenn du die Aufgabe in Begriffen des gewünschten Codes formulierst, verschwindet die Mehrdeutigkeit:
prompt_v2 = (
"Count every coin in this image. Use Python to draw a numbered "
"bounding box on the image around each coin you find. Check for "
"overlapping or partially hidden coins. After annotating, give "
"me the final count."
)
response_v2 = client.models.generate_content(
model=MODEL,
contents=[image_part, prompt_v2],
config=agentic_config,
)
print_response(response_v2, show_thoughts=True)
Diesmal schreibt das Modell echten Zeichen-Code:
[CODE]
import PIL.Image
import PIL.ImageDraw
img = PIL.Image.open('input_file_0.jpeg')
width, height = img.size
coins = [
[383, 175, 452, 227], [352, 196, 411, 255], ... # 34 total
]
draw = PIL.ImageDraw.Draw(img)
for i, coin in enumerate(coins):
ymin, xmin, ymax, xmax = coin
left, top, right, bottom = (xmin*width/1000, ymin*height/1000,
xmax*width/1000, ymax*height/1000)
draw.rectangle([left, top, right, bottom], outline='red', width=3)
draw.text((left, top), str(i + 1), fill='red')
[RESULT] (Outcome.OUTCOME_OK)
Total coins detected: 34
[IMAGE] image/png, 3,685,043 bytes
[ANSWER] I have identified and counted a total of 34 coins.

Jede Münze bekommt einen roten Rahmen und eine Nummer. Die tatsächliche Zahl liegt bei 35 oder 36 – je nachdem, wie du zwei überlappende Münzen am unteren Bildrand wertest.
Das Modell landet bei 34 und verpasst eine oder zwei in diesem Cluster. Aber die Annotation dient als visuelles Notizbuch: Statt einer Zahl, die du glauben musst, bekommst du ein prüfbares Artefakt, das du Box für Box nachvollziehen kannst.
Die vollständigen, ungekürzten Ausgaben beider Calls findest du in diesem Gist.
Mehrschritt-Extraktion und Plotten
Die bisherigen Beispiele hatten je eine Hauptaufgabe (Text lesen, Objekte zählen). Hier werden mehrere verknüpft: Eine Tabelle aus einem Foto zuschneiden, die Zahlen in ein DataFrame extrahieren und ein Diagramm erzeugen. Das Bild zeigt eine IRS-ähnliche Steuertabelle, fotografiert auf einem Schreibtisch mit Taschenrechner.

Der Prompt beschreibt die komplette Pipeline in einem Rutsch:
image_path = Path("images/data_table.jpg")
image_part = types.Part.from_bytes(
data=image_path.read_bytes(), mime_type="image/jpeg"
)
prompt = (
"Crop and zoom into the table in this image. Extract the first "
"10 rows of data into a structured format. Identify the column "
"headers. Then create a bar chart comparing the values in the "
"numeric columns for those 10 rows. Summarize which row has the "
"highest and lowest values."
)
response = client.models.generate_content(
model=MODEL,
contents=[image_part, prompt],
config=agentic_config,
)
print_response(response, show_thoughts=True)
Das Modell benötigt vier Code-Runden vom Gesamtfoto bis zum fertigen Chart. Die ersten drei sind schrittweise Zooms: Es schneidet die „Single or Married Filing Separately“-Tabelle aus, dann die Spaltenüberschriften und dann die ersten 10 Datenzeilen und erzeugt dabei fünf Zwischenbilder. Hier ist der erste Zuschnitt, der die Tabelle isoliert:

In Runde vier hat es genug Details gelesen, um die Zahlen zu extrahieren. Es baut ein pandas DataFrame, druckt die Tabelle und erzeugt ein gruppiertes Balkendiagramm in einem einzigen Codeblock:
[CODE]
import matplotlib.pyplot as plt
import pandas as pd
data = [
{"Higher Paying Job Wage": "$0 - 9,999",
"$0 - 9,999": 0, "$10,000 - 19,999": 940,
"$20,000 - 29,999": 1020, "$30,000 - 39,999": 1020},
... # 10 rows total
]
df = pd.DataFrame(data)
df.set_index("Higher Paying Job Wage").plot(kind='bar', figsize=(12, 6))
plt.title('Tax Table: Single or Married Filing Separately')
plt.ylabel('Tax Amount')
plt.savefig('tax_bar_chart.png')
Die extrahierte Tabelle:
|
Higher Paying Job Wage |
$0 - 9,999 |
$10,000 - 19,999 |
$20,000 - 29,999 |
$30,000 - 39,999 |
|
$0 - 9,999 |
$0 |
$940 |
$1,020 |
$1,020 |
|
$10,000 - 19,999 |
$940 |
$1,540 |
$1,620 |
$2,020 |
|
$20,000 - 29,999 |
$1,020 |
$1,620 |
$2,100 |
$3,100 |
|
$30,000 - 39,999 |
$1,020 |
$2,020 |
$3,100 |
$4,100 |
|
$40,000 - 59,999 |
$1,870 |
$3,470 |
$4,550 |
$5,550 |
|
$60,000 - 79,999 |
$1,870 |
$3,470 |
$4,690 |
$5,890 |
|
$80,000 - 99,999 |
$2,000 |
$3,810 |
$5,090 |
$6,290 |
|
$100,000 - 124,999 |
$2,040 |
$3,840 |
$5,120 |
$6,320 |
|
$125,000 - 149,999 |
$2,040 |
$3,840 |
$5,120 |
$6,910 |
|
$150,000 - 174,999 |
$2,220 |
$4,830 |
$6,910 |
$8,910 |
Und das erzeugte Balkendiagramm:

Die vollständige, ungekürzte Ausgabe findest du in diesem Gist.
Ein einzelner API-Call hat ein strukturiertes DataFrame, eine Zusammenfassung mit identifizierten Max-/Min-Zeilen und ein publikationsreifes Balkendiagramm erzeugt. Der Prompt nannte vier Dinge (zuschneiden, extrahieren, plotten, zusammenfassen) – und das Modell behandelte sie als Pipeline, in der die Ausgabe eines Schritts in den nächsten einfließt.
Die früheren Beispiele nutzten den Loop, um eine einzelne Operation zu verfeinern (bessere Zuschnitte, bessere Annotationen). Hier siehst du, wie der Loop verschiedene Operationen verkettet, wobei jede auf dem Ergebnis der vorherigen Runde aufbaut.
Fazit
Agentic Vision macht aus einem einzelnen API-Call einen Feedback-Loop, in dem das Modell Code schreibt, die Ergebnisse sichtet und den nächsten Schritt entscheidet.
Das Supermarktregal zeigte das Grundmuster: Bereiche zuschneiden, die zu klein zum Lesen sind, und aus den vergrößerten Versionen antworten. Die Bar-Karte fügte eine zweite Dimension hinzu: Eine Crop-Runde reichte nicht, also zoomte das Modell eigenständig weiter in die Problemzonen.
Bei den Münzen verwandelte die Annotation eine Schätzung in ein überprüfbares Artefakt. Die Steuertabelle verknüpfte vier verschiedene Schritte (zuschneiden, extrahieren, berechnen, plotten) in einer einzigen Anfrage.
Jedes Beispiel verriet auch etwas über Prompting. Eine Vollständigkeitslatte („Liste alle Produkte auf“) trieb das Modell zur Gründlichkeit. Die Methode offen zu lassen, gab ihm die Wahl des Preprocessings.
Mehrdeutige Verben wie „draw“ führten es dagegen manchmal auf den falschen Pfad – „Use Python to draw“ hat das behoben.
Das Muster: Beschreibe, was du als Ergebnis willst, werde bei mehrdeutigen Aufgaben konkret zum Werkzeug – und lass den Loop den Rest erledigen.
Der gesamte Code aus diesem Tutorial läuft mit gemini-3-flash-preview und dem google-genai SDK. Wenn du tiefer einsteigen willst, deckt der DataCamp-Kurs Introduction to AI Agents das Loop-Muster hinter all dem ab.
Agentic Vision in Gemini 3: Häufige Fragen
What is agentic vision in Gemini 3 Flash?
Agentic Vision ist ein Feature, bei dem Gemini 3 Flash mitten in der Antwort Python-Code schreiben und ausführen kann, um Bilder zu manipulieren, bevor es antwortet. Es nutzt einen Think-Act-Observe-Loop, um Bilder in einer Sandbox zuzuschneiden, zu zoomen, zu annotieren und zu verbessern – alles in einem einzigen API-Call.
How do I enable agentic vision in the Gemini API?
Füge deiner GenerateContentConfig ein Codeausführungs-Tool hinzu: tools=[types.Tool(code_execution=types.ToolCodeExecution())]. Damit bekommt das Modell Zugang zu einer Python-Sandbox mit 43 vorinstallierten Bibliotheken, darunter PIL, OpenCV und matplotlib.
Why does the model skip code execution even when it is enabled?
Das Modell schreibt nur dann Code, wenn es entscheidet, dass ein einzelner Blick aufs Bild nicht reicht. Wenn es die Antwort in Originalauflösung sicher geben kann, überspringt es die Codeausführung. Das ist so vorgesehen und von Google dokumentiert.
What is the difference between "draw" and "Use Python to draw" in prompts?
„Draw“ ist mehrdeutig, und das Modell könnte Textbeschreibungen oder JSON-Koordinaten statt eines echten Bildes zurückgeben. Mit „Use Python to draw“ signalisierst du, dass ausführbarer Code ein visuelles Ergebnis erzeugen soll – so wird der Codepfad zuverlässig aktiviert.
Can I combine agentic vision with custom function calling?
Nein. Codeausführung und Custom Function Calling können nicht in derselben API-Anfrage kombiniert werden. Wenn dein Workflow beides braucht, musst du separate Calls machen.
Ich bin Content-Creator im Bereich Data Science mit über zwei Jahren Erfahrung und zähle zu den größten Stimmen auf Medium. Ich schreibe gern ausführliche Artikel über KI und ML – mit einer Prise Sarkasmus, damit das Ganze nicht zu trocken wird. Bisher habe ich über 130 Artikel veröffentlicht und einen DataCamp-Kurs produziert, ein weiterer ist in Arbeit. Meine Inhalte wurden von über 5 Millionen Menschen gelesen, 20.000 davon folgen mir auf Medium und LinkedIn.


