1. Einführung

Hier erfahren Sie, wie Sie eine multimodale Multi-Agenten-Engine erstellen, die auf Grundlage eines einfachen Themenbriefings ansprechende Social-Media-Assets erstellt. Mit dem Agent Development Kit (ADK) von Google und dem Agent2Agent-Protokoll (A2A) erstellen Sie autonome Mikro-Agents, verpacken Markenregeln als wiederverwendbare Agent-Fähigkeit, stellen einen Agent-Dienst in Cloud Run bereit und bewerten die generierten Key-Visuals auf Markenkonformität mit BigQuery-KI-Funktionen.
Aufgaben
In diesem Codelab lernen Sie, wie Sie die folgenden Aufgaben ausführen:
- Mehrere ADK-Agents mit einem deterministischen Graph-Workflow orchestrieren
- Verpacken Sie Markenrichtlinien als Agenten-Skill, der nur bei Bedarf geladen wird.
- Statten Sie einen Agenten mit einem Tool zur Bildgenerierung aus, das seine Ausgabe als Artefakt speichert.
- Einen Agenten als A2A-Dienst bereitstellen und ihn von einem anderen Agenten als Remote-Knoten aufrufen.
- Stellen Sie den Visual Director in Cloud Run bereit und rufen Sie den Workflow über A2A auf.
- Mit KI-Funktionen in BigQuery generierte Key-Visuals auf Markeneignung bewerten
Voraussetzungen
- Ein Webbrowser wie Chrome.
- Ein Google Cloud-Konto und ein Google Cloud-Projekt mit aktivierter Abrechnung.
2. Hinweis
Google Cloud-Projekt erstellen
- Wählen Sie in der Google Cloud Console auf der Seite der Projektauswahl ein Google Cloud-Projekt aus oder erstellen Sie eines.
- Die Abrechnung für das Cloud-Projekt muss aktiviert sein. So prüfen Sie, ob die Abrechnung für ein Projekt aktiviert ist.
Cloud Shell starten
Sie verwenden Google Cloud Shell, um den Code herunterzuladen, Einrichtungs-Scripts auszuführen und die Anwendung bereitzustellen.
- Öffnen Sie Google Cloud Shell in Ihrem Browser oder klicken Sie oben in der Google Cloud Console auf Cloud Shell aktivieren:
Klicken Sie auf Weiter, wenn zusätzliche Hinweise angezeigt werden.Warten Sie, bis sowohl das Terminal als auch der Editor vollständig geladen sind. Das kann ein paar Minuten dauern.https://shell.cloud.google.com/ - Konfigurieren Sie Ihre Google Cloud-Projekt-ID und ‑Region (z. B.
us-central1) in Ihrer Umgebung, indem Sie Folgendes in das Terminal einfügen (ersetzen Sieunddurch Ihre Werte):export PROJECT_ID="<YOUR_PROJECT_ID>" export REGION="<YOUR_REGION>" gcloud config set project $PROJECT_ID
Es sollte eine Meldung ähnlich der folgenden angezeigt werden:Your active configuration is: [cloudshell-####] Updated property [core/project] - Aktivieren Sie die erforderlichen Google Cloud APIs für Ihr Projekt:
gcloud services enable \ compute.googleapis.com \ cloudresourcemanager.googleapis.com \ aiplatform.googleapis.com \ storage.googleapis.com \ storage-component.googleapis.com \ bigqueryconnection.googleapis.com \ bigquery.googleapis.com \ run.googleapis.com \ secretmanager.googleapis.com \ cloudbuild.googleapis.com \ artifactregistry.googleapis.com \ iap.googleapis.com \ iam.googleapis.com
Repository klonen
Wir haben eine Codevorlage für den Einstieg in das Codelab. Es ist relativ klein, aber das GitHub-Repository, in dem es sich befindet, ist ziemlich groß. Um den Klonvorgang zu beschleunigen und Speicherplatz zu sparen, würden wir normalerweise git clone mit der Option --filter=blob:none und git sparse-checkout sowie einige weitere Befehle verwenden.
Das klingt sehr komplex, aber Antigravity kann das alles für uns erledigen.
Zuerst konfigurieren wir die Antigravity CLI, damit sie unser Problem direkt lösen kann, und starten sie.
Führen Sie in Cloud Shell den folgenden Befehl aus:
source <(curl -fsSL https://github.com/GoogleCloudPlatform/devrel-demos/raw/refs/heads/vladkol/cloud-shell-configure-agy/codelabs/labs-scripts/bwg-multi-agent-pitch-generator/cloud_shell_configure_agy.sh)
Mit dem Befehl wird die Antigravity CLI konfiguriert und im selben Terminal gestartet. Wenn Sie die Antigravity CLI beenden, kehren Sie zur Cloud Shell-Eingabeaufforderung zurück.

Wir benötigen nur den Ordner codelabs/bwg-multi-agent-pitch-generator im Repository. Wir bitten Antigravity, nur diesen Ordner herunterzuladen und ihn lokal in ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/ zu speichern.
Weisen Sie Antigravity CLI folgende Aufgabe zu:
Download files from under `https://github.com/GoogleCloudPlatform/devrel-demos/tree/main/codelabs/bwg-multi-agent-pitch-generator`
to folder `~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/`.
If `devrel-demos` folder already exists, rename it with a `.backup` suffix.

Antigravity führt die Aufgabe aus. Sie werden aufgefordert, Berechtigungen zum Ausführen einiger Befehle zu erteilen. Nachdem der Code heruntergeladen wurde, beenden Sie die Antigravity CLI mit dem Befehl /exit:
/exit

Repository-Arbeitsbereich öffnen
Öffnen wir nun den Code-Arbeitsbereich in Cloud Shell. Führen Sie diesen Befehl im Cloud Shell-Terminal aus:
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/
cloudshell workspace .
Setup-Script ausführen
Um die Einrichtung zu vereinfachen, führen Sie das Setupscript aus dem Repository aus. Es konfiguriert Umgebungsvariablen, installiert agents-cli, erstellt den Cloud Storage-Bucket für Artefakte, erstellt die Cloud-Ressourcenverbindung für BigQuery und gewährt dem zugehörigen Dienstkonto die erforderlichen IAM-Berechtigungen mit automatischer Wiederholung.
Das Setupscript ruft auch setenv.sh auf, ein kleines Hilfsprogramm, das die Variablen ableitet, die beide Agents benötigen: GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_REGION, GOOGLE_CLOUD_LOCATION und GOOGLE_GENAI_USE_VERTEXAI. Diese werden aus den oben exportierten PROJECT_ID und REGION abgeleitet. Außerdem werden diese beiden Werte in einer .env-Datei in Ihrem Basisverzeichnis gespeichert, damit Sie sie später wiederherstellen können.
- Machen Sie das Setupscript in Cloud Shell ausführbar und führen Sie es aus:
chmod +x codelab-setup.sh setenv.sh ./codelab-setup.sh - Die Ausführung dauert etwa eine Minute. Es sollte die folgende Erfolgsmeldung angezeigt werden: 🎉 🦄 Script execution complete.

- Das Setupscript wurde in einer eigenen Shell ausgeführt, sodass seine Variablen nicht in Ihrem Terminal verfügbar waren. Laden Sie sie in Ihre Sitzung:
Ihr Projekt, Ihre Region und Ihr Standort sollten angezeigt werden.source ./setenv.sh
3. KI-Agenten mit einem Diagramm-Workflow orchestrieren
In dieser Aufgabe erstellen Sie das Projekt für den Pitch-Generator und einen Graph-Workflow, in dem zwei Agents ausgeführt und ihre Ausgaben kombiniert werden.
Für einen Vorschlag ist ein Konzept erforderlich, d. h. die Idee und die Assets, mit denen das Konzept verkauft wird. In diesem Anwendungsfall entwerfen wir Agents mit unterschiedlichen Verantwortlichkeiten im Rahmen der Arbeit. So wird gezeigt, wie Sie komplexe Aufgaben entkoppeln und an verschiedene Agents mit unterschiedlichen Verantwortlichkeiten delegieren können, um sie einfacher zu verwalten.
Wenn diese Art von Arbeit zwischen Spezialisten aufgeteilt wird, muss koordiniert werden, wann jeder Agent ausgeführt wird. Sie können festlegen, dass Ihr Agent entscheidet, wann er die einzelnen Sub-Agents aufruft, oder einen deterministischeren Ansatz wählen. In diesem Codelab verwenden Sie einen deterministischen Ansatz mit einem Diagramm-Workflow.
Erstes Projekt für KI-Agenten erstellen
- Erstellen Sie das Projekt in Cloud Shell, indem Sie Folgendes in das Terminal einfügen:
Dadurch wird ein vollständiges, ausführbares Projekt geschrieben: ein Agent, eincd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator agents-cli create pitch-generator \ --agent adk \ --agent-directory pitch_generator \ --deployment-target cloud_run \ --session-type in_memory \ --cicd-runner skip \ --region <YOUR_REGION> \ --auto-approveDockerfile, Tests, Terraform für später und eine.env-Datei mit der zugehörigen.env.example-Vorlage. Für dieses Codelab sind zwei Teile wichtig:pitch_generator/agent.pyist der Agent und die Datei, die Sie neu schreiben.pitch_generator/ist der Paketname, der von--agent-directoryfestgelegt wird.
setenv.shexportiert haben. Hier ist also nichts zu konfigurieren. - Installieren Sie die Abhängigkeiten:
Hinweis:Das Gerüst verbindet das Projekt auch mit A2A, dem Protokoll, das später in diesem Codelab verwendet wird. Lassen Sie diese Dateien vorerst in Ruhe.cd pitch-generator agents-cli update -y && agents-cli install && uv sync --upgrade-package google-adk
Diagramm verstehen
ADK v2.x unterstützt Diagramm-Workflows. Ein Graph besteht aus Knoten, die die Arbeitseinheiten darstellen, und Kanten, die sie verbinden. Ein Knoten ist in der Regel ein KI-Agent, aber auch eine einfache Python-Funktion ist möglich. Eine Kante gibt an, dass nach Abschluss eines Knotens ein anderer ausgeführt wird.
Kanten werden als Liste geschrieben und die Reihenfolge wird von ADK festgelegt:
edges=[
("START", creative_director), ## the graph begins here
(creative_director, copywriter), ## then this
]
Durch die Verschachtelung erhält eine Kante ihre Bedeutung:
Edge | Bedeutung |
| Eine Kette: a, dann b, dann c, nacheinander |
| Ein Fan-Out: a, dann b und c gleichzeitig |
| Ein Fan-in. c wartet auf a und b. |
Für einen Fan-in verwenden Sie ein JoinNode, das auf alle Vorgänger wartet und deren Ausgaben gemeinsam weiterleitet.
In dieser Aufgabe erstellen wir den folgenden Workflow:

Pipeline erstellen
- Öffnen Sie die Agent-Datei, indem Sie Folgendes in das Terminal einfügen:
Der eingerüstetecd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/pitch-generator cloudshell edit pitch_generator/agent.pyagent.pywird im Cloud Shell-Editor angezeigt.💡 Tipp: Sie können den Code jederzeit auswählen und Gemini über das Glühbirnensymbol bitten, ihn zu erklären. Sie können auch die Antigravity CLI fragen.
- Ersetzen Sie die gesamte Datei in
pitch_generator/agent.pyim Editor durch Folgendes:import mimetypes import os from dotenv import load_dotenv from google.adk.agents import Agent from google.adk.agents.context import Context from google.adk.agents.remote_a2a_agent import ( AGENT_CARD_WELL_KNOWN_PATH, RemoteA2aAgent, ) from google.adk.apps import App from google.adk.events.event import Event from google.adk.models import Gemini from google.adk.workflow import JoinNode, Workflow from google.genai import types load_dotenv() MODEL = "gemini-3.8-flash" def _model() -> Gemini: return Gemini( model=MODEL, client_kwargs={"location": "global"}, retry_options=types.HttpRetryOptions(attempts=3), ) """ ⬇️ Configure visual-director RemoteA2aAgent agent below this comment """ creative_director = Agent( name="creative_director", model=_model(), description="Turns a raw idea into a campaign concept.", instruction=( "You are the Creative Director. Turn the idea you are given into ONE " "punchy campaign concept line with the rationale explanation behind it." ), output_key="creative_director", ) copywriter = Agent( name="copywriter", model=Gemini(model=MODEL, retry_options=types.HttpRetryOptions(attempts=3)), description="Writes social copy for a campaign concept.", instruction=( "You are the Copywriter. Write ONE short social caption for the " "campaign concept you are given. Under 25 words." ), ) """ Waits for every node wired into it, then hands their outputs on together.""" assemble = JoinNode(name="assemble") def package(node_input: dict): """Render the joined branches as the finished pitch. """ pitch = "\n\n".join( [ f"CONCEPT\n{node_input['creative_director']}", f"COPY\n{node_input['copywriter']}", ] ) """ The first event is what the user sees. The second is the node's output, which any downstream node would receive.""" yield Event(content=types.Content(role="model", parts=[types.Part(text=pitch)])) yield Event(output=pitch) """ we put creative_director before `assemble` so that we can gather the `Concept` output at assemble""" root_agent = Workflow( name="pitch_generator", edges=[ ("START", creative_director), (creative_director, copywriter), ((creative_director, copywriter), assemble), (assemble, package), ], ) app = App( root_agent=root_agent, name="pitch_generator", ) agents-clienthält eine integrierte Webentwicklungsoberfläche namensplaygroundzur Überprüfung, ähnlich wie das ADK. So starten Sie den Playground: Sie werden gefragt, ob Sie die Telemetrie aktivieren möchten. Geben Sieagents-cli playground --port 8080nein und drücken Sie die Eingabetaste.- Klicken Sie oben rechts im Terminal auf Webvorschau (das Augensymbol) und wählen Sie Vorschau auf Port 8080 aus.

- Die folgende Benutzeroberfläche wird angezeigt, über die Sie mit dem KI-Agenten chatten können. Versuchen Sie es mit dem Prompt „Fliegende Skateboards für Katzen“. Sie sehen eine Antwort wie unten dargestellt. Dort können Sie auch das vollständige Workflowdiagramm aufrufen.
Ansehen, wie diese Antwort erstellt wurde. Im Playground werden die einzelnen Schritte des Diagramms in der richtigen Reihenfolge angezeigt: creative_director, danncopywriter, dannassembleund dannpackage. Diese Sequenz ist das Diagramm, das Sie erstellt haben. So können Sie das Diagramm, das Sie gerade erstellt haben, schnell bestätigen. - Kehren Sie zum Terminal zurück und beenden Sie den laufenden
agents-cli playground-Prozess, indem Sie zweimal Strg+C drücken.
4. KI-Agenten eine Fähigkeit zuweisen
In dieser Aufgabe erstellen Sie einen zweiten Agenten und geben ihm eine Reihe von Markenrichtlinien, die als Skill verpackt sind.
Die Pipeline schreibt Wörter. Ein Bild braucht einen Stil: eine Palette, eine Art, Dinge zu beleuchten, Kompositionen, die Sie verwenden, und solche, die Sie nie verwenden. Das ist eine Seite mit Regeln und eine Seite mit Regeln muss besser verwaltet werden. Eine Möglichkeit besteht darin, sie als „Agent-Skill“ zu verpacken.
Ein Skill ist ein Ordner, der eine SKILL.md-Datei enthält. Die Struktur des Skill-Verzeichnisses sieht so aus wie im folgenden Beispiel (mit visual_director, dem nächsten Agenten, den Sie erstellen):
visual_director/
...
agent.py
skills/
brand-guidelines/
SKILL.md ## required: frontmatter + instructions
references/ ## optional: longer supporting documents
assets/ ## optional: templates, images, data
scripts/ ## optional: executable helpers
...
Der Einstiegspunkt des Agent-Skills ist die Datei SKILL.md, die einen YAML-Frontmatter-Abschnitt wie den unten gezeigten enthält:
---
name: brand-guidelines
description: The house brand rules for a key visual. Load this before writing art direction, so the visual looks like it came from this brand.
---
## Brand guidelines
Deep indigo and slate as the ground. One warm accent, amber or terracotta...
Das Label ist Frontmatter. Das ist alles, was der Agent im Voraus sieht. Deshalb muss in der Beschreibung angegeben werden, wann es sich lohnt, den Skill zu laden. Der body ist der Inhalt und bleibt außerhalb des Kontexts, bis der Agent load_skill aufruft.
Genau darum geht es. Der Prompt bleibt kurz, der Agent ruft die Regeln nur bei Bedarf ab und das Ändern des Stils bedeutet, dass nur eine Datei bearbeitet werden muss, anstatt einen Anweisungsstring zu durchsuchen.
Wir beginnen mit der Entwicklung des zweiten Agenten, visual-director, und nutzen dabei Agent-Skills, wie im folgenden Diagramm dargestellt:

Scaffold the Visual Director
Sie erstellen einen spezialisierten Agenten für die visuelle Komponente, visual-director. Es handelt sich um ein separates Projekt, da es später zu einem eigenen Dienst wird, um zu demonstrieren, wie mehrere Agents über das A2A-Protokoll miteinander kommunizieren. Sie haben dann zwei Projekte nebeneinander:
bwg-multi-agent-pitch-generator/
├── pitch-generator/ ## built in the last task
│ ├── pitch_generator/
│ │ ├── agent.py ## the graph you wrote
│ │ ├── app_utils/ ## generated, A2A wiring
│ │ └── fast_api_app.py ## generated, serves the agent
│ └── pyproject.toml
└── visual-director/ ## created below
└── ... ## the same shape again
- Erstellen Sie das Projekt und installieren Sie die zugehörigen Abhängigkeiten, indem Sie Folgendes in das Terminal einfügen:
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator agents-cli create visual-director \ --agent adk \ --agent-directory visual_director \ --deployment-target cloud_run \ --session-type in_memory \ --cicd-runner skip \ --region <YOUR_REGION> \ --auto-approve cd visual-director agents-cli update -y && agents-cli install && uv sync --upgrade-package google-adk
Markenrichtlinien schreiben
- Erstellen Sie den Skill-Ordner und öffnen Sie die Datei:
mkdir -p visual_director/skills/brand-guidelines cloudshell edit visual_director/skills/brand-guidelines/SKILL.md - Fügen Sie den folgenden Inhalt in die geöffnete Datei
SKILL.mdim Editor ein und speichern Sie sie:
--- name: brand-guidelines description: The house brand rules for a key visual — palette, light, composition, subject treatment, and what never appears. Load this before writing art direction or rendering an image, so the visual looks like it came from this brand rather than from a generic image model. --- ## Brand guidelines House style for campaign key visuals. Every rule here beats a preference in the brief. If the brief asks for something forbidden below, follow the brief for the subject and the guidelines for the treatment. ## Palette Deep indigo and slate as the ground. One warm accent — amber or terracotta — carrying the eye to the subject. Nothing neon, nothing fluorescent. At most three colors with any weight. A fourth reads as clutter. ## Light One dominant source, low and raking. Long shadows are wanted. Golden hour or a single hard studio key, never flat overhead light and never a ring light. Rim light is allowed on the subject only, and only to separate it from the ground. ## Composition Subject off-center, roughly a third in. Generous negative space on the opposite side — copy lands there later, so leave it genuinely empty. Eye level or slightly below. No top-down flat lays. No fisheye, no Dutch tilt. ## Subject One subject. If the idea implies a crowd, pick the one that carries it. Photographic realism with a shallow depth of field. Not illustration, not 3D render, not clay, not pixel art. ## Never - Text, logos, watermarks, or signage anywhere in the frame - Collage or split-screen layouts - Chrome, lens flare, bokeh sparkle - Cool-toned neon cyan or magenta ## Rendering the prompt When you turn art direction into an image prompt, state the palette, the light, and the composition explicitly. An image model will not infer them from the subject alone. Put the "Never" items in as plain description of what the frame does contain, not as negatives — image models handle a positive description far better than a list of prohibitions.
Passen Sie visual_director/agent.py an.
Aktualisieren Sie die Datei agent.py und konfigurieren Sie sie so, dass sie mit dem zuvor definierten Skill ausgestattet ist.
- Öffnen Sie die Agent-Datei:
cloudshell edit ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/visual-director/visual_director/agent.py - Ersetzen Sie den gesamten Inhalt der Datei
visual_director/agent.pydurch den folgenden Code: Derimport mimetypes from pathlib import Path from google import genai from google.adk.agents import Agent from google.adk.apps import App from google.adk.models import Gemini from google.adk.skills import load_skill_from_dir from google.adk.tools import ToolContext from google.adk.tools.skill_toolset import SkillToolset from google.genai import types MODEL = "gemini-3.8-flash" ## Configure the `brand-guidelines` skill for the agent BRAND_SKILL = load_skill_from_dir(Path(__file__).parent / "skills" / "brand-guidelines") ## Add definition of `generate_key_visual` tool below this comment root_agent = Agent( name="visual_director", model=Gemini( model=MODEL, client_kwargs={"location": "global"}, retry_options=types.HttpRetryOptions(attempts=3), ), description="Turns a campaign concept into art direction and a key visual.", instruction="""You are the Visual Director on a campaign pitch team. Call `load_skill` for `brand-guidelines` before you write anything. The house style is not optional and it is not in this prompt. You are given a campaign concept. Then, in order: 1. Write art direction for ONE key visual that sells it, obeying the brand guidelines: subject, composition, lighting, color, mood. Three or four sentences. 2. Call `generate_key_visual` with exactly that art direction. Your final reply is the art direction itself and nothing else. No preamble, no alternatives, no questions back. Do not mention the skill, the tool, or the image file — the image travels on its own.""", tools=[ SkillToolset(skills=[BRAND_SKILL]), ## Supply the `generate_key_visual` tool below this comment ], ) app = App( root_agent=root_agent, name="visual_director", )visual-director-Agent ist jetzt richtig mit einem Agent-Skill konfiguriert. Bevor Sie ihn testen, statten Sie diesen Agenten mit einem Tool zum Generieren von Bild-Assets aus.
5. Agenten mit einem Tool zur Bildgenerierung ausstatten
In dieser Aufgabe stellen Sie dem Visual Director ein Tool zur Verfügung, mit dem die Art Direction als Bild gerendert und als Artefakt gespeichert wird. Ein Artefakt ist ein benanntes, versioniertes Stück binärer Daten oder Dateiinhalte, das ein KI-Agent während einer Aufgabe erstellt, ändert oder verwendet.

Tool implementieren und dem Agenten hinzufügen
- Öffnen Sie die Agent-Datei:
cloudshell edit ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/visual-director/visual_director/agent.py - Kopieren Sie das folgende
generate_key_visual-Tool vor dieroot_agent-Definition:async def generate_key_visual(art_direction: str, tool_context: ToolContext) -> dict: """Render the art direction as the campaign's key visual. Args: art_direction: The art direction to render, in full. Returns: The saved artifact's filename, version, size and media type. """ IMAGE_MODEL = "gemini-3.1-flash-lite-image" response = await genai.Client(location="global").aio.models.generate_content( model=IMAGE_MODEL, contents=art_direction ) ## The image arrives as inline bytes on one of the response parts. image = next( ( part.inline_data for part in response.candidates[0].content.parts or [] if part.inline_data ), None, ) if image is None: raise ValueError(f"{IMAGE_MODEL} returned no image for: {art_direction[:120]}") filename = "key_visual" + ( mimetypes.guess_extension(image.mime_type or "") or ".bin" ) version = await tool_context.save_artifact(filename, types.Part(inline_data=image)) ## Return the artifact filename and version return { "filename": filename, "version": version, "bytes": len(image.data), "mime_type": image.mime_type, } - Fügen Sie
generate_key_visualunterSkillToolsetein, um den Agenten mit dem Tool auszustatten:tools=[ SkillToolset(skills=[BRAND_SKILL]), ## Supply the `generate_key_visual` tool below this comment generate_key_visual, ], agents-clienthält eine integrierte Webentwicklungsoberfläche namensplaygroundzur Überprüfung, ähnlich wie das ADK. So starten Sie den Playground:agents-cli playground --port 8080- Klicken Sie oben rechts im Terminal auf Webvorschau (das Augensymbol) und wählen Sie Vorschau auf Port 8080 aus.

- Die folgende Benutzeroberfläche wird angezeigt, über die Sie mit dem KI-Agenten chatten können. Versuchen Sie es mit dem Prompt „Neun Leben. Schwerelosigkeit.“
Anhand der Interaktionen können Sie sehen, wie der visual_director-Agentload_skill("brand-guidelines")ausführt, um die Markenrichtlinien zu lesen, und danngenerate_key_visualausführt, um mit dem Generieren des Bildes zu beginnen. Das resultierende Bild wird als Artefakt gespeichert, das auch in der Benutzeroberfläche angezeigt und einfach überprüft werden kann. - Kehren Sie zum Terminal zurück und beenden Sie den laufenden
agents-cli playground-Prozess, indem Sie zweimal Strg+C drücken.
6. Architektur mit mehreren Agenten mit A2A-Protokoll
In dieser Aufgabe machen Sie den Visual Director als Dienst verfügbar, der von anderen Agenten aufgerufen werden kann, und konfigurieren ihn so, dass er mit dem generierten Bild antwortet.
Agent2Agent (A2A) ist ein offenes Protokoll, mit dem ein Agent einen anderen über ein Netzwerk aufrufen kann. Das Herzstück ist die Agentenkarte, ein JSON-Dokument, das der Agent über eine bekannte URL veröffentlicht und in dem er seinen Namen, seine Beschreibung und seine Funktionen angibt. Ein Anrufer ruft die Karte ab und weiß, wie er mit dem Agenten dahinter sprechen muss, ohne dass Quellcode, Abhängigkeiten oder Sprache geteilt werden.

agents-cli hat dies bereits standardmäßig eingerichtet. Das Gerüst generiert visual_director/app_utils/a2a.py, das die Karte aus Ihrem Agent erstellt und die Routen einbindet, und visual_director/fast_api_app.py, das sie bereitstellt. Sie müssen nur eine kleine Änderung vornehmen, damit die Artefakte auch an den Client zurückgesendet werden.
Die Architektur sieht so aus: Der Agent ist noch nicht in unseren ursprünglichen Workflow eingebunden:

Das agents-cli-A2A-Servergerüst
Der folgende Code und das folgende Modul werden bereits bereitgestellt, wenn wir den visual-director-Agenten mit agents-cli initialisieren. Öffnen Sie diese Dateien, indem Sie die folgenden Befehle in das Terminal einfügen:
cloudshell edit visual_director/fast_api_app.py
cloudshell edit visual_director/app_utils/a2a.py
visual_director/fast_api_app.py startet den Agenten und hängt die A2A-Routen unter einem Pfad ein, der aus dem App-Namen erstellt wird:
await attach_a2a_routes(
app,
agent=root_agent,
runner=runner,
rpc_path=f"/a2a/{adk_app.name}", ## becomes /a2a/visual_director
)
visual_director/app_utils/a2a.py erledigt den Rest in drei Zügen.
Zuerst wird die Agentenkarte aus dem Agenten selbst erstellt. Der Name, die Beschreibung und jedes Tool werden zu Einträgen, die ein Anrufer lesen kann:
agent_card = await AgentCardBuilder(
agent=agent,
rpc_url=f"{resolved_app_url}{rpc_path}",
).build()
Zweitens wird ein Executor zwischen dem Protokoll und Ihrem Agent eingefügt. Eingehende A2A-Anfragen werden in ADK-Ausführungen übersetzt und die Ergebnisse werden zurückübersetzt:
request_handler = DefaultRequestHandler(
agent_executor=A2aAgentExecutor(runner=runner, force_new_version=True),
task_store=task_store,
agent_card=agent_card,
)
Drittens werden zwei Routen eingebunden: eine für die Bereitstellung der Karte und eine für die Annahme von Anrufen.
Route | Zweck |
| Die Karte. Anrufer lesen dies zuerst, um zu erfahren, was der Kundenservicemitarbeiter tun kann. |
| Der JSON-RPC-Endpunkt. Wohin die tatsächlichen Anfragen gehen |
Artefakte die Grenze überschreiten lassen
Standardmäßig enthält eine A2A-Antwort Text. Das Bild ist ein Artefakt und bleibt im Speicher des Bereitstellungs-Agents, sofern Sie es nicht so konfigurieren, dass es eingeschlossen wird.
- Öffnen Sie die generierte A2A-Datei:
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/visual-director cloudshell edit visual_director/app_utils/a2a.py - Suchen Sie den
AgentCardBuilder-Import und fügen Sie dieA2aAgentExecutorConfig- undinclude_artifacts_in_a2a_event_interceptor-Importe darunter ein:## ... ## from google.adk.a2a.utils.agent_card_builder import AgentCardBuilder ## Add the following two below `AgentCardBuilder` import from google.adk.a2a.executor.config import A2aAgentExecutorConfig from google.adk.a2a.executor.interceptors.include_artifacts_in_a2a_event import ( include_artifacts_in_a2a_event_interceptor, ) - Suchen Sie die Zeile
agent_executor=A2aAgentExecutor(runner=runner),und ersetzen Sie sie durch die folgende (fügen SieA2aAgentExecutorConfighinzu):agent_executor=A2aAgentExecutor( runner=runner, force_new_version=True, config=A2aAgentExecutorConfig( execute_interceptors=[include_artifacts_in_a2a_event_interceptor] ), ),
Dienst starten und veröffentlichte A2A-Karte lesen
- Starten Sie den Server im Hintergrund. Sie müssen
APP_URLdeklarieren, da dies die Adresse ist, die die Karte als ihre eigene bewirbt. Fügen Sie Folgendes in das Terminal ein:APP_URL=http://localhost:8801 nohup uv run uvicorn visual_director.fast_api_app:app --port 8801 > /tmp/visual-director.log 2>&1 & - Warten Sie einige Sekunden, bis der Dienst gestartet wurde, und prüfen Sie dann, ob er bereitgestellt wird:
Sie sollten Folgendes sehen:sleep 10 tail -2 /tmp/visual-director.logINFO: Application startup complete. INFO: Uvicorn running on http://127.0.0.1:8801 (Press CTRL+C to quit) - Lesen Sie die Karte, die der Agent jetzt veröffentlicht:
Auf der Karte werden der Name, die Beschreibung, die URL und die Fähigkeiten des Agenten aufgeführt, einschließlichcurl -s http://localhost:8801/a2a/visual_director/.well-known/agent-card.json | python3 -m json.toolgenerate_key_visual. Sie wird direkt aus der Agent-Definition im Code generiert. Sie können den{ "name": "visual_director", "description": "Turns a campaign concept into art direction and a key visual.", "skills": [ { "id": "visual_director", "name": "model", "tags": [ "llm" ] }, { "id": "visual_director-generate_key_visual", "name": "generate_key_visual", "description": "Render the art direction as the campaign's key visual.\n\nArgs:\n art_direction: The art direction to render, in full.\n\nReturns:\n The saved artifact's filename, version, size and media type.", "tags": [ "llm", "tools" ] } ], "preferredTransport": "JSONRPC", "protocolVersion": "0.3", "url": "http://localhost:8801/a2a/visual_director" }visual-director-Agenten jetzt in den Hauptworkflowpitch-generatoreinbetten.
7. A2A-Remote-Agent in den Workflow einbetten
In dieser Aufgabe fügen Sie den Remote-Agenten als dritten Zweig in das Diagramm ein.
Ein Remote-KI-Agent wird in RemoteA2aAgent eingeschlossen und wie jeder andere Knoten im Diagramm platziert. Die Kanten behalten ihre Form bei und der Koordinator weiß nicht, welche seiner Knoten lokal sind.
Koordinator auf den Dienst verweisen und den Diagramm-Workflow aktualisieren
- Öffnen Sie die Agent-Datei:
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/pitch-generator cloudshell edit pitch_generator/agent.py - Fügen Sie diese Importe oben in der Datei neben den vorhandenen hinzu:
import asyncio import subprocess import google.auth.transport.requests import google.oauth2.id_token import httpx from google.adk.a2a.converters.part_converter import convert_genai_part_to_a2a_part - Fügen Sie die folgende
RemoteA2aAgent-Definition über dercreative_director-Deklaration hinzu:VISUAL_DIRECTOR_URL = os.getenv("VISUAL_DIRECTOR_URL", "http://localhost:8801") ## For deployment on Cloud Run def _cloud_run_client() -> httpx.AsyncClient | None: """An httpx client that signs each request with a Cloud Run ID token. Cloud Run deploys private, so both the agent-card fetch and the A2A calls need one. """ if not VISUAL_DIRECTOR_URL.startswith("https://"): return None async def sign(request: httpx.Request) -> None: token = None try: token = await asyncio.to_thread( google.oauth2.id_token.fetch_id_token, google.auth.transport.requests.Request(), VISUAL_DIRECTOR_URL, ) except Exception: token = subprocess.check_output( ["gcloud", "auth", "print-identity-token", "-q"], stderr=subprocess.PIPE ).decode().strip() if not token: raise Exception("Failed to fetch ID token") request.headers["Authorization"] = f"Bearer {token}" return httpx.AsyncClient(event_hooks={"request": [sign]}, timeout=600) ## Keep the approval's tool traffic out of the A2A request def _pitch_parts_only(part: types.Part): """Sends the Visual Director text and media only. RemoteA2aAgent replays the session on every call, and the Visual Director runs downstream of the human approval, so the approval's function_response would travel alongside the concept text. An ADK server reads a function response as "resume the paused invocation" and rejects a message that also carries text, so drop the tool parts here. """ if part.function_call or part.function_response: return None return convert_genai_part_to_a2a_part(part) visual_director = RemoteA2aAgent( name="visual_director", description="Turns a campaign concept into art direction for one key visual.", agent_card=( f"{VISUAL_DIRECTOR_URL}/a2a/visual_director{AGENT_CARD_WELL_KNOWN_PATH}" ), httpx_client=_cloud_run_client(), genai_part_converter=_pitch_parts_only, ) - Überschreiben oder ersetzen Sie die Python-Funktion des
package-Knotens mit der folgenden Definition:async def package(ctx: Context, node_input: dict): """Render the joined branches as the finished pitch.""" empty = [name for name, value in node_input.items() if not value] if empty: raise ValueError(f"nothing reached the join from: {', '.join(empty)}") def _key_visual(ctx: Context) -> types.Blob | None: """The image the Visual Director sent back, or None if it sent none.""" for event in reversed(ctx.session.events): if event.author != "visual_director" or not event.content: continue for part in event.content.parts or []: if part.inline_data and part.inline_data.data: return part.inline_data return None image = _key_visual(ctx) if image is None: raise ValueError("the Visual Director returned art direction but no image") suffix = mimetypes.guess_extension(image.mime_type or "") or ".bin" filename = f"key_visual{suffix}" await ctx.save_artifact(filename, types.Part(inline_data=image)) pitch = "\n\n".join( [ f"CONCEPT\n{node_input['creative_director']}", f"COPY\n{node_input['copywriter']}", f"ART DIRECTION\n{node_input['visual_director']}", f"KEY VISUAL\n{filename}, {len(image.data)} bytes, {image.mime_type}", ] ) yield Event( content=types.Content( role="model", parts=[types.Part(text=pitch), types.Part(inline_data=image)], ) ) yield Event(output=pitch) - Fügen Sie vor der nachgelagerten Generierung ein Human Approval Gate ein. Definieren Sie in
pitch_generator/agent.pydie Genehmigungsknoten überroot_agent:@node(rerun_on_resume=False) async def approve_concept(ctx: Context): yield RequestInput( message="Please approve the campaign concept (yes/no).", response_schema=str ) @node(rerun_on_resume=True) async def user_approval(ctx: Context): user_response = await ctx.run_node(approve_concept) if str(user_response).lower() in ("yes", "y"): approved_concept = f"## Approved Concept\n\n{ctx.session.state['creative_director']}" yield Event( content=types.Content( role="model", parts=[types.Part(text=approved_concept)] ) ) else: raise ValueError("User rejected the concept") - Aktualisieren Sie schließlich die Importe oben, um
RequestInputundnodeausgoogle.adk.eventsundgoogle.adk.workfloweinzuschließen: und ändern Sie denfrom google.adk.events import Event, RequestInput from google.adk.workflow import JoinNode, Workflow, noderoot_agent-Workflowedgesso, dass er überuser_approvalweitergeleitet wird: Dabei sind einige Details zu beachten:edges=[ ("START", creative_director), (creative_director, user_approval, (copywriter, visual_director)), ((creative_director, copywriter, visual_director), assemble), (assemble, package), ],- Human-in-the-Loop-Genehmigung (HITL):
approve_conceptergibtRequestInput. Wenn der Workflow diesen Knoten erreicht, wird die Ausführung pausiert und eine Unterbrechung an den Aufrufer gesendet. Die nachgelagerten Zweige (copywriterundvisual_director) werden erst ausgeführt, wenn die Nutzergenehmigung bestätigt wurde. visual_directorwird an den Rändern genau wiecopywriterangezeigt, obwohl das eine ein Funktionsaufruf und das andere über ein Netzwerk erfolgt.- Das zurückgegebene Bild wird aus den Sitzungsereignissen und nicht aus
node_inputgelesen, da derzeit nur Text in die Ausgabe eines Knotens aufgenommen wird. Das Bild hat die Grenze über den A2A-Interceptor überschritten, ist aber an die Ereignisse des Remote-Agents angehängt. Die Hilfsfunktion_key_visualruft es daher von dort ab.
- Human-in-the-Loop-Genehmigung (HITL):
Integration testen
Als Nächstes testen Sie, ob der Visual Director (der im Hintergrund ausgeführt wird) und der Pitch Generator über das A2A-Protokoll kommunizieren können.
- Prüfen Sie, ob Visual Director weiterhin im Hintergrund ausgeführt wird:
Sie sollten hier das Ergebniscurl -s -o /dev/null -w "visual director: %{http_code}\n" http://localhost:8801/a2a/visual_director/.well-known/agent-card.jsonvisual director: 200erhalten.Wenn Sie einen anderen Status erhalten, führen Sie den folgenden Befehl aus, um den Dienst neu zu starten:fuser -k 8801/tcp 2>/dev/null || true cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/visual-director APP_URL=http://localhost:8801 nohup uv run uvicorn visual_director.fast_api_app:app --port 8801 > /tmp/visual-director.log 2>&1 & cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/pitch-generator sleep 10 curl -s -o /dev/null -w "visual director: %{http_code}\n" http://localhost:8801/a2a/visual_director/.well-known/agent-card.json - So starten Sie die Vorschau:
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/pitch-generator/pitch_generator agents-cli playground --port 8080 - Klicken Sie oben rechts im Terminal auf Webvorschau (das Augensymbol) und wählen Sie Vorschau auf Port 8080 aus.

- Die Oberfläche für den Chat mit dem Kundenserviceteam wird angezeigt. Senden Sie den Prompt „Flying skateboards for cats“.

Sie sehen die vollständige Interaktion, in der der Workflow gestartet und jeder Agent ausgeführt wird. Nachdem creative_directordas Konzept entworfen hat, wird der Workflow am Genehmigungstor angehalten und Sie werden aufgefordert, Folgendes zu bestätigen: „Bitte genehmigen Sie das Kampagnenkonzept (ja/nein).“ Geben Sie yes in das Eingabefeld ein, um fortzufahren. Nach der Genehmigung wird der Graph aufgefächert: Sie sehen, wann dervisual-director-Agent mit dem Laden des Skill beginnt. In der Mitte der Bildgenerierung beendet dercopywriter-Agent die Generierung der Social-Media-Bildunterschrift. Das zeigt, dass beide Agents parallel ausgeführt werden, ohne aufeinander zu warten. Wenn beide Vorgänge abgeschlossen sind, werden die Ergebnisse vom Knotenassemblemit dem genehmigten Konzept zusammengeführt, das voncreative_directorgeneriert wurde. So wird die Bereitstellung der Präsentationsinhalte in der Funktionpackageabgeschlossen.
8. Schlüsselbilder in Cloud Storage speichern
Bisher waren alle Key Visuals nur im Arbeitsspeicher verfügbar. Sobald der Prozess beendet ist, ist das Bild verschwunden. Das ist für einen Playground in Ordnung, aber für eine Kampagne unbrauchbar. In dieser Aufgabe weisen Sie dem Workflow einen Bucket zum Schreiben zu und erstellen ein BigQuery-Dataset, das Sie in der letzten Aufgabe verwenden.
Das ADK entscheidet beim Start, wohin Artefakte gesendet werden. Der generierte app_utils/services.py liest eine einzelne Umgebungsvariable:
def get_artifact_service():
"""Process-wide artifact service: GCS when a bucket is set, else in-memory."""
if bucket := os.environ.get("LOGS_BUCKET_NAME"):
return GcsArtifactService(bucket_name=bucket)
return InMemoryArtifactService()
Wenn Sie LOGS_BUCKET_NAME festlegen, wird jeder save_artifact-Aufruf stattdessen in Cloud Storage gespeichert.

BigQuery-Dataset erstellen
- Führen Sie in Cloud Shell den folgenden Befehl aus, um ein BigQuery-Dataset zu erstellen:
bq mk --dataset --location=<YOUR_REGION> --project_id=<YOUR_PROJECT_ID> bwg - Weisen Sie den Artifact-Speicher des Koordinators dem Bucket zu:
export LOGS_BUCKET_NAME="<YOUR_PROJECT_ID>-bwg"GcsArtifactServiceakzeptiert einen einfachen Bucket-Namen ohne das Präfixgs://. Wie die anderen Variablen befindet sich diese in Ihrer Shell und die Bereitstellungsaufgabe übergibt sie an Cloud Run. - Prüfen Sie den Inhalt Ihres Buckets. Öffnen Sie in einem neuen Browsertab die folgende URL:
Klicken Sie auf den Bucket. Je nach Ihren bisherigen Tests kann es bereits generierte Bilder enthalten.https://console.cloud.google.com/storage/browser?project=<YOUR_PROJECT_ID>
9. Visual Director-Agent in Cloud Run bereitstellen
Bisher lief alles auf einer Maschine, wobei der Visual Director unter localhost:8801 erreichbar war. In dieser Aufgabe stellen Sie den Visual Director-Agenten als eigenen Cloud Run-Dienst bereit und lassen den Pitch-Generator über das Netzwerk mit ihm kommunizieren. Dazu wird das Agent2Agent-Protokoll (A2A) verwendet.
Der Visual Director erhält eine echte https://-URL. Das _cloud_run_client, das Sie zuvor geschrieben haben, beginnt also, Anfragen zu signieren, anstatt None zurückzugeben. Außerdem werden Cloud Run-Bereitstellungen standardmäßig als privat festgelegt.

Visual Director bereitstellen
- Beenden Sie den lokalen Hintergrunddienst und den Playground, falls sie noch ausgeführt werden:
fuser -k 8801/tcp 2>/dev/null || true fuser -k 8000/tcp 2>/dev/null || true - Agent bereitstellen. Dadurch wird ein Container erstellt und übertragen.⏰ Das dauert einige Minuten.
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/visual-director source .env agents-cli deploy \ --service-name visual-director \ --project <YOUR_PROJECT_ID> \ --region <YOUR_REGION> \ --no-confirm-project \ --labels dev-tutorial=bwg001-devlab-1 \ --update-env-vars "LOGS_BUCKET_NAME=$LOGS_BUCKET_NAME,GOOGLE_GENAI_USE_VERTEXAI=true,GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT,GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION,GOOGLE_CLOUD_REGION=$GOOGLE_CLOUD_REGION"
Pitch Generator ausführen, der den in Cloud Run bereitgestellten Visual Director verwendet
- Lesen Sie die URL des Visual Director und führen Sie den Pitch Generator aus, der sie verwendet:
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/pitch-generator source .env export VISUAL_DIRECTOR_URL=$(gcloud run services list \ --project <YOUR_PROJECT_ID> \ --region <YOUR_REGION> \ --flatten='spec.template.spec.containers[0].env' \ --filter='metadata.name=visual-director AND spec.template.spec.containers[0].env.name=APP_URL' \ --format='value(spec.template.spec.containers[0].env.value)') echo "Visual Director is at $VISUAL_DIRECTOR_URL" APP_URL=http://localhost:8000 nohup uv run uvicorn pitch_generator.fast_api_app:app --port 8000 > /tmp/visual-pitch_generator.log 2>&1 &
Bereitgestellten Workflow aufrufen
Beide Agenten unterstützen das A2A-Protokoll. Das Repository enthält einen kleinen Client zum Aufrufen von Pitch Generator über A2A.
PITCH_GENERATOR_URL muss auf die URL des Pitch-Generators festgelegt werden, der lokal ausgeführt wird. In der Zwischenzeit wird der Visual Director in Cloud Run ausgeführt und der Pitch Generator kommuniziert über A2A mit ihm.
- Kopieren Sie den Client in Ihr Projekt und führen Sie ihn aus:
Da der Workflow ein Human Approval Gate enthält, wird das Skript nach dem Generieren des Konzeptentwurfs angehalten:cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/pitch-generator cp ../solution/pitch-generator/call_agent.py . PITCH_GENERATOR_URL=http://localhost:8000 uv run python call_agent.py "Flying skateboards for cats" --save-image ./key_visual.png Geben Sie=== HUMAN APPROVAL REQUIRED === [DRAFT CONCEPT] Concept Line: "Gravity is a Suggestion." ... Please approve the campaign concept (yes/no):yesein und drücken Sie die Eingabetaste, um den Workflow zu genehmigen und fortzusetzen. Sie können auch-yoder--auto-approveübergeben, um die Genehmigung automatisch zu erteilen. - Öffnen Sie
call_agent.pyund sehen Sie sich an, wie es mit dem KI-Agenten interagiert, indem Siea2a-sdkverwenden:ClientFactoryerstellt eine offizielle A2A-Clientfürhttps://SERVICE_URL/a2a/pitch_generator.generate_pitch_asyncsendet eine ersteSendMessageRequest. Wenn die Antwort mitTaskState.TASK_STATE_INPUT_REQUIREDzurückgegeben wird, wird der Teiladk_request_inputerkannt, das Konzeptentwurf angezeigt, Ihre Genehmigung eingeholt und eine Anfrage zum Fortsetzen mit Ihrer Antwort zurück an die Aufgabe gesendet.- In der Parsing-Schleife werden die Abschnitte
CONCEPT,COPYundART DIRECTIONaus den Artefakten der abgeschlossenen Aufgabe gelesen und das binäre Bild wird inkey_visual.pnggespeichert.
key_visual.pnggespeichert werden. - Laden Sie das Key-Visual in Ihren Bucket hoch. Verwenden Sie dabei ein Präfix, auf das Sie in BigQuery verweisen können:
gcloud storage cp ./key_visual.png gs://<YOUR_PROJECT_ID>-bwg/key-visuals/cats.png - Generieren Sie einen zweiten Vorschlag, damit Sie etwas zum Vergleichen haben, und laden Sie ihn ebenfalls hoch:
PITCH_GENERATOR_URL=http://localhost:8000 uv run python call_agent.py "A commuter bike built for rainy cities" --save-image ./bike.png gcloud storage cp ./bike.png gs://<YOUR_PROJECT_ID>-bwg/key-visuals/bike.png
10. Schlüsselbilder in BigQuery auf Markenkonformität bewerten
Sie haben jetzt Bilder in einem Bucket und die Markenrichtlinien, die sie prägen sollen. In dieser Aufgabe führen Sie die beiden zusammen: Sie verweisen auf die Bilder aus BigQuery und bitten dann ein Gemini-Modell, jedes Bild anhand der Richtlinien zu bewerten, ohne dass ein einziges Byte aus Cloud Storage verschoben wird.
Dafür sind zwei BigQuery-Funktionen zuständig:
ObjectRefist ein Wert, der auf ein Cloud Storage-Objekt verweist.OBJ.MAKE_REFerstellt eine aus einem URI und einer Verbindung, die BigQuery delegierten Zugriff auf den Bucket gewährt. Diepitch-connection, die vom Setupscript erstellt wird, ist diese Verbindung und enthält bereits „Storage Object Viewer“ und „Agent Platform User“.AI.SCOREnimmt einen Prompt entgegen und gibt einenFLOAT64zurück. Im Prompt können Strings mitObjectRef-Werten kombiniert werden, sodass das Modell sowohl Ihre Rubrik als auch das Bild sieht.

Tabelle mit wichtigen visuellen Elementen erstellen
- Öffnen Sie BigQuery Studio in einem neuen Browsertab:
https://console.cloud.google.com/bigquery?project=<YOUR_PROJECT_ID> - Klicken Sie auf Neue Abfrage erstellen (das Symbol +), fügen Sie die folgende Abfrage ein und klicken Sie auf Ausführen. Ersetzen Sie dabei
unddurch Ihre Projekt-ID und Region. Für jedes Schlüsselbild wird eine Zeile erstellt, in der das Kampagnenkonzept mit einem Verweis auf das Bild kombiniert wird:SET @@location = '<YOUR_REGION>'; CREATE OR REPLACE TABLE bwg.key_visuals AS SELECT campaign, concept, OBJ.FETCH_METADATA( OBJ.MAKE_REF(uri, '<YOUR_REGION>.pitch-connection') ) AS key_visual FROM UNNEST([ STRUCT( 'cats' AS campaign, 'Flying skateboards for cats' AS concept, 'gs://<YOUR_PROJECT_ID>-bwg/key-visuals/cats.png' AS uri ), STRUCT( 'bike', 'A commuter bike built for rainy cities', 'gs://<YOUR_PROJECT_ID>-bwg/key-visuals/bike.png' ) ]);
OBJ.MAKE_REFerstellt den Verweis aus dem URI und der Verbindung.OBJ.FETCH_METADATAkontaktiert dann Cloud Storage und füllt die Größe, den Inhaltstyp und die Generation des Objekts aus. Dieser zweite Aufruf ist auch der schnellste Weg, um zu prüfen, ob die Verbindung funktioniert: Wenn die Berechtigungen falsch sind, enthält das Felddetailsden Fehler anstelle der Metadaten. - Sehen Sie sich an, was Sie gespeichert haben. Ersetzen Sie die vorherige Abfrage durch diese und führen Sie sie aus:
Die Tabelle enthält einen Zeiger und seine Metadaten, nicht das Bild. Die Bytes haben den Bucket nie verlassen.SELECT campaign, concept, key_visual.uri, key_visual.details FROM bwg.key_visuals;
Bewerten Sie jedes Bild anhand der Markenrichtlinien.
Der Visual Director wurde angewiesen, sich an eine Farbpalette, eine Beleuchtungsregel und eine Kompositionsregel zu halten. Ob das tatsächlich der Fall war, ist eine Ermessensfrage, und genau dafür ist AI.SCORE da.
- Führen Sie die folgende Abfrage aus und ersetzen Sie
durch Ihre Region. Der Prompt ist ein Tupel: Ihre Richtlinie, das Kampagnenkonzept und dieObjectReffür das Bild:SELECT campaign, concept, AI.SCORE( ('''You are the brand guardian reviewing a campaign key visual. Score the attached image from 1 to 10 on how closely it follows these house rules: - Palette: deep indigo and slate, with one warm accent of amber or terracotta. Nothing neon. - Light: one dominant low, raking source with long shadows. No flat overhead light. - Composition: subject off-center with generous empty negative space on the opposite side. - Subject: one subject only, photographic realism, shallow depth of field. - Never: text, logos, or watermarks anywhere in the frame. A 10 obeys every rule. A 1 ignores them. The campaign concept is: ''', concept, key_visual), connection_id => '<YOUR_REGION>.pitch-connection', endpoint => 'gemini-3.5-flash' ) AS brand_fit FROM bwg.key_visuals ORDER BY brand_fit DESC; - Wandeln Sie die Punktzahl in ein Urteil um, auf das Ihr Team reagieren kann:
CREATE OR REPLACE TABLE bwg.brand_review AS SELECT campaign, concept, brand_fit, IF(brand_fit >= 7, 'on brand', 'needs another pass') AS verdict FROM ( SELECT campaign, concept, AI.SCORE( ('''Score this campaign key visual from 1 to 10 on how closely it follows the house brand rules: deep indigo and slate palette with a single warm accent and nothing neon; one low raking light source with long shadows; the subject off-center with empty negative space opposite; a single photographic subject; and no text, logos, or watermarks in the frame. The campaign concept is: ''', concept, key_visual), connection_id => '<YOUR_REGION>.pitch-connection', endpoint => 'gemini-3.5-flash' ) AS brand_fit FROM bwg.key_visuals ); SELECT * FROM bwg.brand_review ORDER BY brand_fit DESC;AI.SCOREgibt nurFLOAT64zurück. Der Grenzwert befindet sich also in einfachem SQL und kann angepasst werden, ohne dass der Prompt geändert werden muss. Die Bewertung erfolgt pro Zeile. Das bedeutet, dass dasselbe Bewertungsschema auf jedes Asset angewendet wird, das in einer Kampagne erstellt wird, nicht nur auf die beiden, die Sie hier generiert haben.
11. Nächste Schritte
Bewertungen erstellen
Agentische Tests oder „Evals“ sind automatisierte Tests, mit denen gemessen wird, wie gut autonome KI-Agenten Schlussfolgerungen ziehen, planen, Tools verwenden und mehrstufige Workflows ausführen. Sie ähneln Unittests für Agents, berücksichtigen aber deren nicht deterministische Natur.
Einer unserer KI-Agents enthält ein Human in the loop, was bedeutet, dass er auf eine Eingabe wartet. Sie müssen Antigravity erlauben, Änderungen am aktuellen Code vorzunehmen, damit dieses Verhalten die automatischen Auswertungen nicht beeinträchtigt.
Eine der besten Möglichkeiten, um loszulegen, ist, Antigravity CLI zu fragen.
Geben Sie Folgendes in die Cloud Shell ein, um die CLI zu starten:
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/
agy
Hier ist ein Beispiel für einen Startprompt:
Explore this repository (`pitch-generator` and `visual-director`), including their agent instructions, tools, and `SKILL.md` files. Design and implement a creative `agents-cli eval` evaluation suite under `tests/eval/` that stress-tests the agent's behavior.
Ein Beispiel für Bewertungen und eine Anleitung zum Ausführen von Bewertungen finden Sie auch im geklonten Repository.
12. Bereinigen
Damit Ihrem Google Cloud-Konto die in diesem Codelab verwendeten Ressourcen nicht in Rechnung gestellt werden, löschen Sie entweder das Projekt (empfohlen) oder die einzelnen Ressourcen, die während des Codelabs erstellt wurden:
gcloud run services delete visual-director --region=<YOUR_REGION> --project=<YOUR_PROJECT_ID> --quiet
bq rm -r -f -d <YOUR_PROJECT_ID>:bwg
bq rm --connection --location=<YOUR_REGION> --project_id=<YOUR_PROJECT_ID> pitch-connection
gcloud storage rm -r gs://<YOUR_PROJECT_ID>-bwg
13. Glückwunsch!
In diesem Codelab haben Sie mit dem Agent Development Kit einen Generator für Kampagnen-Pitches mit mehreren Agenten erstellt. Sie haben drei KI-Agenten in einen deterministischen Diagramm-Workflow eingebunden, Markenrichtlinien als Agent-Skill verpackt, der bei Bedarf geladen wird, und einem KI-Agenten ein Tool zur Bildgenerierung zugewiesen, das seine Ausgabe als Artefakt speichert. Anschließend haben Sie den Visual Director in einen eigenen A2A-Dienst aufgeteilt, ihn als Remote-Knoten wieder in den Graph eingebettet, in Cloud Run bereitgestellt und den gesamten Workflow über A2A von einem lokal ausgeführten Koordinator aus aufgerufen. Schließlich haben Sie die generierten Key Visuals aus BigQuery mit ObjectRef referenziert und mit AI.SCORE mit Ihren eigenen Markenrichtlinien verglichen.