1. Vertrauen aufbauen, um Großzügigkeit zu fördern

Der Moment der Inspiration
Ihr Smartphone vibriert. Sie sehen einen Nachrichtenbeitrag über ein erfolgreiches Alphabetisierungsprogramm, das Kindern in benachteiligten Gemeinden hilft, lesen zu lernen. Sie verspüren einen starken Drang, etwas beizutragen. Sie öffnen Ihren Browser und suchen nach Spenden für Kinderbildungsprogramme.

Hunderte von Ergebnissen werden angezeigt.
Sie klicken auf den ersten Link. Die Website wirkt professionell. Sie scrollen nach unten zu den Finanzinformationen. „Verwaltungskosten: 28 %“ Sie pausieren. Nur 72 Cent von jedem gespendeten Dollar werden tatsächlich für das Programm verwendet. Ist das gut? Sie sind sich nicht sicher.
Sie versuchen es mit einer anderen Organisation. Sie haben noch nie von ihnen gehört. Sind sie legitim? Eine kurze Suche führt Sie in eine Sackgasse. Sie finden einen Reddit-Thread von vor zwei Jahren, in dem ein Nutzer behauptet: „Das ist Betrug. Meine Spende ist nie angekommen.“ Ein anderer verteidigt sie leidenschaftlich: „Sie sind vor Ort und leisten echte Arbeit!“ Die Unklarheit ist lähmend.
Dreißig Minuten später sind Sie in einem Labyrinth aus widersprüchlichen Rezensionen, Effizienzbewertungen und IRS-Aufzeichnungen gefangen und haben immer noch nicht gespendet. Die anfängliche Großzügigkeit wurde durch die Reibung der Recherche ersetzt. Der Tab bleibt einige Tage lang geöffnet, als kleine Erinnerung an eine gute Absicht, bis Sie ihn schließlich schließen.
Das ist kein persönliches Versagen, sondern ein Systemfehler
Dieses Erlebnis ist universell. Die Bereitschaft zu spenden ist groß, aber der Prozess ist mit Hürden verbunden, die zu Zögern und Zweifeln führen:
- ❌ Rechercheaufwand:Für jede Wohltätigkeitsorganisation ist eine eigene Recherche erforderlich.
- ❌ Überprüfung des Vertrauens: Es ist schwierig, hocheffektive Organisationen von ineffizienten oder sogar betrügerischen Organisationen zu unterscheiden.
- ❌ Analyse-Lähmung:Eine überwältigende Anzahl von Auswahlmöglichkeiten führt zu Entscheidungsermüdung.
- ❌ Verlust an Dynamik:Die emotionale Motivation zum Spenden lässt nach, wenn der logistische Aufwand steigt.
Diese Reibung verursacht enorme Kosten in der realen Welt. Die Spenden von Einzelpersonen in den USA sind enorm. Laut Giving USA 2024 spendeten Einzelpersonen allein im Jahr 2023 rund 374 Milliarden$. Studien belegen jedoch, dass Hindernisse beim Spenden, darunter Suchkosten, psychologische Reibung und Zeitbeschränkungen, die Menge, die für wohltätige Zwecke erreicht wird, erheblich reduzieren. Studien mit Millionen von Spendern haben ergeben, dass selbst kleine Reibungspunkte beim Online-Spenden Menschen davon abhalten, ihre wohltätigen Absichten zu verwirklichen.
Das entspricht Milliarden von Dollar an geplanten Spenden, die nie bei den Organisationen ankommen, die sie benötigen.
Die Vision
Stellen Sie sich eine andere Erfahrung vor. Statt einer 30-minütigen Recherche sagen Sie einfach:
„Ich möchte 50 $an ein Alphabetisierungsprogramm für Kinder spenden. Suche mir eine gut bewertete, effiziente und geprüfte Wohltätigkeitsorganisation.“
Innerhalb von Sekunden erhalten Sie eine Antwort, die Vertrauen schafft:
Das ist das Versprechen eines KI-Spenden-Agents. Um diese Vision zu verwirklichen, müssen wir jedoch eine grundlegende Herausforderung meistern: Wenn ein autonomer KI-Agent Geld verwaltet, ist Vertrauen nicht optional, sondern die gesamte Grundlage.
- Wie können wir nachweisen, was ein Nutzer autorisiert hat?
- Wer ist verantwortlich, wenn ein Fehler gemacht wird?
- Wie können wir Spendern, gemeinnützigen Organisationen und Zahlungsnetzwerken die Zuversicht geben, dass sie teilnehmen können?
Deine Mission heute
In diesem Workshop kombinieren Sie zwei leistungsstarke Technologien, um einen vertrauenswürdigen Agenten zu erstellen:
Google Agent Development Kit (ADK) | Agent Payments Protocol (AP2) | |
Rolle | Die Factory zum Erstellen produktionsreifer KI‑Agenten | Der Architektur-Blueprint für Vertrauen in KI-Transaktionen |
Was bietet die Funktion? | • Framework für die Orchestrierung mehrerer Agents | • Rollenbasierte Sicherheitsgrenzen |
Weitere Informationen |
Umfang
Am Ende dieses Workshops haben Sie Folgendes erstellt:
✅ Ein Multi-Agenten-System mit spezialisierten Rollen:
- Ein Shopping-Agent, der geprüfte Wohltätigkeitsorganisationen findet
- Ein Händler-Agent, der verbindliche Spendenangebote erstellt
- Ein Anmeldedatenanbieter, der Zahlungen sicher verarbeitet
- Ein Orchestrator, der den gesamten Ablauf koordiniert
✅ Drei Arten von überprüfbaren Anmeldedaten:
- IntentMandate: „Find me an education charity“ (Suche für mich eine Wohltätigkeitsorganisation im Bildungsbereich)
- CartMandate: „50 $ an Room to Read, vom Händler unterzeichnet“
- PaymentMandate: „Über simulierte Zahlung verarbeiten“
✅ Sicherheit auf allen Ebenen:
- Rollenbasierte Vertrauensgrenzen
- Ausdrückliche Einwilligung des Nutzers
✅ Vollständiger Audit-Trail:
- Jede Entscheidung nachvollziehbar
- Jede Einwilligung wird aufgezeichnet
- Jede Übergabe ist sichtbar
🔒 Wichtig: Dies ist eine sichere Lernumgebung
Sind Sie bereit, Vertrauen aufzubauen?
Im nächsten Modul richten wir Ihre Entwicklungsumgebung ein und erstellen Ihren ersten KI-Agenten. Sie werden schnell feststellen, warum einfache Agents nicht vertrauenswürdig sind, und dann den Rest des Workshops damit verbringen, zu lernen, wie Sie das beheben können.
Beginnen wir damit, das Problem aus erster Hand zu verstehen.
2. Arbeitsbereich vorbereiten
Die Grundlage für vertrauenswürdige Agents
Bevor wir unseren KI-Giving-Agent erstellen können, müssen wir eine saubere, konsistente und korrekt konfigurierte Entwicklungsumgebung vorbereiten. In diesem Modul geht es darum, dass alle erforderlichen Tools und Dienste vorhanden sind.
Wenn Sie diese Einrichtung erfolgreich abgeschlossen haben, können Sie sich ganz auf die Entwicklung der Agentenlogik in den folgenden Modulen konzentrieren, ohne sich um Konfigurationsprobleme kümmern zu müssen.
Auf Cloud Shell zugreifen
Zuerst öffnen wir Cloud Shell. Das ist ein browserbasiertes Terminal, in dem das Google Cloud SDK und andere wichtige Tools vorinstalliert sind.
Google Cloud-Guthaben erforderlich?
Klicken Sie oben in der Google Cloud Console auf Cloud Shell aktivieren (das Terminalsymbol in der Navigationsleiste rechts oben).

So finden Sie Ihre Google Cloud-Projekt-ID:
- Öffnen Sie die Google Cloud Console: https://console.cloud.google.com.
- Wählen Sie oben auf der Seite im Drop-down-Menü das Projekt aus, das Sie für diesen Workshop verwenden möchten.
- Ihre Projekt-ID wird im Dashboard
auf der Karte „Projektinformationen“ angezeigt.
Prüfen Sie nach dem Öffnen von Cloud Shell, ob Sie authentifiziert sind:
# Check that you are logged in
gcloud auth list
Ihr Konto sollte als (ACTIVE) aufgeführt sein.
Projekt konfigurieren
Richten Sie nun Ihr Google Cloud-Projekt ein und aktivieren Sie die erforderlichen APIs.
Projekt-ID festlegen
# Set your project using the auto-detected environment variable in Cloud Shell
gcloud config set project $GOOGLE_CLOUD_PROJECT
# Verify the project has been set
echo "Your active Google Cloud project is: $(gcloud config get-value project)"
Erforderliche APIs aktivieren
Ihre Agents benötigen Zugriff auf mehrere Google Cloud-Dienste:
gcloud services enable \
aiplatform.googleapis.com \
secretmanager.googleapis.com \
cloudtrace.googleapis.com
Dies kann 1–2 Minuten dauern. Sie sehen hier Folgendes:
Operation "operations/..." finished successfully.
Funktionen dieser APIs:
- aiplatform.googleapis.com: Zugriff auf Gemini-Modelle für die Agentenlogik
- secretmanager.googleapis.com: Sichere Speicherung von API-Schlüsseln (Best Practice für die Produktion)
- cloudtrace.googleapis.com: Observability für unseren Verantwortlichkeitsnachweis
Starter-Code klonen
Rufen Sie das Workshop-Repository mit dem gesamten Vorlagencode und allen Ressourcen ab:
git clone https://github.com/ayoisio/adk-ap2-charity-agents
cd adk-ap2-charity-agents
git checkout codelab
Sehen wir uns an, was wir haben:
ls -la
Hier sollten Sie dies sehen:
charity_advisor/– Hier erstellen wir unsere Agents und Tools.scripts/– Hilfsskripts für Tests und Überprüfungdeploy.sh– Hilfsskript für die Bereitstellungsetup.py: Hilfsskript für die Modulinstallation.env.template– Datei mit Umgebungsvariablen
Python-Umgebung einrichten
Als Nächstes erstellen wir eine isolierte Python-Umgebung für unser Projekt.
Virtuelle Umgebung erstellen und aktivieren
# Create the virtual environment
python3 -m venv venv
# Activate it
source venv/bin/activate
✅ Bestätigung: Ihrem Prompt sollte jetzt das Präfix (venv) vorangestellt sein.
Abhängigkeiten installieren
pip install -r charity_advisor/requirements.txt
pip install -e .
Dadurch wird Folgendes installiert:
- google-adk: Das Framework des Agent Development Kit
- google-cloud-aiplatform: Vertex AI- und Gemini-Integration
- ap2: Agent Payments Protocol SDK (von GitHub)
- python-dotenv: Verwaltung von Umgebungsvariablen
Mit dem Flag -e können Sie adk_ap2_charity_agents-Module von überall aus importieren.
Umgebungsdatei konfigurieren
Konfiguration aus der Vorlage erstellen:
# Copy the template
cp .env.template .env
# Get your current Project ID
PROJECT_ID=$(gcloud config get-value project)
# Replace the placeholder with your actual project ID
sed -i "s/your-project-id/$PROJECT_ID/g" .env
# Verify the replacement worked
grep GOOGLE_CLOUD_PROJECT .env
Hier sollten Sie dies sehen:
GOOGLE_CLOUD_PROJECT=your-actual-project-id
Bestätigung
Führen Sie das Bestätigungsskript aus, um sicherzustellen, dass alles richtig konfiguriert ist:
python scripts/verify_setup.py
Es sollten nur grüne Häkchen angezeigt werden:
======================================================================
SETUP VERIFICATION
======================================================================
✓ Python version: 3.11.x
✓ google-adk: 1.17.0
✓ google-cloud-aiplatform: 1.111.0+
✓ ap2: 0.1.0
✓ python-dotenv: 1.0.0+
✓ .env file found and contains project ID
✓ Google Cloud project configured: your-project-id
✓ Mock charity database found
✓ Agent templates ready
✓ All directories present
======================================================================
✓ Setup complete! You are ready to build trustworthy agents.
======================================================================
Fehlerbehebung
Wie geht es weiter?
Ihre Umgebung ist jetzt vollständig vorbereitet. Sie haben:
- ✅ Google Cloud-Projekt konfiguriert
- ✅ Erforderliche APIs aktiviert
- ✅ ADK- und AP2-Bibliotheken installiert
- ✅ Vorlagencode kann geändert werden
Im nächsten Modul erstellen Sie Ihren ersten KI-Agenten mit wenigen Codezeilen und erfahren, warum einfache Agenten bei Finanztransaktionen nicht vertrauenswürdig sind.
3. Ihr erster Kundenservicemitarbeiter und die Vertrauenslücke

Von der Idee zur Interaktion
Im vorherigen Modul haben wir unsere Entwicklungsumgebung vorbereitet. Jetzt beginnt die spannende Arbeit. Wir werden unseren ersten Agenten erstellen und ausführen, ihm seine erste Funktion geben und dabei die grundlegenden Herausforderungen erkennen, die wir lösen müssen, um ihn wirklich vertrauenswürdig zu machen.
Dieses Modul ist Ihr „Vorher“-Bild – der Moment, der zeigt, warum für die Entwicklung vertrauenswürdiger Agents mehr erforderlich ist, als einem LLM nur Zugriff auf Tools zu gewähren.
Schritt 1: Starter-Agent untersuchen
Sehen wir uns zuerst die Vorlage für unseren ersten Agent an. Sie enthält eine grundlegende Struktur mit Platzhaltern, die wir in den nächsten Schritten ausfüllen werden.
👉 Datei öffnen
charity_advisor/simple_agent/agent.py
in Ihrem Editor.
Sie sehen hier Folgendes:
"""
A simple agent that can research charities using Google Search.
"""
# MODULE_3_STEP_2_IMPORT_COMPONENTS
simple_agent = Agent(
name="SimpleAgent",
model="gemini-2.5-flash",
# MODULE_3_STEP_3_WRITE_INSTRUCTION
instruction="""""",
# MODULE_3_STEP_4_ADD_TOOLS
tools=[]
)
Die Platzhalterkommentare folgen einem Muster: MODULE_3_STEP_X_DESCRIPTION. Wir werden diese Platzhalter ersetzen, um unseren Agenten nach und nach zu erstellen.
Schritt 2: Erforderliche Komponenten importieren
Bevor wir die Klasse Agent instanziieren oder das Tool google_search verwenden können, müssen wir sie in unsere Datei importieren.
👉 Finden:
# MODULE_3_STEP_2_IMPORT_COMPONENTS
👉 Ersetzen Sie diese einzelne Zeile durch:
from google.adk.agents import Agent
from google.adk.tools import google_search
Die Klasse Agent und das Tool google_search sind jetzt in unserer Datei verfügbar.
Schritt 3: Agent-Anweisung schreiben
Die Anleitung ist die „Stellenbeschreibung“ des Agents. Sie gibt dem LLM vor, wann und wie es seine Tools verwenden soll. Wir schreiben eine, die unseren Agent anweist, nach Informationen zu Wohltätigkeitsorganisationen zu suchen.
👉 Finden:
# MODULE_3_STEP_3_WRITE_INSTRUCTION
instruction="""""",
👉 Ersetzen Sie diese beiden Zeilen durch:
instruction="""You are a helpful research assistant. When a user asks you to find information about charities,
use the google_search tool to find the most relevant and up-to-date results from the web.
Synthesize the search results into a helpful summary.""",
Schritt 4: Suchtool hinzufügen
Ein Agent ohne Tools ist nur ein Gesprächspartner. Wir geben unserem Agent die erste Funktion: die Möglichkeit, im Web zu suchen.
👉 Finden:
# MODULE_3_STEP_4_ADD_TOOLS
tools=[]
👉 Ersetzen Sie diese beiden Zeilen durch:
tools=[google_search]
Schritt 5: Complete Agent bestätigen
Bevor wir mit dem Testen beginnen, sollten wir sichergehen, dass alle Voraussetzungen erfüllt sind.
👉 Vollständige
charity_advisor/simple_agent/agent.py
Die -Datei sollte jetzt genau so aussehen:
"""
A simple agent that can research charities using Google Search.
"""
from google.adk.agents import Agent
from google.adk.tools import google_search
simple_agent = Agent(
name="SimpleAgent",
model="gemini-2.5-flash",
instruction="""You are a helpful research assistant. When a user asks you to find information about charities,
use the google_search tool to find the most relevant and up-to-date results from the web.
Synthesize the search results into a helpful summary.""",
tools=[google_search]
)
Schritt 6: Agent testen – Vertrauenslücken aufdecken
Nachdem wir den Agent vollständig konfiguriert haben, können wir ihn testen und sein Verhalten analysieren. Hier wird deutlich, warum einfache KI-Assistenten bei finanziellen Entscheidungen nicht vertrauenswürdig sind.
Test 1: Das Discovery-Problem
👉 Führen Sie im Cloud Shell-Terminal den folgenden Befehl aus:
adk run charity_advisor/simple_agent
Die Ausgabe sollte in etwa so aussehen:
INFO:google.adk.agents:Loading agent from charity_advisor/simple_agent
INFO:google.adk.agents:Agent 'SimpleAgent' ready
[user]:
Der Prompt [user]: wartet jetzt auf Ihre Eingabe.
👉 Geben Sie an der Eingabeaufforderung [user] Folgendes ein:
Can you find me a verified, highly-rated charity for children's literacy?
👉 Drücken Sie die Eingabetaste und sehen Sie sich die Antwort an.
Nach kurzer Zeit fasst der Agent die Suchergebnisse in einer Antwort wie dieser zusammen:
Laut einer Websuche sind Reading Is Fundamental und Room to Read einige angesehene Wohltätigkeitsorganisationen für die Lesefähigkeit von Kindern. Quellen wie Charity Navigator und GuideStar werden oft empfohlen, um den Status und die Bewertungen zu überprüfen. Ich habe auch mehrere Online-Diskussionen gefunden, unter anderem in Foren wie Reddit, in denen Nutzer persönliche Erfahrungen mit verschiedenen kleineren, lokalen Alphabetisierungsprogrammen teilen.
Sehen wir uns das genauer an. Hat der Kundenservicemitarbeiter unser Problem gelöst?
❌ Nein. Das Modell hat die menschliche Erfahrung, die wir in Modul 1 beschrieben haben, perfekt nachgebildet. Es hat den Prozess des „Googlens“ erfolgreich automatisiert und das Problem der „Analyse-Paralyse“ direkt an uns zurückgegeben.
Hier zeigt sich die erste Vertrauenslücke: Es fehlen autoritative Daten.
Der KI-Agent durchsucht das offene Web. Das bedeutet:
- ✅ Es wurden schnell Ergebnisse gefunden (verbesserte Nutzerfreundlichkeit).
- ❌ Es werden Organisationen mit hoher Bewertung mit Reddit-Diskussionen (unzuverlässige Quellen) vermischt.
- ❌ Es kann nicht zwischen geprüften Wohltätigkeitsorganisationen und potenziellen Betrugsfällen unterscheiden (keine Überprüfung).
- ❌ Es fordert uns auf, die gerade bereitgestellten Informationen zu bestätigen (die Verantwortung wird zurückgegeben).
Test 2: Das Ausführungsproblem
Jetzt kommt der entscheidende zweite Test. Versuchen Sie bei der Eingabeaufforderung [user]:, die Spende abzuschließen:
Okay, please donate $50 to Room to Read for me.
Der Agent antwortet mit einer Entschuldigung und gibt seine Einschränkung zu:
Sie haben uns mitgeteilt, dass Sie spenden möchten. Das ist toll! Ich bin jedoch eine Forschungsassistentin und kann keine Finanztransaktionen oder Zahlungen bearbeiten. Wenn Sie spenden möchten, müssen Sie die offizielle Website von Room to Read aufrufen.
Das ist der zweite, ebenso wichtige „Aha!“-Moment.
Der Agent kann nicht nur nicht als vertrauenswürdig eingestuft werden, wenn es darum geht, die richtige Wohltätigkeitsorganisation zu finden, sondern auch nicht, wenn es darum geht, die Spende auszuführen.
👉 Drücken
Ctrl+C
, um den Test zu beenden.
Die beiden Lücken im Überblick
Das haben Sie gerade gelernt
In diesem Modul haben Sie Ihren ersten KI-Agenten erfolgreich erstellt und ausgestattet. Dabei haben Sie die beiden grundlegenden Herausforderungen bei der Entwicklung eines vertrauenswürdigen Systems kennengelernt.
Beherrschte Schlüsselkonzepte
✅ Die Agent-Klasse:
- Zentraler Baustein des ADK
- Kombiniert LLM-Logik (Gehirn) mit Tools (Hände)
- Mit Modell, Anleitung und Tools konfiguriert
✅ Ordnerbasierte Struktur:
- Jeder Agent befindet sich in einem eigenen Ordner.
- ADK sucht nach
agent_folder/agent.py - Laufen mit
adk run agent_folder
✅ Die Liste der Tools:
- Definiert die Agent-Funktionen
- LLM entscheidet, wann und wie Tools verwendet werden
- Kann mehrere Tools für verschiedene Aktionen enthalten
✅ Der Anweisungsprompt:
- Steuert das Verhalten des KI-Agenten wie eine Stellenbeschreibung
- Gibt Rolle, Trigger, Aktionen und Ausgabeformat an
- Wichtig für die zuverlässige Verwendung von Tools
✅ Das Vertrauensproblem:
- Lücke bei der Erkennung: Nicht geprüfte Quellen, gemischte Qualität
- Ausführungslücke: Keine sicheren Funktionen, keine Einwilligung, kein Prüfpfad
Weitere Informationen
Im nächsten Modul beginnen wir mit der Entwicklung der Lösung, indem wir die rollenbasierte Architektur von AP2 implementieren.
Erstellen wir den ersten Agent und sehen wir uns die Rollentrennung in Aktion an.
4. Shopping-Agent erstellen – Rollenbasierte Suche

Die Grundlage für Vertrauen: Rollentrennung
Im letzten Modul haben Sie erfahren, dass ein einfacher Allzweck-Agent in zwei Punkten scheitert: Er kann keine vertrauenswürdige Suche durchführen und keine sicheren Transaktionen ausführen. Wir beginnen nun mit der Lösung dieser Probleme, indem wir den ersten Grundsatz aus dem Agent Payments Protocol implementieren: rollenbasierte Architektur.
Bevor wir Code schreiben, wollen wir uns ansehen, warum dieses Prinzip wichtig ist.
AP2-Grundsatz: Rollentrennung
Das Problem mit „Alles erledigen“-KI-Agenten
Stellen Sie sich vor, Sie stellen eine Person ein, die Ihr Finanzberater, Buchhalter und Anlageberater ist. Praktisch? Ja. Sicher? Auf keinen Fall. Sie hätten:
- Ihre Anlageziele (Beraterrolle)
- Zugriff auf Ihre Konten (Rolle „Buchhalter“)
- Berechtigung, Ihr Geld zu bewegen (Rolle des Brokers)
Wenn diese Person kompromittiert wird oder einen Fehler macht, ist alles gefährdet.
Lösung von AP2: Ein Agent, ein Job
AP2 wendet das Prinzip der Aufgabentrennung an, um Vertrauensgrenzen zu schaffen:
Warum das wichtig ist:
- ✅ Begrenzter Blast Radius: Wenn der Shopping-Agent kompromittiert wird, kann der Angreifer nicht auf Zahlungsanmeldedaten zugreifen.
- ✅ Datenschutz: Der Anmeldedatenanbieter sieht Ihre Shopping-Unterhaltung nicht.
- ✅ Compliance: Die PCI DSS-Anforderungen lassen sich leichter erfüllen, wenn Zahlungsdaten isoliert werden.
- ✅ Rechenschaftspflicht: Klare Verantwortung für jeden Schritt
So kommunizieren Agents: Status als gemeinsames Notizbuch
Da Agents nicht direkt auf die Daten der anderen zugreifen können, kommunizieren sie über den gemeinsamen Status. Stellen Sie sich das als Whiteboard vor, auf das alle Kundenservicemitarbeiter schreiben und von dem sie lesen können:
# Shopping Agent writes:
state["intent_mandate"] = {
"natural_language_description": "Donate $50 to Room to Read",
"merchants": ["Room to Read"],
"intent_expiry": "2024-11-07T15:32:16Z",
"amount": 50.0
}
# Merchant Agent reads:
intent = state["intent_mandate"]
charity_name = intent["merchants"][0]
amount = intent["amount"]
# Creates CartMandate based on IntentMandate...
# Credentials Provider reads:
cart_mandate = state["cart_mandate"]
# Processes payment...
So wahren wir Vertrauensgrenzen und ermöglichen gleichzeitig die Zusammenarbeit.
Unser erster Agent: der Shopping-Agent
Die Aufgaben des Shopping-Agents sind einfach und konzentriert:
- Mit dem
find_charities-Tool unsere vertrauenswürdige Datenbank abfragen - Nutzeroptionen präsentieren
- Verwenden Sie das
save_user_choice-Tool, um ein IntentMandate zu erstellen und im Status zu speichern. - An den nächsten Kundenservicemitarbeiter (den Händler) weiterleiten
Das war's. Es gibt keine Zahlungsabwicklung und keine Warenkorberstellung – es geht nur um die Erkennung und Übergabe.
Wir gehen das Schritt für Schritt durch.
Schritt 1: Input Validation Helper hinzufügen
Beim Erstellen von Produktionstools ist die Eingabevalidierung von entscheidender Bedeutung. Erstellen wir eine Hilfsfunktion, die die Daten der Wohltätigkeitsorganisation validiert, bevor sie im Status gespeichert werden.
👉 Offen
charity_advisor/tools/charity_tools.py
Oben sehen Sie die Funktion find_charities (bereits fertig). Scrollen Sie nach unten, um Folgendes zu sehen:
# MODULE_4_STEP_1_ADD_VALIDATION_HELPER
👉 Ersetzen Sie diese einzelne Zeile durch:
def _validate_charity_data(charity_name: str, charity_ein: str, amount: float) -> tuple[bool, str]:
"""
Validates charity selection data before saving to state.
This helper function performs basic validation to ensure data quality
before it gets passed to other agents in the pipeline.
Args:
charity_name: Name of the selected charity
charity_ein: Employer Identification Number (should be format: XX-XXXXXXX)
amount: Donation amount in USD
Returns:
(is_valid, error_message): Tuple where is_valid is True if all checks pass,
and error_message contains details if validation fails
"""
# Validate charity name
if not charity_name or not charity_name.strip():
return False, "Charity name cannot be empty"
# Validate EIN format (should be XX-XXXXXXX)
if not charity_ein or len(charity_ein) != 10 or charity_ein[2] != '-':
return False, f"Invalid EIN format: {charity_ein}. Expected format: XX-XXXXXXX"
# Validate amount
if amount <= 0:
return False, f"Donation amount must be positive, got: ${amount}"
if amount > 1_000_000:
return False, f"Donation amount exceeds maximum of $1,000,000: ${amount}"
# All checks passed
return True, ""
Schritt 2: IntentMandate Creation Helper hinzufügen
Erstellen wir nun die Hilfsfunktion, mit der die AP2-IntentMandate-Struktur erstellt wird. Dies ist eines der drei überprüfbaren Anmeldedaten in AP2.
👉 Suchen Sie in derselben Datei nach:
# MODULE_4_STEP_2_ADD_INTENTMANDATE_CREATION_HELPER
👉 Ersetzen Sie diese einzelne Zeile durch:
def _create_intent_mandate(charity_name: str, charity_ein: str, amount: float) -> dict:
"""
Creates an IntentMandate - AP2's verifiable credential for user intent.
This function uses the official Pydantic model from the `ap2` package
to create a validated IntentMandate object before converting it to a dictionary.
Args:
charity_name: Name of the selected charity
charity_ein: Employer Identification Number
amount: Donation amount in USD
Returns:
Dictionary containing the IntentMandate structure per AP2 specification
"""
from datetime import datetime, timedelta, timezone
from ap2.types.mandate import IntentMandate
# Set the expiry for the intent
expiry = datetime.now(timezone.utc) + timedelta(hours=1)
# Step 1: Instantiate the Pydantic model with official AP2 fields
intent_mandate_model = IntentMandate(
user_cart_confirmation_required=True,
natural_language_description=f"Donate ${amount:.2f} to {charity_name}",
merchants=[charity_name],
skus=None,
requires_refundability=False,
intent_expiry=expiry.isoformat()
)
# Step 2: Convert the validated model to a dictionary for state storage
intent_mandate_dict = intent_mandate_model.model_dump()
# Step 3: Add the codelab's custom fields to the dictionary
timestamp = datetime.now(timezone.utc)
intent_mandate_dict.update({
"timestamp": timestamp.isoformat(),
"intent_id": f"intent_{charity_ein.replace('-', '')}_{int(timestamp.timestamp())}",
"charity_ein": charity_ein,
"amount": amount,
"currency": "USD"
})
return intent_mandate_dict
Schritt 3: Tool für die Statusübergabe mit IntentMandate erstellen
Erstellen wir nun das Tool, mit dem das IntentMandate erstellt und im Status gespeichert wird.
👉 Scrollen Sie in derselben Datei nach unten zu
save_user_choice
-Funktion. Suchen:
# MODULE_4_STEP_3_COMPLETE_SAVE_TOOL
👉 Ersetzen Sie diese einzelne Zeile durch:
# Validate inputs before creating IntentMandate
is_valid, error_message = _validate_charity_data(charity_name, charity_ein, amount)
if not is_valid:
logger.error(f"Validation failed: {error_message}")
return {"status": "error", "message": error_message}
# Create AP2 IntentMandate using our updated helper function
intent_mandate = _create_intent_mandate(charity_name, charity_ein, amount)
# Write the IntentMandate to shared state for the next agent
tool_context.state["intent_mandate"] = intent_mandate
logger.info(f"Successfully created IntentMandate and saved to state")
logger.info(f"Intent ID: {intent_mandate['intent_id']}")
logger.info(f"Intent expires: {intent_mandate['intent_expiry']}")
# Return success confirmation
return {
"status": "success",
"message": f"Created IntentMandate: ${amount:.2f} donation to {charity_name} (EIN: {charity_ein})",
"intent_id": intent_mandate["intent_id"],
"expiry": intent_mandate["intent_expiry"]
}
Schritt 4: Display Formatting Helper hinzufügen
Bevor wir den Agent erstellen, fügen wir noch eine Hilfsfunktion hinzu, mit der Wohltätigkeitsorganisationen für die nutzerfreundliche Darstellung formatiert werden.
👉 Scrollen Sie, um Folgendes zu finden:
# MODULE_4_STEP_4_ADD_FORMATTING_HELPER
👉 Ersetzen Sie diese einzelne Zeile durch:
def _format_charity_display(charity: dict) -> str:
"""
Formats a charity dictionary into a user-friendly display string.
This helper function demonstrates how to transform structured data
into readable text for the user.
Args:
charity: Dictionary containing charity data (name, ein, mission, rating, efficiency)
Returns:
Formatted string suitable for display to the user
"""
name = charity.get('name', 'Unknown')
ein = charity.get('ein', 'N/A')
mission = charity.get('mission', 'No mission statement available')
rating = charity.get('rating', 0.0)
efficiency = charity.get('efficiency', 0.0)
# Format efficiency as percentage
efficiency_pct = int(efficiency * 100)
# Build formatted string
display = f"""
**{name}** (EIN: {ein})
⭐ Rating: {rating}/5.0
💰 Efficiency: {efficiency_pct}% of funds go to programs
📋 Mission: {mission}
""".strip()
return display
Schritt 5: Shopping-Agent erstellen – Komponenten importieren
Nachdem unsere Tools fertig und robust sind, erstellen wir den Agent, der sie verwenden wird.
👉 Offen
charity_advisor/shopping_agent/agent.py
Es wird eine Vorlage mit Platzhalterkommentaren angezeigt. Wir gehen das Schritt für Schritt durch.
👉 Finden:
# MODULE_4_STEP_5_IMPORT_COMPONENTS
👉 Ersetzen Sie diese einzelne Zeile durch:
from google.adk.agents import Agent
from google.adk.tools import FunctionTool
from charity_advisor.tools.charity_tools import find_charities, save_user_choice
Schritt 6: Agent-Anweisung schreiben
In der Anleitung definieren wir die Stellenbeschreibung und den Workflow des Agents. Das ist entscheidend: Eine schlecht formulierte Anleitung führt zu unzuverlässigem Verhalten.
👉 Finden:
# MODULE_4_STEP_6_WRITE_INSTRUCTION
instruction="""""",
👉 Ersetzen Sie diese beiden Zeilen durch:
instruction="""You are a research specialist helping users find verified charities.
Your workflow:
1. When the user describes what cause they want to support (e.g., "education", "health", "environment"),
use the find_charities tool to search our vetted database.
2. Present the results clearly. The tool returns formatted charity information that you should
show to the user.
3. When the user selects a charity and specifies an amount, use the save_user_choice tool
to create an IntentMandate and record their decision. You MUST call save_user_choice with:
- charity_name: The exact name of the chosen charity
- charity_ein: The EIN of the chosen charity
- amount: The donation amount in dollars (as a number, not a string)
4. After successfully saving, inform the user:
- That you've created an IntentMandate (mention the intent ID if provided)
- When the intent expires
- That you're passing their request to the secure payment processor
IMPORTANT BOUNDARIES:
- Your ONLY job is discovery and creating the IntentMandate
- You do NOT process payments
- You do NOT see the user's payment methods
- You do NOT create cart offers (that's the Merchant Agent's job)
- After calling save_user_choice, your work is done
WHAT IS AN INTENTMANDATE:
An IntentMandate is a structured record of what the user wants to do. It includes:
- Natural language description ("Donate $50 to Room to Read")
- Which merchants can fulfill it
- When the intent expires
- Whether user confirmation is required
This is the first of three verifiable credentials in our secure payment system.
If the user asks you to do anything related to payment processing, politely explain that
you don't have that capability and that their request will be handled by the appropriate
specialist agent.""",
Schritt 7: Tools zum Agent hinzufügen
Jetzt geben wir dem KI‑Agenten Zugriff auf beide Tools.
👉 Finden:
# MODULE_4_STEP_7_ADD_TOOLS
👉 Ersetzen Sie diese beiden Zeilen durch:
tools=[
FunctionTool(func=find_charities),
FunctionTool(func=save_user_choice)
]
Schritt 8: Complete Agent bestätigen
Wir prüfen, ob alles richtig verkabelt ist.
👉 Vollständige
charity_advisor/shopping_agent/agent.py
sollte jetzt so aussehen:
"""
Shopping Agent - Finds charities from a trusted database and saves the user's choice.
This agent acts as our specialized "Research Analyst."
"""
from google.adk.agents import Agent
from google.adk.tools import FunctionTool
from charity_advisor.tools.charity_tools import find_charities, save_user_choice
shopping_agent = Agent(
name="ShoppingAgent",
model="gemini-2.5-pro",
description="Finds and recommends vetted charities from a trusted database, then creates an IntentMandate capturing the user's donation intent.",
instruction="""You are a research specialist helping users find verified charities.
Your workflow:
1. When the user describes what cause they want to support (e.g., "education", "health", "environment"),
use the find_charities tool to search our vetted database.
2. Present the results clearly. The tool returns formatted charity information that you should
show to the user.
3. When the user selects a charity and specifies an amount, use the save_user_choice tool
to create an IntentMandate and record their decision. You MUST call save_user_choice with:
- charity_name: The exact name of the chosen charity
- charity_ein: The EIN of the chosen charity
- amount: The donation amount in dollars (as a number, not a string)
4. After successfully saving, inform the user:
- That you've created an IntentMandate (mention the intent ID if provided)
- When the intent expires
- That you're passing their request to the secure payment processor
IMPORTANT BOUNDARIES:
- Your ONLY job is discovery and creating the IntentMandate
- You do NOT process payments
- You do NOT see the user's payment methods
- You do NOT create cart offers (that's the Merchant Agent's job)
- After calling save_user_choice, your work is done
WHAT IS AN INTENTMANDATE:
An IntentMandate is a structured record of what the user wants to do. It includes:
- Natural language description ("Donate $50 to Room to Read")
- Which merchants can fulfill it
- When the intent expires
- Whether user confirmation is required
This is the first of three verifiable credentials in our secure payment system.
If the user asks you to do anything related to payment processing, politely explain that
you don't have that capability and that their request will be handled by the appropriate
specialist agent.""",
tools=[
FunctionTool(func=find_charities),
FunctionTool(func=save_user_choice)
]
)
✅ Perfekt! Sie haben einen AP2-kompatiblen Agent in Produktionsqualität mit folgenden Funktionen erstellt:
- Eingabevalidierung
- Ordnungsgemäße Erstellung von IntentMandate mit AP2-Pydantic-Modellen
- Formatierte Ausgabe
- Klare Rollengrenzen
- Detaillierte Anleitung
- Fehlerbehandlung
Schritt 9: Shopping-Agent testen
Wir prüfen jetzt, ob unser Agent richtig funktioniert, korrekte IntentMandates erstellt und seine Grenzen einhält.
👉 Führen Sie in Ihrem Cloud Shell-Terminal Folgendes aus:
adk run charity_advisor/shopping_agent
Die Eingabeaufforderung [user]: wird angezeigt.
Test 1: Discovery mit Trusted Database
👉 Typ:
I want to donate to an education charity. What are my options?
Nach kurzer Zeit antwortet der Kundenservicemitarbeiter. Dank unseres _format_charity_display-Helfertools sind die Ergebnisse ansprechend formatiert:
Wir haben drei bestätigte Bildungsorganisationen in unserer Datenbank gefunden:
Room to Read (EIN: 77-0479905)
⭐ Bewertung: 4,9/5,0
💰 Effizienz: 88% der Mittel fließen in Programme
📋 Mission: Das Leben von Millionen von Kindern in einkommensschwachen Gemeinden verändern, indem der Schwerpunkt auf Alphabetisierung und Gleichstellung der Geschlechter in der Bildung liegt.
Teach For America (EIN: 13-3541913)
⭐ Bewertung: 4,7/5,0
💰 Effizienz: 81% der Mittel fließen in Programme
📋 Mission: Setzt sich für die Ausweitung der Bildungschancen für benachteiligte Kinder ein.
Tech Education Alliance (EIN: 45-2345678)
⭐ Bewertung: 4,8/5,0
💰 Effizienz: 92% der Mittel fließen in Programme
📋 Mission: Informatikunterricht für Schulen in unterversorgten Gebieten.
Welche Wohltätigkeitsorganisation möchten Sie unterstützen und wie viel möchten Sie spenden?
Vergleichen Sie das mit dem einfachen Agent aus Modul 3, der ungeprüfte Google-Ergebnisse lieferte. Das ist der Unterschied zwischen nicht vertrauenswürdiger und vertrauenswürdiger Erkennung.
Test 2: Nutzerauswahl aufzeichnen und IntentMandate erstellen
👉 Typ:
I'll donate $50 to Room to Read.
Der Agent sollte das Tool save_user_choice mit den richtigen Parametern aufrufen. Dank der Erstellung von IntentMandate mit AP2-Modellen erhalten Sie eine strukturiertere Antwort:
Super! Ich habe ein IntentMandate für Ihre Spende erstellt:
Details zur Intention:
- Intent-ID: intent_774795905_1730927536
- Betrag: 50,00 $ an Room to Read (EIN: 77-0479905)
- Läuft ab: 2024-11-07T15:32:16Z (in 1 Stunde)
Dieses IntentMandate erfasst Ihre Spendenabsicht und enthält Einschränkungen, um sicherzustellen, dass die Transaktion sicher verarbeitet wird. Ich leite diese Informationen jetzt an unseren sicheren Zahlungsdienstleister weiter, damit ein offizielles Angebot erstellt und Ihre Spende abgeschlossen werden kann.
Hinter den Kulissen ist Folgendes passiert:
_validate_charity_data()hat die Eingaben überprüft_create_intent_mandate()hat das AP2-Pydantic-Modell verwendet, um die Struktur zu erstellen:
# Created and validated via Pydantic
intent_mandate_model = IntentMandate(
user_cart_confirmation_required=True,
natural_language_description="Donate $50.00 to Room to Read",
merchants=["Room to Read"],
skus=None,
requires_refundability=False,
intent_expiry="2024-11-07T15:32:16Z"
)
# Converted to dict and extended with custom fields
intent_mandate_dict = intent_mandate_model.model_dump()
intent_mandate_dict.update({
"charity_ein": "77-0479905",
"amount": 50.0,
"currency": "USD"
})
- Das Tool hat NUR das IntentMandate in den freigegebenen Status geschrieben:
state["intent_mandate"] = intent_mandate_dict
- Dem LLM wurde eine Erfolgsmeldung mit Intent-Details zurückgegeben.
- Das LLM hat die endgültige Nutzernachricht verfasst.
Dieses IntentMandate kann jetzt vom Händler-Agent (Modul 5) abgerufen werden. Der Händler extrahiert den Namen der Organisation und den Betrag aus dem IntentMandate und prüft, ob es abgelaufen ist.
Test 3: Validierung in Aktion
Prüfen wir, ob unser Validierungs-Helper ungültige Eingaben erkennt.
👉 Typ:
I'll donate -$25 to Room to Read.
Der Agent sollte den ungültigen Betrag erkennen:
Ich habe ein Problem: Der Spendenbetrag muss positiv sein. Ich habe Folgendes erhalten: $-25.0
Bitte gib einen positiven Spendenbetrag an. Ich erstelle dann das IntentMandate für dich.
Das ist Defensive Programming in Aktion. Unser _validate_charity_data-Helfer hat verhindert, dass ungültige Daten in das System gelangen und ein fehlerhaftes IntentMandate erstellt wird.
Test 4: Vertrauensgrenze überprüfen
👉 Agent bitten, die Zahlung zu verarbeiten:
Now process my credit card payment.
Der Kundenservicemitarbeiter sollte die Anfrage ablehnen und dabei seine Rolle berücksichtigen:
Ich kann keine Zahlungen verarbeiten. Das gehört nicht zu meinen Aufgaben. Meine Aufgabe ist es, Ihnen dabei zu helfen, bestätigte Wohltätigkeitsorganisationen zu finden und das IntentMandate zu erstellen, in dem Ihre Spendenabsicht festgehalten wird.
Ihr Intent-Mandat wurde bereits erstellt und an unseren sicheren Zahlungsabwickler weitergeleitet. Der Händler-Agent erstellt ein formelles Angebot (CartMandate) und der Anmeldedatenanbieter wickelt die eigentliche Zahlung mit Ihrer ausdrücklichen Einwilligung ab.
Hier sehen Sie die Vertrauensgrenze in Aktion. Der Agent weiß, dass er nicht berechtigt ist, Zahlungsdaten zu verarbeiten. In seiner Anleitung wird er explizit angewiesen, dies den Nutzern zu erklären und ihnen gleichzeitig das Konzept von „IntentMandate“ zu erläutern.
👉 Drücken
Ctrl+C
, um den Test zu beenden.
Was Sie gerade erstellt haben
Sie haben den ersten Teil der AP2-Architektur erfolgreich implementiert und mit AP2-Pydantic-Modellen ein gültiges IntentMandate erstellt.
Beherrschte Schlüsselkonzepte
✅ Rollenbasierte Architektur:
- Jeder Agent hat eine klar definierte Aufgabe.
- Agenten kommunizieren über einen gemeinsamen Status, nicht über direkten Zugriff
- Vertrauensgrenzen begrenzen die Auswirkungen von Sicherheitslücken
✅ IntentMandate (AP2-Anmeldedaten 1):
- Mit offiziellen AP2-Pydantic-Modellen zur Validierung erstellt
- Strukturierte Erfassung der Nutzerabsicht
- Enthält ein Ablaufdatum für die Sicherheit (verhindert Wiederholungsangriffe)
- Gibt Einschränkungen an (Händler, Erstattungsfähigkeit, Bestätigung)
- Beschreibung in natürlicher Sprache für Menschen
- Maschinenlesbar für Agenten
- Modell vor der Konvertierung in ein Dictionary validiert
✅ Als geteilte Erinnerung speichern:
tool_context.stateist das „Notizbuch“, auf das alle Kundenservicemitarbeiter zugreifen können.- Schreiben in den Status = überprüfbare Anmeldedaten verfügbar machen
- Lesen aus dem Status = Anmeldedaten verwenden und validieren
- Downstream-Agents extrahieren die benötigten Informationen aus den Anmeldedaten.
✅ FunctionTool:
- Konvertiert Python-Funktionen in LLM-aufrufbare Tools
- Verlässt sich auf Docstrings und Typ-Hinweise, damit das LLM die Funktion versteht
- Aufruf wird automatisch verarbeitet
- Tool-Komposition: kleine, fokussierte Tools > monolithische Tools
✅ Anweisungen für Kundenservicemitarbeiter:
- Detaillierte Workflowanleitung
- Explizite Grenzen („NICHT…“)
- Parameterspezifikationen zur Vermeidung von Fehlern
- Technische Definitionen (was ist IntentMandate?)
- Umgang mit Sonderfällen (was sagen, wenn…)
Weitere Informationen
Im nächsten Modul erstellen wir den Merchant Agent, um das IntentMandate zu empfangen und das zweite überprüfbare Attribut CartMandate zu erstellen.
Der Shopping-Agent hat ein IntentMandate mit Ablaufdatum erstellt, das die Absicht des Nutzers erfasst. Jetzt benötigen wir einen Agent, der diese Anmeldedaten liest, prüft, ob sie abgelaufen sind, und ein formelles, unterzeichnetes Angebot erstellt, in dem steht: „Ich, der Händler, werde diesen Preis einhalten und diese Waren liefern.“
Wir erstellen den Merchant Agent und sehen uns die zweite AP2-Anmeldedaten in Aktion an.
5. Händler-Agent erstellen – Bindende Angebote und CartMandate

Von der Entdeckung zur Verpflichtung
Im vorherigen Modul haben Sie den Shopping-Agent erstellt, einen Spezialisten, der geprüfte Wohltätigkeitsorganisationen findet und ein IntentMandate erstellt, das die Absicht des Nutzers erfasst. Jetzt benötigen wir einen Agent, der dieses IntentMandate empfängt und ein formelles, verbindliches Angebot erstellt.
Hier kommt der zweite Grundsatz von AP2 ins Spiel: Nachweis von Anmeldedaten über CartMandate.
AP2-Grundsatz: Warenkorb-Mandat und verbindliche Angebote
Warum wir eine Händlerrolle benötigen
Im Modul 4 hat der Shopping-Agent ein IntentMandate erstellt und im Status gespeichert:
state["intent_mandate"] = {
"natural_language_description": "Donate $50 to Room to Read",
"merchants": ["Room to Read"],
"amount": 50.0,
"intent_expiry": "2024-11-07T15:32:16Z"
}
Das ist aber nur die Nutzerintention. Bevor eine Zahlung verarbeitet werden kann, benötigen wir Folgendes:
- Eine formelle Angebotsstruktur, die von Zahlungssystemen verstanden wird
- Nachweis, dass der Händler diesen Preis akzeptiert
- Eine verbindliche Zusage, die während der Transaktion nicht geändert werden kann
- Bestätigung, dass der Intent nicht abgelaufen ist
Das ist die Aufgabe des Merchant-Agents.
Was ist ein CartMandate?
Ein CartMandate ist der Begriff von AP2 für einen „digitalen Einkaufswagen“, der als verbindliches Angebot dient. Sie ist gemäß dem W3C-Standard „PaymentRequest“ strukturiert. Das bedeutet:
- Zahlungsabwickler weltweit erkennen das Format
- Sie enthält alle Transaktionsdetails in standardisierter Form.
- Sie kann kryptografisch signiert werden, um die Authentizität zu beweisen.
Stellen Sie sich das wie ein schriftliches Angebot eines Auftragnehmers vor:
- ❌ Mündlich: „Ja, ich kann das für etwa 50 € machen.“
- ✅ Schriftliches Angebot: Aufgeschlüsselte Kosten, Gesamtsumme, Unterschrift, Datum
Das schriftliche Angebot ist verbindlich. Das CartMandate ist das digitale Äquivalent.
Struktur eines CartMandate
Ein CartMandate in AP2 hat eine bestimmte verschachtelte Struktur:
cart_mandate = {
"contents": { # ← AP2 wrapper
"id": "cart_xyz123",
"cart_expiry": "2024-11-07T15:47:16Z",
"merchant_name": "Room to Read",
"user_cart_confirmation_required": False,
"payment_request": { # ← W3C PaymentRequest nested inside
"method_data": [...],
"details": {...},
"options": {...}
}
},
"merchant_authorization": "SIG_a3f7b2c8" # ← Merchant signature
}
Drei Hauptkomponenten:
1. contents: Der Warenkorb-Wrapper mit folgenden Elementen:
- Warenkorb-ID und Ablaufdatum
- Händlername
- W3C PaymentRequest
2. payment_request (im Inhalt) – Was wird gekauft?
- method_data: Akzeptierte Zahlungsmethoden
- Details: Artikel und Summe
- Optionen: Versand, Anforderungen an Zahlungsinformationen
3. merchant_authorization – Kryptografische Signatur
Händlersignaturen: Nachweis der Verpflichtung
Die Händlersignatur ist entscheidend. Das beweist:
- Dieses Angebot stammt von einem autorisierten Händler
- Der Händler verpflichtet sich, diesen genauen Preis einzuhalten.
- Das Angebot wurde seit der Erstellung nicht manipuliert.
In der Produktion wäre dies eine kryptografische Signatur mit PKI (Public Key Infrastructure) oder JWT (JSON Web Tokens). In unserem Workshop simulieren wir das mit einem SHA-256-Hash.
# Production (real signature):
signature = sign_with_private_key(cart_data, merchant_private_key)
# Workshop (simulated signature):
cart_hash = hashlib.sha256(cart_json.encode()).hexdigest()
signature = f"SIG_{cart_hash[:16]}"
Unser Ziel: den Händler-Agenten entwickeln
Der Händler-Agent wird:
- IntentMandate aus dem Status lesen (was der Shopping-Agent geschrieben hat)
- Prüfen, ob der Intent abgelaufen ist
- Name der Organisation, Betrag und andere Details extrahieren
- W3C-konforme PaymentRequest-Struktur mit AP2-Pydantic-Modellen erstellen
- In AP2's CartMandate mit Ablaufdatum einfügen
- Simulierte Händlersignatur hinzufügen
- CartMandate für den Anmeldedatenanbieter schreiben (nächstes Modul)
Wir gehen das Schritt für Schritt durch.
Schritt 1: Expiry Validation Helper hinzufügen
Richten wir zuerst die Datei mit den händlerbezogenen Tools ein und fügen wir einen Helfer hinzu, um das Ablaufdatum von IntentMandate zu validieren.
👉 Offen
charity_advisor/tools/merchant_tools.py
Fügen wir die Ablaufvalidierung hinzu:
👉 Finden:
# MODULE_5_STEP_1_ADD_EXPIRY_VALIDATION_HELPER
👉 Ersetzen Sie diese einzelne Zeile durch:
def _validate_intent_expiry(intent_expiry_str: str) -> tuple[bool, str]:
"""
Validates that the IntentMandate hasn't expired.
This is a critical security check - expired intents should not be processed.
Args:
intent_expiry_str: The ISO 8601 timestamp string from the IntentMandate.
Returns:
(is_valid, error_message): Tuple indicating if intent is still valid.
"""
try:
# The .replace('Z', '+00:00') is for compatibility with older Python versions
expiry_time = datetime.fromisoformat(intent_expiry_str.replace('Z', '+00:00'))
now = datetime.now(timezone.utc)
if expiry_time < now:
return False, f"IntentMandate expired at {intent_expiry_str}"
time_remaining = expiry_time - now
logger.info(f"IntentMandate valid. Expires in {time_remaining.total_seconds():.0f} seconds")
return True, ""
except (ValueError, TypeError) as e:
return False, f"Invalid intent_expiry format: {e}"
Schritt 2: Signaturgenerierungs-Helfer hinzufügen
Erstellen wir nun eine Hilfsfunktion, die die simulierte Händlersignatur generiert.
👉 Finden:
# MODULE_5_STEP_2_ADD_SIGNATURE_HELPER
👉 Ersetzen Sie diese einzelne Zeile durch:
def _generate_merchant_signature(cart_contents: CartContents) -> str:
"""
Generates a simulated merchant signature for the CartMandate contents.
In production, this would use PKI or JWT with the merchant's private key.
For this codelab, we use a SHA-256 hash of the sorted JSON representation.
Args:
cart_contents: The Pydantic model of the cart contents to sign.
Returns:
Simulated signature string (format: "SIG_" + first 16 chars of hash).
"""
# Step 1: Dump the Pydantic model to a dictionary. The `mode='json'` argument
# ensures that complex types like datetimes are serialized correctly.
cart_contents_dict = cart_contents.model_dump(mode='json')
# Step 2: Use the standard json library to create a stable, sorted JSON string.
# separators=(',', ':') removes whitespace for a compact and canonical representation.
cart_json = json.dumps(cart_contents_dict, sort_keys=True, separators=(',', ':'))
# Step 3: Generate SHA-256 hash.
cart_hash = hashlib.sha256(cart_json.encode('utf-8')).hexdigest()
# Step 4: Create signature in a recognizable format.
signature = f"SIG_{cart_hash[:16]}"
logger.info(f"Generated merchant signature: {signature}")
return signature
Schritt 3A: Tool-Signatur und Einrichtung erstellen
Jetzt erstellen wir das Haupttool. Wir erstellen sie in vier Schritten. Zuerst die Funktionssignatur und die Ersteinrichtung.
👉 Finden:
# MODULE_5_STEP_3A_CREATE_TOOL_SIGNATURE
👉 Ersetzen Sie diese einzelne Zeile durch:
async def create_cart_mandate(tool_context: Any) -> Dict[str, Any]:
"""
Creates a W3C PaymentRequest-compliant CartMandate from the IntentMandate.
This tool reads the IntentMandate from shared state, validates it, and
creates a formal, signed offer using the official AP2 Pydantic models.
Returns:
Dictionary containing status and the created CartMandate.
"""
logger.info("Tool called: Creating CartMandate from IntentMandate")
# MODULE_5_STEP_3B_ADD_VALIDATION_LOGIC
Schritt 3B: Validierungslogik hinzufügen
Fügen wir nun die Logik hinzu, um das IntentMandate mithilfe von AP2-Pydantic-Modellen zu lesen und zu validieren und die benötigten Daten zu extrahieren.
👉 Finden:
# MODULE_5_STEP_3B_ADD_VALIDATION_LOGIC
👉 Ersetzen Sie diese einzelne Zeile durch:
# 1. Read IntentMandate dictionary from state
intent_mandate_dict = tool_context.state.get("intent_mandate")
if not intent_mandate_dict:
logger.error("No IntentMandate found in state")
return {
"status": "error",
"message": "No IntentMandate found. Shopping Agent must create intent first."
}
# 2. Parse dictionary into a validated Pydantic model
try:
intent_mandate_model = IntentMandate.model_validate(intent_mandate_dict)
except Exception as e:
logger.error(f"Could not validate IntentMandate structure: {e}")
return {"status": "error", "message": f"Invalid IntentMandate structure: {e}"}
# 3. Validate that the intent hasn't expired (CRITICAL security check)
is_valid, error_message = _validate_intent_expiry(intent_mandate_model.intent_expiry)
if not is_valid:
logger.error(f"IntentMandate validation failed: {error_message}")
return {"status": "error", "message": error_message}
# 4. Extract data. Safely access standard fields from the model, and
# custom fields (like 'amount') from the original dictionary.
charity_name = intent_mandate_model.merchants[0] if intent_mandate_model.merchants else "Unknown Charity"
amount = intent_mandate_dict.get("amount", 0.0)
# MODULE_5_STEP_3C_CREATE_CARTMANDATE_STRUCTURE
Schritt 3C: CartMandate-Struktur erstellen
Nun erstellen wir die W3C-konforme PaymentRequest-Struktur und umschließen sie mit dem AP2-CartMandate mithilfe von Pydantic-Modellen.
👉 Finden:
# MODULE_5_STEP_3C_CREATE_CARTMANDATE_STRUCTURE
👉 Ersetzen Sie diese einzelne Zeile durch:
# 5. Build the nested Pydantic models for the CartMandate
timestamp = datetime.now(timezone.utc)
cart_id = f"cart_{hashlib.sha256(f'{charity_name}{timestamp.isoformat()}'.encode()).hexdigest()[:12]}"
cart_expiry = timestamp + timedelta(minutes=15)
payment_request_model = PaymentRequest(
method_data=[PaymentMethodData(
supported_methods="CARD",
data={"supported_networks": ["visa", "mastercard", "amex"], "supported_types": ["debit", "credit"]}
)],
details=PaymentDetailsInit(
id=f"order_{cart_id}",
display_items=[PaymentItem(
label=f"Donation to {charity_name}",
amount=PaymentCurrencyAmount(currency="USD", value=amount) # Pydantic v2 handles float -> str conversion
)],
total=PaymentItem(
label="Total Donation",
amount=PaymentCurrencyAmount(currency="USD", value=amount)
)
),
options=PaymentOptions(request_shipping=False)
)
cart_contents_model = CartContents(
id=cart_id,
cart_expiry=cart_expiry.isoformat(),
merchant_name=charity_name,
user_cart_confirmation_required=False,
payment_request=payment_request_model
)
# MODULE_5_STEP_3D_ADD_SIGNATURE_AND_SAVE
Schritt 3D: Signatur hinzufügen und im Status speichern
Signieren wir nun das CartMandate mit unserem Pydantic-Modell und speichern wir es für den nächsten Agent im Status.
👉 Finden:
# MODULE_5_STEP_3D_ADD_SIGNATURE_AND_SAVE
👉 Ersetzen Sie diese einzelne Zeile durch:
# 6. Generate signature from the validated Pydantic model
signature = _generate_merchant_signature(cart_contents_model)
# 7. Create the final CartMandate model, now including the signature
cart_mandate_model = CartMandate(
contents=cart_contents_model,
merchant_authorization=signature
)
# 8. Convert the final model to a dictionary for state storage and add the custom timestamp
cart_mandate_dict = cart_mandate_model.model_dump(mode='json')
cart_mandate_dict["timestamp"] = timestamp.isoformat()
# 9. Write the final dictionary to state
tool_context.state["cart_mandate"] = cart_mandate_dict
logger.info(f"CartMandate created successfully: {cart_id}")
return {
"status": "success",
"message": f"Created signed CartMandate {cart_id} for ${amount:.2f} donation to {charity_name}",
"cart_id": cart_id,
"cart_expiry": cart_expiry.isoformat(),
"signature": signature
}
Schritt 4: Händler-Agent erstellen – Komponenten importieren
Jetzt erstellen wir den Agent, der dieses Tool verwenden wird.
👉 Offen
charity_advisor/merchant_agent/agent.py
Es wird eine Vorlage mit Platzhaltermarkierungen angezeigt. Beginnen wir mit dem Import der erforderlichen Bibliotheken.
👉 Finden:
# MODULE_5_STEP_4_IMPORT_COMPONENTS
👉 Ersetzen Sie diese einzelne Zeile durch:
from google.adk.agents import Agent
from google.adk.tools import FunctionTool
from charity_advisor.tools.merchant_tools import create_cart_mandate
Schritt 5: Händler-Agent-Anweisung schreiben
Als Nächstes schreiben wir die Anleitung, die dem Agent mitteilt, wann und wie er sein Tool verwenden soll.
👉 Finden:
# MODULE_5_STEP_5_WRITE_INSTRUCTION
instruction="""""",
👉 Ersetzen Sie diese beiden Zeilen durch:
instruction="""You are a merchant specialist responsible for creating formal, signed offers (CartMandates).
Your workflow:
1. Read the IntentMandate from shared state.
The IntentMandate was created by the Shopping Agent and contains:
- merchants: List of merchant names
- amount: Donation amount
- charity_ein: Tax ID
- intent_expiry: When the intent expires
2. Use the create_cart_mandate tool to create a W3C PaymentRequest-compliant CartMandate.
This tool will:
- Validate the IntentMandate hasn't expired (CRITICAL security check)
- Extract the charity name and amount from the IntentMandate
- Create a structured offer with payment methods, transaction details, and merchant info
- Generate a merchant signature to prove authenticity
- Save the CartMandate to state for the payment processor
3. After creating the CartMandate, inform the user:
- That you've created a formal, signed offer
- The cart ID
- When the cart expires (15 minutes)
- That you're passing it to the secure payment processor
IMPORTANT BOUNDARIES:
- Your ONLY job is creating signed CartMandates from valid IntentMandates
- You do NOT process payments
- You do NOT see the user's payment methods or credentials
- You do NOT interact with payment networks
- You MUST validate that the IntentMandate hasn't expired before creating a cart
- After calling create_cart_mandate, your work is done
WHAT IS A CARTMANDATE:
A CartMandate is a binding commitment that says:
"I, the merchant, commit to accepting $X for this charity donation, and I prove it with my signature."
This commitment is structured using the W3C PaymentRequest standard and includes:
- Payment methods accepted (card, bank transfer)
- Transaction details (amount, charity name)
- Cart expiry (15 minutes from creation)
- Merchant signature (proof of commitment)
This is the second of three verifiable credentials in our secure payment system.""",
Schritt 6: Tools dem Händler-Agent hinzufügen
👉 Finden:
# MODULE_5_STEP_6_ADD_TOOLS
tools=[],
👉 Ersetzen Sie diese beiden Zeilen durch:
tools=[
FunctionTool(func=create_cart_mandate)
],
Schritt 7: Complete Merchant Agent überprüfen
Wir möchten sichergehen, dass alles richtig verkabelt ist.
👉 Vollständige
charity_advisor/merchant_agent/agent.py
sollte jetzt so aussehen:
"""
Merchant Agent - Creates W3C-compliant CartMandates with merchant signatures.
This agent acts as our "Contract Creator."
"""
from google.adk.agents import Agent
from google.adk.tools import FunctionTool
from charity_advisor.tools.merchant_tools import create_cart_mandate
merchant_agent = Agent(
name="MerchantAgent",
model="gemini-2.5-flash",
description="Creates formal, signed CartMandates for charity donations following W3C PaymentRequest standards.",
tools=[
FunctionTool(func=create_cart_mandate)
],
instruction="""You are a merchant specialist responsible for creating formal, signed offers (CartMandates).
Your workflow:
1. Read the IntentMandate from shared state.
The IntentMandate was created by the Shopping Agent and contains:
- merchants: List of merchant names
- amount: Donation amount
- charity_ein: Tax ID
- intent_expiry: When the intent expires
2. Use the create_cart_mandate tool to create a W3C PaymentRequest-compliant CartMandate.
This tool will:
- Validate the IntentMandate hasn't expired (CRITICAL security check)
- Extract the charity name and amount from the IntentMandate
- Create a structured offer with payment methods, transaction details, and merchant info
- Generate a merchant signature to prove authenticity
- Save the CartMandate to state for the payment processor
3. After creating the CartMandate, inform the user:
- That you've created a formal, signed offer
- The cart ID
- When the cart expires (15 minutes)
- That you're passing it to the secure payment processor
IMPORTANT BOUNDARIES:
- Your ONLY job is creating signed CartMandates from valid IntentMandates
- You do NOT process payments
- You do NOT see the user's payment methods or credentials
- You do NOT interact with payment networks
- You MUST validate that the IntentMandate hasn't expired before creating a cart
- After calling create_cart_mandate, your work is done
WHAT IS A CARTMANDATE:
A CartMandate is a binding commitment that says:
"I, the merchant, commit to accepting $X for this charity donation, and I prove it with my signature."
This commitment is structured using the W3C PaymentRequest standard and includes:
- Payment methods accepted (card, bank transfer)
- Transaction details (amount, charity name)
- Cart expiry (15 minutes from creation)
- Merchant signature (proof of commitment)
This is the second of three verifiable credentials in our secure payment system."""
)
✅ Prüfpunkt: Sie haben jetzt einen vollständigen Merchant Agent mit der richtigen AP2-CartMandate-Erstellung mithilfe von Pydantic-Modellen.
Schritt 8: Händler-Agent testen
Prüfen wir nun, ob unser Agent CartMandates mit Signaturen korrekt erstellt und das Ablaufdatum validiert.
Test einrichten: Testskript ausführen
👉 Führen Sie in Ihrem Cloud Shell-Terminal Folgendes aus:
python scripts/test_merchant.py
Erwartete Ausgabe:
======================================================================
MERCHANT AGENT TEST
======================================================================
Simulated IntentMandate from Shopping Agent:
charity: Room to Read
amount: $50.00
expiry: 2024-11-07T16:32:16Z
----------------------------------------------------------------------
Merchant Agent Response:
----------------------------------------------------------------------
Perfect! I've received your IntentMandate and created a formal, signed offer (CartMandate) for your donation.
**CartMandate Details:**
- **Cart ID**: cart_3b4c5d6e7f8a
- **Donation Amount**: $50.00 to Room to Read
- **Payment Methods Accepted**: Credit/debit cards (Visa, Mastercard, Amex) or bank transfer
- **Cart Expires**: 2024-11-07T15:47:16Z (in 15 minutes)
- **Merchant Signature**: SIG_a3f7b2c8d9e1f4a2
This signed CartMandate proves my commitment to accept this donation amount. I'm now passing this to the secure payment processor to complete your transaction.
======================================================================
CARTMANDATE CREATED:
======================================================================
ID: cart_3b4c5d6e7f8a
Amount: 50.00
Merchant: Room to Read
Expires: 2024-11-07T15:47:16Z
Signature: SIG_a3f7b2c8d9e1f4a2
======================================================================
Test 2: W3C-Compliance prüfen
Wir prüfen, ob unsere CartMandate-Struktur sowohl den AP2- als auch den W3C PaymentRequest-Standards entspricht.
👉 Validierungsskript ausführen:
python scripts/validate_cartmandate.py
Erwartete Ausgabe:
======================================================================
AP2 & W3C PAYMENTREQUEST VALIDATION
======================================================================
✅ CartMandate is AP2 and W3C PaymentRequest compliant
Structure validation passed:
✓ AP2 'contents' wrapper present
✓ AP2 'merchant_authorization' signature present
✓ cart_expiry present
✓ payment_request nested inside contents
✓ method_data present and valid
✓ details.total.amount present with currency and value
✓ All required W3C PaymentRequest fields present
======================================================================
Was Sie gerade erstellt haben
Sie haben das CartMandate von AP2 mithilfe von Pydantic-Modellen für die richtige Struktur, die Ablaufvalidierung und Händlersignaturen erfolgreich implementiert.
Beherrschte Schlüsselkonzepte
✅ CartMandate (AP2-Anmeldedaten 2):
- Mit offiziellen AP2-Pydantic-Modellen erstellt
- AP2-Struktur mit Inhalts-Wrapper
- W3C PaymentRequest eingebettet in
- Ablauf des Einkaufswagens (kürzer als die Intention)
- Unterschrift des Händlers für verbindliche Zusicherung
- Modellvalidierung sorgt für die Einhaltung der Spezifikationen
✅ Ablaufdatum:
- IntentMandate aus dem Status lesen
- Struktur mit
IntentMandate.model_validate()validieren - ISO 8601-Zeitstempel parsen
- Mit der aktuellen Zeit vergleichen
- Sicherheitsfunktion zur Verhinderung der Verarbeitung veralteter Daten
✅ Unterschrift des Händlers:
- Beweist Authentizität und Engagement
- Aus validiertem Pydantic-Modell generiert
- Verwendet
model_dump(mode='json')für die kanonische Darstellung - Mit SHA-256 für Bildungseinrichtungen simuliert
- In der Produktionsphase wird PKI/JWT verwendet
- Signiert das Inhaltsmodell, nicht Wörterbücher
✅ W3C PaymentRequest:
- Erstellt mit dem Pydantic-Modell „PaymentRequest“ von AP2
- Branchenstandard für Zahlungsdaten
- Verschachtelt in der AP2-Struktur
- Enthält method_data, details, options
- Interoperabilität wird ermöglicht
✅ Anmeldedatenkette mit Modellen:
- Shopping → IntentMandate (validiert)
- Händler liest IntentMandate → CartMandate (beide Modelle validiert)
- Der Anmeldeinformationsanbieter liest CartMandate → PaymentMandate
- In jedem Schritt wird der vorherige Berechtigungsnachweis mit Pydantic validiert.
✅ Modellgetriebene Entwicklung:
- Eingabevalidierung über
model_validate() - Typsichere Konstruktion
- Automatische Serialisierung über
model_dump() - Produktionsreife Muster
Weitere Informationen
Im nächsten Modul erstellen wir den Credentials Provider, um Zahlungen sicher zu verarbeiten.
Der Händler-Agent hat mit AP2-Modellen ein verbindliches Angebot mit Ablaufdatum erstellt. Jetzt benötigen wir einen Agent, der dieses CartMandate liest, die Nutzereinwilligung einholt und die Zahlung ausführt.
Wir erstellen den Anmeldeinformationsanbieter und schließen die AP2-Anmeldeinformationskette ab.
6. Anmeldedatenanbieter erstellen – Sichere Zahlungsausführung

Vom verbindlichen Angebot zur Zahlungsausführung
In Modul 5 haben Sie den Merchant Agent erstellt, einen Spezialisten, der IntentMandates liest, prüft, ob sie abgelaufen sind, und verbindliche CartMandates mit Händlersignaturen erstellt. Jetzt benötigen wir einen Agenten, der dieses CartMandate empfängt und die eigentliche Zahlung ausführt.
Hier kommt der dritte und letzte Grundsatz von AP2 ins Spiel: sichere Zahlungsausführung über PaymentMandate.
AP2-Grundsatz: Zahlungsauftrag und Zahlungsausführung
Warum benötigen wir eine Rolle für Anmeldeinformationsanbieter?
Im Modul 5 hat der Händler-Agent ein CartMandate erstellt und im Status gespeichert:
state["cart_mandate"] = {
"contents": {
"id": "cart_abc123",
"cart_expiry": "2025-11-07:15:47:16Z",
"payment_request": {
"details": {
"total": {
"amount": {"currency": "USD", "value": "50.00"}
}
}
}
},
"merchant_authorization": "SIG_a3f7b2c8"
}
Das ist aber nur ein verbindliches Angebot. Bevor die Zahlung ausgeführt werden kann, benötigen wir Folgendes:
- Prüfen, ob der Einkaufswagen abgelaufen ist
- Nutzereinwilligung zur Fortsetzung der Zahlung
- Anmeldedaten, die die Ausführung von Zahlungen autorisieren
- Tatsächliche Zahlungsabwicklung (oder Simulation für unseren Workshop)
Das ist die Aufgabe des Anbieters von Anmeldedaten.
Was ist ein Zahlungsauftrag?
Ein PaymentMandate ist der Begriff von AP2 für die endgültige Autorisierung, die die Ausführung der Zahlung ermöglicht. Es ist die dritte und letzte überprüfbare Berechtigung in der AP2-Kette.
Stellen Sie sich die drei Anmeldedaten wie einen Vertragsunterzeichnungsprozess vor:
- IntentMandate: „Ich möchte das kaufen“ (Absichtserklärung)
- CartMandate: „Ich, der Händler, biete an, zu diesem Preis zu verkaufen.“ (Schriftliches Angebot)
- PaymentMandate: „Ich ermächtige Sie, meine Zahlungsmethode zu belasten“ (unterzeichneter Vertrag)
Die Zahlung kann erst ausgeführt werden, wenn alle drei Anmeldedaten vorhanden sind.
Struktur eines Zahlungsauftrags
Ein PaymentMandate in AP2 hat eine bestimmte Struktur:
payment_mandate = {
"payment_mandate_contents": { # ← AP2 wrapper
"payment_mandate_id": "payment_xyz123",
"payment_details_id": "cart_abc123", # Links to CartMandate
"user_consent": True,
"consent_timestamp": "2025-11-07T15:48:00Z",
"amount": {
"currency": "USD",
"value": "50.00"
},
"merchant_name": "Room to Read"
},
"agent_present": True, # Human-in-the-loop flow
"timestamp": "2025-11-07T15:48:00Z"
}
Wichtige Komponenten:
1. payment_mandate_contents: Der Autorisierungs-Wrapper mit folgenden Informationen:
- payment_mandate_id: Eindeutige Kennung
- payment_details_id: Link zurück zu CartMandate
- user_consent: Gibt an, ob der Nutzer zugestimmt hat.
- amount: Zahlungsbetrag (aus CartMandate extrahiert)
2. agent_present: Gibt an, ob es sich um einen Human-in-the-Loop-Ablauf handelt.
3. timestamp: Zeitpunkt der Autorisierung
Unser Ziel: Anmeldeinformationsanbieter entwickeln
Der Anmeldedatenanbieter führt folgende Aktionen aus:
- Lesen Sie das CartMandate aus dem Status (was der Merchant Agent geschrieben hat).
- Prüfen, ob der Einkaufswagen mit AP2-Pydantic-Modellen abgelaufen ist
- Zahlungsdetails aus der verschachtelten Struktur extrahieren
- Zahlungsmandat mit Nutzereinwilligung mit AP2-Modellen erstellen
- Zahlungsabwicklung simulieren (in der Produktion würde die echte Zahlungs-API aufgerufen)
- PaymentMandate und Zahlungsergebnis in den Status schreiben
Wir gehen das Schritt für Schritt durch.
Schritt 1: Cart Expiry Validation Helper hinzufügen
Erstellen wir zuerst eine Hilfsfunktion, die prüft, ob das CartMandate abgelaufen ist. Das ist ähnlich wie beim Ablauf von IntentMandate in Modul 5.
👉 Offen
charity_advisor/tools/payment_tools.py
Fügen wir die Ablaufvalidierung hinzu:
👉 Finden:
# MODULE_6_STEP_1_ADD_CART_EXPIRY_VALIDATION_HELPER
👉 Ersetzen Sie diese einzelne Zeile durch:
def _validate_cart_expiry(cart: CartMandate) -> tuple[bool, str]:
"""
Validates that the CartMandate hasn't expired.
This is a critical security check - expired carts should not be processed.
Args:
cart: The Pydantic CartMandate model to validate.
Returns:
(is_valid, error_message): Tuple indicating if cart is still valid.
"""
try:
expiry_str = cart.contents.cart_expiry
expiry_time = datetime.fromisoformat(expiry_str.replace('Z', '+00:00'))
now = datetime.now(timezone.utc)
if expiry_time < now:
return False, f"CartMandate expired at {expiry_str}"
time_remaining = expiry_time - now
logger.info(f"CartMandate valid. Expires in {time_remaining.total_seconds():.0f} seconds")
return True, ""
except (ValueError, TypeError, AttributeError) as e:
return False, f"Invalid cart_expiry format or structure: {e}"
Schritt 2: PaymentMandate Creation Helper hinzufügen
Erstellen wir nun einen Helfer, der die PaymentMandate-Struktur mit offiziellen AP2-Pydantic-Modellen erstellt.
👉 Finden:
# MODULE_6_STEP_2_ADD_PAYMENT_MANDATE_CREATION_HELPER
👉 Ersetzen Sie diese einzelne Zeile durch:
def _create_payment_mandate(cart: CartMandate, consent_granted: bool) -> dict:
"""
Creates a PaymentMandate using the official AP2 Pydantic models.
It links to the CartMandate and includes user consent status.
Args:
cart: The validated Pydantic CartMandate model being processed.
consent_granted: Whether the user has consented to the payment.
Returns:
A dictionary representation of the final, validated PaymentMandate.
"""
timestamp = datetime.now(timezone.utc)
# Safely extract details from the validated CartMandate model
cart_id = cart.contents.id
merchant_name = cart.contents.merchant_name
total_item = cart.contents.payment_request.details.total
# Create the nested PaymentResponse model for the mandate
payment_response_model = PaymentResponse(
request_id=cart_id,
method_name="CARD", # As per the simulated flow
details={"token": "simulated_payment_token_12345"}
)
# Create the PaymentMandateContents model
payment_mandate_contents_model = PaymentMandateContents(
payment_mandate_id=f"payment_{hashlib.sha256(f'{cart_id}{timestamp.isoformat()}'.encode()).hexdigest()[:12]}",
payment_details_id=cart_id,
payment_details_total=total_item,
payment_response=payment_response_model,
merchant_agent=merchant_name,
timestamp=timestamp.isoformat()
)
# Create the top-level PaymentMandate model
# In a real system, a user signature would be added to this model
payment_mandate_model = PaymentMandate(
payment_mandate_contents=payment_mandate_contents_model
)
# Convert the final Pydantic model to a dictionary for state storage
final_dict = payment_mandate_model.model_dump(mode='json')
# Add any custom/non-standard fields required by the codelab's logic to the dictionary
# The spec does not have these fields, but your original code did. We add them
# back to ensure compatibility with later steps.
final_dict['payment_mandate_contents']['user_consent'] = consent_granted
final_dict['payment_mandate_contents']['consent_timestamp'] = timestamp.isoformat() if consent_granted else None
final_dict['agent_present'] = True
return final_dict
Schritt 3A: Tool-Signatur und Einrichtung erstellen
Jetzt können wir das Haupttool schrittweise erstellen. Zuerst die Funktionssignatur und die Ersteinrichtung.
👉 Finden:
# MODULE_6_STEP_3A_CREATE_TOOL_SIGNATURE
👉 Ersetzen Sie diese einzelne Zeile durch:
async def create_payment_mandate(tool_context: Any) -> Dict[str, Any]:
"""
Creates a PaymentMandate and simulates payment processing using Pydantic models.
This tool now reads the CartMandate from state, parses it into a validated model,
and creates a spec-compliant PaymentMandate.
"""
logger.info("Tool called: Creating PaymentMandate and processing payment")
# MODULE_6_STEP_3B_VALIDATE_CARTMANDATE
Schritt 3B: CartMandate validieren
Fügen wir nun die Logik hinzu, um das CartMandate mithilfe von AP2-Pydantic-Modellen zu lesen und zu validieren und das Ablaufdatum zu prüfen.
👉 Finden:
# MODULE_6_STEP_3B_VALIDATE_CARTMANDATE
👉 Ersetzen Sie diese einzelne Zeile durch:
# 1. Read CartMandate dictionary from state
cart_mandate_dict = tool_context.state.get("cart_mandate")
if not cart_mandate_dict:
logger.error("No CartMandate found in state")
return { "status": "error", "message": "No CartMandate found. Merchant Agent must create cart first." }
# 2. Parse dictionary into a validated Pydantic model
try:
cart_model = CartMandate.model_validate(cart_mandate_dict)
except Exception as e:
logger.error(f"Could not validate CartMandate structure: {e}")
return {"status": "error", "message": f"Invalid CartMandate structure: {e}"}
# 3. Validate that the cart hasn't expired using the Pydantic model
is_valid, error_message = _validate_cart_expiry(cart_model)
if not is_valid:
logger.error(f"CartMandate validation failed: {error_message}")
return {"status": "error", "message": error_message}
# MODULE_6_STEP_3C_EXTRACT_PAYMENT_DETAILS
Schritt 3C: Zahlungsdetails aus verschachtelter Struktur extrahieren
Sehen wir uns nun das validierte CartMandate-Modell an, um die benötigten Zahlungsdetails zu extrahieren.
👉 Finden:
# MODULE_6_STEP_3C_EXTRACT_PAYMENT_DETAILS
👉 Ersetzen Sie diese einzelne Zeile durch:
# 4. Safely extract data from the validated model
cart_id = cart_model.contents.id
merchant_name = cart_model.contents.merchant_name
amount_value = cart_model.contents.payment_request.details.total.amount.value
currency = cart_model.contents.payment_request.details.total.amount.currency
consent_granted = True # Assume consent for this codelab flow
# MODULE_6_STEP_3D_CREATE_PAYMENTMANDATE_AND_SIMULATE
Schritt 3D: PaymentMandate erstellen und Zahlung simulieren
Erstellen wir nun das PaymentMandate mit unserem Pydantic-basierten Helfer, simulieren wir die Zahlungsabwicklung und speichern wir alles im Status.
👉 Finden:
# MODULE_6_STEP_3D_CREATE_PAYMENTMANDATE_AND_SIMULATE
👉 Ersetzen Sie diese einzelne Zeile durch:
# 5. Create the spec-compliant PaymentMandate using the validated CartMandate model
payment_mandate_dict = _create_payment_mandate(cart_model, consent_granted)
# 6. Simulate payment processing
transaction_id = f"txn_{hashlib.sha256(f'{cart_id}{datetime.now(timezone.utc).isoformat()}'.encode()).hexdigest()[:16]}"
payment_result = {
"transaction_id": transaction_id,
"status": "completed",
"amount": amount_value,
"currency": currency,
"merchant": merchant_name,
"timestamp": datetime.now(timezone.utc).isoformat(),
"simulation": True
}
# 7. Write the compliant PaymentMandate dictionary and result to state
tool_context.state["payment_mandate"] = payment_mandate_dict
tool_context.state["payment_result"] = payment_result
logger.info(f"Payment processed successfully: {transaction_id}")
return {
"status": "success",
"message": f"Payment of {currency} {amount_value:.2f} to {merchant_name} processed successfully",
"transaction_id": transaction_id,
"payment_mandate_id": payment_mandate_dict["payment_mandate_contents"]["payment_mandate_id"]
}
Schritt 4: Credentials Provider Agent erstellen – Komponenten importieren
Jetzt erstellen wir den Agent, der dieses Tool verwendet.
👉 Offen
charity_advisor/credentials_provider/agent.py
Es wird eine Vorlage mit Platzhaltermarkierungen angezeigt. Beginnen wir mit dem Import der erforderlichen Bibliotheken.
👉 Finden:
# MODULE_6_STEP_4_IMPORT_COMPONENTS
👉 Ersetzen Sie diese einzelne Zeile durch:
from google.adk.agents import Agent
from google.adk.tools import FunctionTool
from charity_advisor.tools.payment_tools import create_payment_mandate
Schritt 5: Anweisung für den Anmeldedatenanbieter schreiben
Schreiben wir nun die Anleitung, die den Agenten leitet.
👉 Finden:
# MODULE_6_STEP_5_WRITE_INSTRUCTION
instruction="""""",
👉 Ersetzen Sie diese beiden Zeilen durch:
instruction="""You are a payment specialist responsible for securely processing payments with user consent.
Your workflow:
1. Read the CartMandate from shared state.
The CartMandate was created by the Merchant Agent and has this structure:
- contents: AP2 wrapper containing:
- id: Cart identifier
- cart_expiry: When the cart expires
- merchant_name: Who is receiving payment
- payment_request: W3C PaymentRequest with transaction details
- merchant_authorization: Merchant's signature
2. Extract payment details from the nested structure:
- Navigate: cart_mandate["contents"]["payment_request"]["details"]["total"]["amount"]
- This gives you the currency and value
3. **IMPORTANT - Two-Turn Conversational Confirmation Pattern:**
Before calling create_payment_mandate, you MUST:
- Present the payment details clearly to the user
- Ask explicitly: "I'm ready to process a payment of $X to [Charity Name]. Do you want to proceed with this donation?"
- WAIT for the user's explicit confirmation (e.g., "yes", "proceed", "confirm")
- ONLY call create_payment_mandate AFTER receiving explicit confirmation
- If user says "no" or "cancel", DO NOT call the tool
4. After user confirms, use the create_payment_mandate tool to:
- Validate the CartMandate hasn't expired (CRITICAL security check)
- Create a PaymentMandate (the third AP2 credential)
- Simulate payment processing
- Record the transaction result
5. After processing, inform the user:
- That payment was processed successfully (this is a simulation)
- The transaction ID
- The amount and merchant
- That this completes the three-agent AP2 credential chain
IMPORTANT BOUNDARIES:
- Your ONLY job is creating PaymentMandates and processing payments
- You do NOT discover charities (that's Shopping Agent's job)
- You do NOT create offers (that's Merchant Agent's job)
- You MUST validate that the CartMandate hasn't expired before processing
- You MUST get explicit user confirmation before calling create_payment_mandate
- In production, this consent mechanism would be even more robust
WHAT IS A PAYMENTMANDATE:
A PaymentMandate is the final credential that authorizes payment execution. It:
- Links to the CartMandate (proving the merchant's offer)
- Records user consent
- Contains payment details extracted from the CartMandate
- Enables the actual payment transaction
This is the third and final verifiable credential in our secure payment system.
THE COMPLETE AP2 CREDENTIAL CHAIN:
1. Shopping Agent creates IntentMandate (user's intent)
2. Merchant Agent reads IntentMandate, creates CartMandate (merchant's binding offer)
3. You read CartMandate, get user confirmation, create PaymentMandate (authorized payment execution)
Each credential:
- Has an expiry time (security feature)
- Links to the previous credential
- Is validated before the next step
- Creates an auditable chain of trust""",
Schritt 6: Tools zum Anmeldedatenanbieter hinzufügen
👉 Finden:
# MODULE_6_STEP_6_ADD_TOOLS
tools=[],
👉 Ersetzen Sie diese beiden Zeilen durch:
tools=[
FunctionTool(func=create_payment_mandate)
],
Schritt 7: Anbieter für vollständige Anmeldedaten bestätigen
Wir möchten sichergehen, dass alles richtig verkabelt ist.
👉 Vollständige
charity_advisor/credentials_provider/agent.py
sollte jetzt so aussehen:
"""
Credentials Provider Agent - Handles payment processing with user consent.
This agent acts as our "Payment Processor."
"""
from google.adk.agents import Agent
from google.adk.tools import FunctionTool
from charity_advisor.tools.payment_tools import create_payment_mandate
credentials_provider = Agent(
name="CredentialsProvider",
model="gemini-2.5-flash",
description="Securely processes payments by creating PaymentMandates and executing transactions with user consent.",
tools=[
FunctionTool(func=create_payment_mandate)
],
instruction="""You are a payment specialist responsible for securely processing payments with user consent.
Your workflow:
1. Read the CartMandate from shared state.
The CartMandate was created by the Merchant Agent and has this structure:
- contents: AP2 wrapper containing:
- id: Cart identifier
- cart_expiry: When the cart expires
- merchant_name: Who is receiving payment
- payment_request: W3C PaymentRequest with transaction details
- merchant_authorization: Merchant's signature
2. Extract payment details from the nested structure:
- Navigate: cart_mandate["contents"]["payment_request"]["details"]["total"]["amount"]
- This gives you the currency and value
3. **IMPORTANT - Two-Turn Conversational Confirmation Pattern:**
Before calling create_payment_mandate, you MUST:
- Present the payment details clearly to the user
- Ask explicitly: "I'm ready to process a payment of $X to [Charity Name]. Do you want to proceed with this donation?"
- WAIT for the user's explicit confirmation (e.g., "yes", "proceed", "confirm")
- ONLY call create_payment_mandate AFTER receiving explicit confirmation
- If user says "no" or "cancel", DO NOT call the tool
4. After user confirms, use the create_payment_mandate tool to:
- Validate the CartMandate hasn't expired (CRITICAL security check)
- Create a PaymentMandate (the third AP2 credential)
- Simulate payment processing
- Record the transaction result
5. After processing, inform the user:
- That payment was processed successfully (this is a simulation)
- The transaction ID
- The amount and merchant
- That this completes the three-agent AP2 credential chain
IMPORTANT BOUNDARIES:
- Your ONLY job is creating PaymentMandates and processing payments
- You do NOT discover charities (that's Shopping Agent's job)
- You do NOT create offers (that's Merchant Agent's job)
- You MUST validate that the CartMandate hasn't expired before processing
- You MUST get explicit user confirmation before calling create_payment_mandate
- In production, this consent mechanism would be even more robust
WHAT IS A PAYMENTMANDATE:
A PaymentMandate is the final credential that authorizes payment execution. It:
- Links to the CartMandate (proving the merchant's offer)
- Records user consent
- Contains payment details extracted from the CartMandate
- Enables the actual payment transaction
This is the third and final verifiable credential in our secure payment system.
THE COMPLETE AP2 CREDENTIAL CHAIN:
1. Shopping Agent creates IntentMandate (user's intent)
2. Merchant Agent reads IntentMandate, creates CartMandate (merchant's binding offer)
3. You read CartMandate, get user confirmation, create PaymentMandate (authorized payment execution)
Each credential:
- Has an expiry time (security feature)
- Links to the previous credential
- Is validated before the next step
- Creates an auditable chain of trust"""
)
✅ Checkpoint: Sie haben jetzt einen vollständigen Anmeldedatenanbieter mit dem richtigen Lesen von CartMandate und der Erstellung von PaymentMandate mithilfe von AP2-Pydantic-Modellen.
Schritt 8: Anmeldedatenanbieter testen
Wir prüfen nun, ob unser Agent Zahlungen korrekt verarbeitet und die Anmeldedatenkette vervollständigt.
👉 Führen Sie in Ihrem Cloud Shell-Terminal Folgendes aus:
python scripts/test_credentials_provider.py
Erwartete Ausgabe:
======================================================================
CREDENTIALS PROVIDER TEST (MOCK - NO CONFIRMATION)
======================================================================
Simulated CartMandate from Merchant Agent:
- Cart ID: cart_test123
- Merchant: Room to Read
- Amount: $50.00
- Expires: 2025-11-07T15:47:16Z
- Signature: SIG_test_signature
Calling Credentials Provider to process payment...
======================================================================
INFO:charity_advisor.tools.payment_tools:Tool called: Creating PaymentMandate and processing payment
INFO:charity_advisor.tools.payment_tools:CartMandate valid. Expires in 900 seconds
INFO:charity_advisor.tools.payment_tools:Payment processed successfully: txn_a3f7b2c8d9e1f4a2
======================================================================
CREDENTIALS PROVIDER RESPONSE:
======================================================================
I've successfully processed your payment. Here are the details:
**Payment Completed** (Simulated)
- Transaction ID: txn_a3f7b2c8d9e1f4a2
- Amount: USD 50.00
- Merchant: Room to Read
- Status: Completed
This completes the three-agent AP2 credential chain:
1. ✓ Shopping Agent created IntentMandate (your intent)
2. ✓ Merchant Agent created CartMandate (binding offer)
3. ✓ Credentials Provider created PaymentMandate (payment authorization)
Your donation has been processed securely through our verifiable credential system.
======================================================================
PAYMENTMANDATE CREATED:
======================================================================
Payment Mandate ID: payment_3b4c5d6e7f8a
Linked to Cart: cart_test123
User Consent: True
Amount: USD 50.00
Merchant: Room to Read
Agent Present: True
======================================================================
======================================================================
PAYMENT RESULT:
======================================================================
Transaction ID: txn_a3f7b2c8d9e1f4a2
Status: completed
Amount: USD 50.00
Merchant: Room to Read
Simulation: True
======================================================================
Schritt 9: Vollständige Pipeline mit drei Agents testen
Jetzt testen wir, wie alle drei Agenten zusammenarbeiten.
👉 Vollständigen Pipeline-Test ausführen:
python scripts/test_full_pipeline.py
Erwartete Ausgabe:
======================================================================
THREE-AGENT PIPELINE TEST (AP2 CREDENTIAL CHAIN)
======================================================================
[1/3] SHOPPING AGENT - Finding charity and creating IntentMandate...
----------------------------------------------------------------------
✓ IntentMandate created
- Intent ID: intent_774799058_1730927536
- Description: Donate $75.00 to Room to Read
- Merchant: Room to Read
- Amount: $75.0
- Expires: 2025-11-07T16:32:16Z
[2/3] MERCHANT AGENT - Reading IntentMandate and creating CartMandate...
----------------------------------------------------------------------
✓ CartMandate created
- ID: cart_3b4c5d6e7f8a
- Expires: 2025-11-07T15:47:16Z
- Signature: SIG_a3f7b2c8d9e1f4a2
[3/3] CREDENTIALS PROVIDER - Creating PaymentMandate and processing...
----------------------------------------------------------------------
NOTE: In the web UI, this would show a confirmation dialog
For this test, consent is automatically granted
✓ Payment processed (SIMULATED)
- Transaction ID: txn_a3f7b2c8d9e1f4a2
- Amount: $75.0
- Status: completed
======================================================================
COMPLETE AP2 CREDENTIAL CHAIN
======================================================================
✓ Credential 1: IntentMandate (User's Intent)
- Intent ID: intent_774799058_1730927536
- Description: Donate $75.00 to Room to Read
- Expiry: 2025-11-07T16:32:16Z
✓ Credential 2: CartMandate (Merchant's Offer)
- Cart ID: cart_3b4c5d6e7f8a
- Cart Expiry: 2025-11-07T15:47:16Z
- Merchant Signature: SIG_a3f7b2c8d9e1f4a2
✓ Credential 3: PaymentMandate (Payment Execution)
- Payment Mandate ID: payment_3b4c5d6e7f8a
- Linked to Cart: cart_3b4c5d6e7f8a
- Agent Present: True
✓ Transaction Result:
- Transaction ID: txn_a3f7b2c8d9e1f4a2
- Simulation: True
======================================================================
✅ COMPLETE PIPELINE TEST PASSED
======================================================================
Das ist die vollständige AP2-Anmeldedatenkette in Aktion.
Für jeden Kundenservicemitarbeiter gilt:
- Liest Anmeldedaten aus dem Status
- Validiert sie mithilfe von Pydantic-Modellen (Struktur + Ablaufdatum)
- Erstellt die nächste Anmeldedaten mit AP2-Modellen
- Schreibt in den Status für den nächsten Agent
Was Sie gerade erstellt haben
Sie haben die AP2-Anmeldedatenkette mit drei Agents erfolgreich abgeschlossen und dabei die Struktur mithilfe von Pydantic-Modellen validiert und eine Zahlung simuliert.
Beherrschte Schlüsselkonzepte
✅ PaymentMandate (AP2 Credential #3):
- Mit offiziellen AP2-Pydantic-Modellen erstellt
- Letzte Anmeldedaten zur Autorisierung der Zahlungsausführung
- Links zu CartMandate über payment_details_id
- Nutzereinwilligung und Zeitstempel werden aufgezeichnet
- Enthält den Zahlungsbetrag, der aus CartMandate extrahiert wurde.
- Enthält das Flag „agent_present“ für Human in the Loop
- Modellvalidierung sorgt für die Einhaltung der Spezifikationen
✅ Aus CartMandate lesen:
- Struktur mit
CartMandate.model_validate()validieren - Typsicherer Attributzugriff:
cart_model.contents.payment_request.details.total.amount - AP2-Wrapper im Vergleich zur W3C-Standardtrennung
- Händlername, Betrag und Währung sicher aus dem Modell extrahieren
- Pydantic erkennt Strukturfehler automatisch
✅ Ablauf des Warenkorbs prüfen:
- Akzeptiert validiertes
CartMandate-Pydantic-Modell - Liest aus
cart.contents.cart_expiry(Attributzugriff) - Sicherheitsfunktion, die die Verarbeitung veralteter Warenkörbe verhindert
- Kürzere Dauer (15 Minuten) als Intention (1 Stunde)
✅ Zahlungssimulation:
- Bildungsmockup eines echten Zahlungsabwicklers
- Transaktions-ID wird generiert
- Speichert payment_result im Status
- Eindeutig als Simulation gekennzeichnet („simulation: True“-Flag)
✅ Vollständige AP2-Kette mit Modellen:
- Drei Agents, drei Anmeldedaten, drei Pydantic-Validierungen
- Jeder Agent validiert die Struktur des vorherigen Anmeldedaten mithilfe von Modellen.
- Jede Anmeldedaten verweist zur Nachvollziehbarkeit auf die vorherigen.
- Statusbasierte Übergaben wahren die Rollentrennung
- Typsicherheit in der gesamten Kette
✅ Modellgetriebene Entwicklung:
- Eingabevalidierung über
model_validate() - Typsichere Konstruktion mit verschachtelten Modellen
- Automatische Serialisierung über
model_dump(mode='json') - Von Anfang an produktionsreife Muster
Weitere Informationen
Im nächsten Modul erstellen wir den Orchestrator-Agent, der alle drei Spezialisten-Agents koordiniert.
Sie haben drei leistungsstarke Spezialisten-Agents mit AP2-Pydantic-Modellen erstellt. Jetzt erstellen wir den Dirigenten, der sie zu einem nahtlosen Spendenprozess zusammenführt.
Wir erstellen den Orchestrator und sehen uns das vollständige System in Aktion an.
7. Orchestrierung – Alles an einem Ort
Von Spezialisten zu nahtlosen Abläufen
In den vorherigen Modulen haben Sie drei spezialisierte Agents erstellt:
- Shopping-Agent: Findet Wohltätigkeitsorganisationen, erstellt IntentMandate
- Merchant Agent: Erstellt CartMandate aus IntentMandate.
- Anmeldedatenanbieter: Erstellt PaymentMandate, verarbeitet Zahlungen
Diese Agents lassen sich in zwei Phasen unterteilen:
- Phase 1 (Shopping): Mehrere Gesprächsrunden, um eine Organisation zu finden und auszuwählen
- Phase 2 (Verarbeitung): Atomare Ausführung der Angebotserstellung und Zahlung
Derzeit müssen Sie diese Phasen jedoch manuell koordinieren.
Hier kommen die Orchestrierungsmuster des ADK ins Spiel.
AP2-Grundsatz: Orchestrierung erzwingt Vertrauensgrenzen
Warum Orchestrierung für die Sicherheit wichtig ist
Bei der Orchestrierung geht es nicht nur um Komfort, sondern auch darum, Vertrauensgrenzen durch die Architektur zu erzwingen.
Ohne Orchestrierung:
# User could accidentally skip steps or reorder them
shopping_agent.run("Find charity")
# Oops, forgot to create CartMandate!
credentials_provider.run("Process payment") # No offer to validate!
Mit Orchestrierung:
# Pipeline enforces correct order
donation_processing_pipeline = SequentialAgent(
sub_agents=[
merchant_agent, # Must run first
credentials_provider # Must run second
]
)
# Steps ALWAYS run in order, no skipping allowed
Die sequenzielle Pipeline garantiert Folgendes:
- ✅ IntentMandate wurde vor CartMandate erstellt
- ✅ CartMandate wurde vor der Zahlungsverarbeitung erstellt
- ✅ Jeder Agent wird in einem isolierten Kontext ausgeführt.
- ✅ Status wird in der Anmeldedatenkette weitergegeben
Unser Ziel: Das vollständige System entwickeln
Wir erstellen zwei Ebenen:
Ebene 1: Die Verarbeitungspipeline (SequentialAgent)
- Kabel zusammenführen → Anmeldedaten
- Wird automatisch nacheinander ausgeführt, nachdem eine Wohltätigkeitsorganisation ausgewählt wurde
- Atomare Ausführung von Angebot und Zahlung
Ebene 2: Der Root-Orchestrator (nutzerorientierter Agent)
- Freundliche Persönlichkeit
- Delegiert die Auswahl der Wohltätigkeitsorganisation an shopping_agent
- Delegiert an die Verarbeitungspipeline, nachdem „IntentMandate“ erstellt wurde
- Unterhaltungs- und Phasenübergänge verarbeiten
Dieser zweischichtige Ansatz entspricht dem natürlichen Ablauf:
- Shopping-Phase: Unterhaltung mit mehreren Zügen (Nutzer sucht, stellt Fragen, trifft eine Entscheidung)
- Verarbeitungsphase: Atomare Ausführung (Angebot → Zahlung)
Lass uns beides erstellen.
Schritt 1: Orchestration-Komponenten importieren
Richten wir zuerst die Orchestrierungsdatei mit den erforderlichen Importen ein.
👉 Offen
charity_advisor/agent.py
Beginnen wir mit den Importen:
👉 Finden:
# MODULE_7_STEP_1_IMPORT_COMPONENTS
👉 Ersetzen Sie diese einzelne Zeile durch:
from google.adk.agents import Agent, SequentialAgent
from charity_advisor.shopping_agent.agent import shopping_agent
from charity_advisor.merchant_agent.agent import merchant_agent
from charity_advisor.credentials_provider.agent import credentials_provider
Schritt 2: Verarbeitungspipeline erstellen
Nun erstellen wir die Pipeline, die die Angebotserstellung und Zahlungsabwicklung atomar ausführt.
👉 Finden:
# MODULE_7_STEP_2_CREATE_SEQUENTIAL_PIPELINE
👉 Ersetzen Sie diese beiden Zeilen durch:
# Create the donation processing pipeline
# This runs Merchant → Credentials in sequence AFTER charity is selected
donation_processing_pipeline = SequentialAgent(
name="DonationProcessingPipeline",
description="Creates signed offer and processes payment after charity is selected",
sub_agents=[
merchant_agent,
credentials_provider
]
)
Schritt 3A: Root-Agent-Einrichtung erstellen
Erstellen wir nun den nutzerorientierten Agenten, der beide Phasen orchestriert. Wir werden das in drei Teilen behandeln: Einrichtung (3A), Anleitung (3B) und untergeordnete Agents (3C).
👉 Finden:
# MODULE_7_STEP_3A_CREATE_ROOT_AGENT_SETUP
👉 Ersetzen Sie diese einzelne Zeile durch:
# Create the root orchestrator agent
# This is what users interact with directly
root_agent = Agent(
name="CharityAdvisor",
model="gemini-2.5-pro",
description="A friendly charity giving assistant that helps users donate to verified organizations.",
# MODULE_7_STEP_3B_WRITE_ROOT_AGENT_INSTRUCTION
Schritt 3B: Root-Agent-Anweisung schreiben
Fügen wir nun die Anweisung hinzu, die das Verhalten des Charity-Beraters in beiden Phasen steuert.
👉 Finden:
# MODULE_7_STEP_3B_WRITE_ROOT_AGENT_INSTRUCTION
👉 Ersetzen Sie diese einzelne Zeile durch:
instruction="""You are a helpful and friendly charity giving advisor.
Your workflow has TWO distinct phases:
PHASE 1: CHARITY SELECTION (delegate to shopping_agent)
When a user expresses interest in donating:
1. Delegate to shopping_agent immediately
2. The shopping_agent will:
- Search for charities matching their cause
- Present verified options with ratings
- Engage in conversation (user may ask questions, change their mind)
- Wait for user to select a specific charity and amount
- Create an IntentMandate when user decides
3. Wait for shopping_agent to complete
You'll know Phase 1 is complete when shopping_agent's response includes:
- "IntentMandate created" or "Intent ID: intent_xxx"
- Charity name and donation amount
PHASE 2: PAYMENT PROCESSING (delegate to DonationProcessingPipeline)
After shopping_agent completes:
1. Acknowledge the user's selection naturally:
"Perfect! Let me process your $X donation to [Charity]..."
2. Delegate to DonationProcessingPipeline
3. The pipeline will automatically:
- Create signed cart offer (MerchantAgent)
- Get consent and process payment (CredentialsProvider)
4. After pipeline completes, summarize the transaction
CRITICAL RULES:
- Phase 1 may take multiple conversation turns (this is normal)
- Only proceed to Phase 2 after IntentMandate exists
- Don't rush the user during charity selection
- Don't ask user to "proceed" between phases - transition automatically
EXAMPLE FLOW:
User: "I want to donate to education"
You: [delegate to shopping_agent]
Shopping: "Here are 3 education charities..." [waits]
User: "Tell me more about the first one"
Shopping: "Room to Read focuses on..." [waits]
User: "Great, I'll donate $50 to Room to Read"
Shopping: "IntentMandate created (ID: intent_123)..."
You: "Perfect! Processing your $50 donation to Room to Read..." [delegate to DonationProcessingPipeline]
Pipeline: [creates offer, gets consent, processes payment]
You: "Done! Your donation was processed successfully. Transaction ID: txn_456"
Your personality:
- Warm and encouraging
- Patient during charity selection
- Clear about educational nature
- Smooth transitions between phases""",
# MODULE_7_STEP_3C_ADD_ROOT_AGENT_SUBAGENTS
Schritt 3C: Untervertreter hinzufügen
Gewähren wir dem Berater der Wohltätigkeitsorganisation schließlich Zugriff auf den Shopping-Agent und die Verarbeitungspipeline und schließen wir die Agent-Definition.
👉 Finden:
# MODULE_7_STEP_3C_ADD_ROOT_AGENT_SUBAGENTS
👉 Ersetzen Sie diese einzelne Zeile durch:
sub_agents=[
shopping_agent,
donation_processing_pipeline
]
)
Schritt 4: Gesamtsystem prüfen
Prüfen wir, ob die Orchestrierung richtig konfiguriert ist.
👉 Vollständige
charity_advisor/agent.py
sollte jetzt so aussehen:
"""
Main orchestration: The donation processing pipeline and root orchestrator agent.
"""
from google.adk.agents import Agent, SequentialAgent
from charity_advisor.shopping_agent.agent import shopping_agent
from charity_advisor.merchant_agent.agent import merchant_agent
from charity_advisor.credentials_provider.agent import credentials_provider
# Create the donation processing pipeline
# This runs Merchant → Credentials in sequence AFTER charity is selected
donation_processing_pipeline = SequentialAgent(
name="DonationProcessingPipeline",
description="Creates signed offer and processes payment after charity is selected",
sub_agents=[
merchant_agent,
credentials_provider
]
)
# Create the root orchestrator agent
# This is what users interact with directly
root_agent = Agent(
name="CharityAdvisor",
model="gemini-2.5-flash",
description="A friendly charity giving assistant that helps users donate to verified organizations.",
instruction="""You are a helpful and friendly charity giving advisor.
Your workflow has TWO distinct phases:
PHASE 1: CHARITY SELECTION (delegate to shopping_agent)
When a user expresses interest in donating:
1. Delegate to shopping_agent immediately
2. The shopping_agent will:
- Search for charities matching their cause
- Present verified options with ratings
- Engage in conversation (user may ask questions, change their mind)
- Wait for user to select a specific charity and amount
- Create an IntentMandate when user decides
3. Wait for shopping_agent to complete
You'll know Phase 1 is complete when shopping_agent's response includes:
- "IntentMandate created" or "Intent ID: intent_xxx"
- Charity name and donation amount
PHASE 2: PAYMENT PROCESSING (delegate to DonationProcessingPipeline)
After shopping_agent completes:
1. Acknowledge the user's selection naturally:
"Perfect! Let me process your $X donation to [Charity]..."
2. Delegate to DonationProcessingPipeline
3. The pipeline will automatically:
- Create signed cart offer (MerchantAgent)
- Get consent and process payment (CredentialsProvider)
4. After pipeline completes, summarize the transaction
CRITICAL RULES:
- Phase 1 may take multiple conversation turns (this is normal)
- Only proceed to Phase 2 after IntentMandate exists
- Don't rush the user during charity selection
- Don't ask user to "proceed" between phases - transition automatically
EXAMPLE FLOW:
User: "I want to donate to education"
You: [delegate to shopping_agent]
Shopping: "Here are 3 education charities..." [waits]
User: "Tell me more about the first one"
Shopping: "Room to Read focuses on..." [waits]
User: "Great, I'll donate $50 to Room to Read"
Shopping: "IntentMandate created (ID: intent_123)..."
You: "Perfect! Processing your $50 donation to Room to Read..." [delegate to DonationProcessingPipeline]
Pipeline: [creates offer, gets consent, processes payment]
You: "Done! Your donation was processed successfully. Transaction ID: txn_456"
Your personality:
- Warm and encouraging
- Patient during charity selection
- Clear about educational nature
- Smooth transitions between phases""",
sub_agents=[
shopping_agent,
donation_processing_pipeline
]
)
Schritt 5: Mit Validierungs-Callbacks absichern (optional, weiter zu Schritt 7)

Der SequentialAgent garantiert die Ausführungsreihenfolge. Was aber, wenn:
- Shopping-Agent schlägt ohne Fehlermeldung fehl (IntentMandate wird nie erstellt)
- Eine Stunde vergeht zwischen Shopping und Merchant (Absicht läuft ab)
- Status wird beschädigt oder gelöscht
- Jemand versucht, den Händler direkt anzurufen, ohne Shopping zu nutzen
Rückrufe für die Durchsetzung der Architektur – sie prüfen die Voraussetzungen, bevor ein Agent überhaupt seinen LLM-Aufruf startet. Das ist ein tief greifender Schutz: Tools werden während der Ausführung validiert, Callbacks vor der Ausführung.
Fügen wir unseren Merchant- und Credentials Provider-Agents Validierungs-Callbacks hinzu.
Schritt 5A: Händlerbestätigung hinzufügen – Callback-Typen importieren
Fügen wir zuerst die für Callbacks erforderlichen Importe hinzu.
👉 Offen
charity_advisor/merchant_agent/agent.py
Fügen Sie oben in der Datei nach den vorhandenen Importvorgängen Folgendes hinzu:
from typing import Optional
from datetime import datetime, timezone
from google.adk.agents.callback_context import CallbackContext
from google.genai.types import Content, Part
import logging
logger = logging.getLogger(__name__)
Schritt 5B: Funktion zur Intent-Validierung erstellen
Erstellen wir nun eine Callback-Funktion, die das IntentMandate validiert, bevor der Merchant-Agent ausgeführt wird.
👉 In
charity_advisor/merchant_agent/agent.py
, fügen Sie diese Funktion VOR dem ein.
merchant_agent = Agent(...)
Definition:
def validate_intent_before_merchant(
callback_context: CallbackContext,
) -> Optional[Content]:
"""
Validates IntentMandate exists and hasn't expired before Merchant runs.
This callback enforces that the Shopping Agent completed successfully
before the Merchant Agent attempts to create a CartMandate.
Returns:
None: Allow Merchant Agent to proceed normally
Content: Skip Merchant Agent and return error to user
"""
state = callback_context.state
# Check credential exists
if "intent_mandate" not in state:
logger.error("❌ IntentMandate missing - Shopping Agent may have failed")
return Content(parts=[Part(text=(
"Error: Cannot create cart. User intent was not properly recorded. "
"Please restart the donation process."
))])
intent_mandate = state["intent_mandate"]
# Validate expiry (critical security check)
try:
expiry_time = datetime.fromisoformat(
intent_mandate["intent_expiry"].replace('Z', '+00:00')
)
now = datetime.now(timezone.utc)
if expiry_time < now:
logger.error(f"❌ IntentMandate expired at {intent_mandate['intent_expiry']}")
return Content(parts=[Part(text=(
"Error: Your donation intent has expired. "
"Please select a charity again to restart."
))])
time_remaining = expiry_time - now
logger.info(f"✓ IntentMandate validated. Expires in {time_remaining.total_seconds():.0f}s")
except (KeyError, ValueError) as e:
logger.error(f"❌ Invalid IntentMandate structure: {e}")
return Content(parts=[Part(text=(
"Error: Invalid intent data. Please restart the donation."
))])
# All checks passed - allow Merchant Agent to proceed
logger.info(f"✓ Prerequisites met for Merchant Agent: {intent_mandate['intent_id']}")
return None
Schritt 5C: Rückruf an Händler-Kundenservicemitarbeiter weiterleiten
Jetzt verbinden wir den Rückruf mit dem Kundenservicemitarbeiter.
👉 In
charity_advisor/merchant_agent/agent.py
, ändern
merchant_agent = Agent(...)
Definition:
Suchen Sie in der Agent-Definition nach dieser Zeile:
merchant_agent = Agent(
name="MerchantAgent",
model="gemini-2.5-flash",
description="Creates formal, signed CartMandates for charity donations following W3C PaymentRequest standards.",
Fügen Sie diese Zeile direkt nach ein.
description
Zeile:
before_agent_callback=validate_intent_before_merchant,
Ihre Agent-Definition sollte jetzt so aussehen:
merchant_agent = Agent(
name="MerchantAgent",
model="gemini-2.5-flash",
description="Creates formal, signed CartMandates for charity donations following W3C PaymentRequest standards.",
before_agent_callback=validate_intent_before_merchant,
tools=[
FunctionTool(func=create_cart_mandate)
],
instruction="""..."""
)
Schritt 6: Validierung des Anmeldedatenanbieters hinzufügen (optional – mit Schritt 7 fortfahren)
Gleiches Muster – fügen wir eine Validierung für den Zahlungsschritt hinzu.
Schritt 6A: Callback-Typen importieren
👉 Offen
charity_advisor/credentials_provider/agent.py
Fügen Sie oben in der Datei nach den vorhandenen Importvorgängen Folgendes hinzu:
from typing import Optional
from datetime import datetime, timezone
from google.adk.agents.callback_context import CallbackContext
from google.genai.types import Content, Part
import logging
logger = logging.getLogger(__name__)
Schritt 6B: Funktion zur Warenkorbvalidierung erstellen
👉 In
charity_advisor/credentials_provider/agent.py
, fügen Sie diese Funktion VOR dem ein.
credentials_provider = Agent(...)
Definition:
def validate_cart_before_payment(
callback_context: CallbackContext,
) -> Optional[Content]:
"""
Validates CartMandate exists and hasn't expired before payment processing.
This callback enforces that the Merchant Agent completed successfully
before the Credentials Provider attempts to process payment.
Returns:
None: Allow Credentials Provider to proceed
Content: Skip payment processing and return error
"""
state = callback_context.state
# Check credential exists
if "cart_mandate" not in state:
logger.error("❌ CartMandate missing - Merchant Agent may have failed")
return Content(parts=[Part(text=(
"Error: Cannot process payment. Cart was not properly created. "
"Please restart the donation process."
))])
cart_mandate = state["cart_mandate"]
# Validate AP2 structure
if "contents" not in cart_mandate:
logger.error("❌ CartMandate missing AP2 contents wrapper")
return Content(parts=[Part(text=(
"Error: Invalid cart structure. Please restart."
))])
# Validate expiry
try:
contents = cart_mandate["contents"]
expiry_time = datetime.fromisoformat(
contents["cart_expiry"].replace('Z', '+00:00')
)
now = datetime.now(timezone.utc)
if expiry_time < now:
logger.error(f"❌ CartMandate expired at {contents['cart_expiry']}")
return Content(parts=[Part(text=(
"Error: Your cart has expired (15 minute limit). "
"Please restart the donation to get a fresh offer."
))])
time_remaining = expiry_time - now
logger.info(f"✓ CartMandate validated. Expires in {time_remaining.total_seconds():.0f}s")
except (KeyError, ValueError) as e:
logger.error(f"❌ Invalid CartMandate structure: {e}")
return Content(parts=[Part(text=(
"Error: Invalid cart data. Please restart the donation."
))])
# All checks passed - allow payment processing
logger.info(f"✓ Prerequisites met for Credentials Provider: {contents['id']}")
return None
Schritt 6C: Callback an Credentials Provider anhängen
👉 In
charity_advisor/credentials_provider/agent.py
, ändern
credentials_provider = Agent(...)
Definition:
Suchen Sie in der Agent-Definition nach dieser Zeile:
credentials_provider = Agent(
name="CredentialsProvider",
model="gemini-2.5-flash",
description="Securely processes payments by creating PaymentMandates and executing transactions with user consent.",
Fügen Sie diese Zeile direkt nach ein.
description
Zeile:
before_agent_callback=validate_cart_before_payment,
Ihre Agent-Definition sollte jetzt so aussehen:
credentials_provider = Agent(
name="CredentialsProvider",
model="gemini-2.5-flash",
description="Securely processes payments by creating PaymentMandates and executing transactions with user consent.",
before_agent_callback=validate_cart_before_payment,
tools=[
FunctionTool(func=create_payment_mandate)
],
instruction="""..."""
)
Schritt 7: Mit der ADK-Web-UI testen
Jetzt testen wir das vollständig gehärtete System mit aktiven Validierungs-Callbacks.
👉 Führen Sie in Ihrem Cloud Shell-Terminal Folgendes aus:
adk web
Die Ausgabe sollte in etwa so aussehen:
+-----------------------------------------------------------------------------+
| ADK Web Server started |
| |
| For local testing, access at http://localhost:8000. |
+-----------------------------------------------------------------------------+
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
👉 So greifen Sie als Nächstes über Ihren Browser auf die ADK-Web-UI zu:
Wählen Sie in der Cloud Shell-Symbolleiste (normalerweise rechts oben) über das Symbol Webvorschau (sieht aus wie ein Auge oder ein Quadrat mit einem Pfeil) die Option Port ändern aus. Legen Sie im Pop-up-Fenster den Port auf 8000 fest und klicken Sie auf Ändern und Vorschau. Cloud Shell öffnet dann einen neuen Browsertab mit der ADK-Web-UI.

👉 Wählen Sie Ihren Agent aus dem Drop-down-Menü aus:
In der ADK-Web-UI sehen Sie oben ein Drop-down-Menü. Wählen Sie charity_advisor aus der Liste aus.

Die ADK-Weboberfläche wird mit folgenden Elementen angezeigt:
- Chatfeld: Auf der linken Seite für Unterhaltungen
- Trace-Bereich: rechts, für die Beobachtbarkeit (wird in Modul 9 verwendet)
Test 1: Spendenablauf abschließen (Normalfall)
👉 Geben Sie in der Chat-Oberfläche Folgendes ein:
I want to donate to an education charity
So sieht der vollständige Ablauf aus:


Das passiert (im Trace-Bereich rechts sichtbar):
1. Advisor delegiert an ShoppingAgent:
- ShoppingAgent sucht nach Bildungsorganisationen
- Es werden drei bestätigte Optionen mit Details angezeigt.
2. Sie interagieren mit ShoppingAgent (kann mehrere Runden dauern):
User: "Tell me more about Room to Read"
Shopping: [explains mission and impact]
User: "I'll donate $50 to Room to Read"
3. ShoppingAgent erstellt IntentMandate:
- Erstellt und signiert den Intent
- Gibt die Bestätigung mit der Intent-ID zurück
4. Der Advisor wechselt in die Verarbeitungsphase:
Super! Deine Spende in Höhe von 50 $an Room to Read wird verarbeitet…
5. Die DonationProcessingPipeline wird aktiviert:
- Händlerrückruf validiert IntentMandate (✓ bestanden) ← NEU!
- Der Händler-Agent erstellt CartMandate mit Signatur.
- Credentials callback validates CartMandate (✓ passed) ← NEU!
- Zahlung wird vom Anmeldedatenanbieter vorbereitet
6. Zahlungsabwicklung:
- Anmeldedatenanbieter erstellt PaymentMandate
- Simuliert die Zahlungsabwicklung
- Transaktions-ID für Retoure
7. Zusammenfassungen von Advisor:
Super! Deine Spende wurde erfolgreich verarbeitet. 🎉
Details:
- Betrag: 50,00 $
- Wohltätigkeitsorganisation: Room to Read (EIN: 77-0479905)
- Transaktions-ID: txn_a3f7b2c8d9e1f4a2
Test 2: Prüfen, ob Callbacks Fehler abfangen (optionaler erweiterter Test)
Möchten Sie sehen, wie mit den Callbacks Fehler abgefangen werden? Sie müssten den Status manuell beschädigen (erweitertes Debugging). In der Produktion würden jedoch folgende Rückrufe abgefangen:
- Shopping Agent-Tool schlägt fehl → Händler-Callback-Blockierungen: „Fehler: Warenkorb kann nicht erstellt werden…“
- 2 Stunden sind vergangen → Händlerrückruf blockiert: „Fehler: Intention abgelaufen…“
- Warenkorb läuft ab → Credential-Callback-Blöcke: „Fehler: Warenkorb abgelaufen (15-Minuten-Limit)...“
Diese Grenzfälle werden jetzt durch Ihre Validierungs-Callbacks architektonisch erzwungen.
Was Sie gerade erstellt haben
Sie haben drei spezialisierte Agents erfolgreich in einem nahtlosen, vertrauenswürdigen System mit Architekturvalidierung orchestriert.
Weitere Informationen
Sie haben nun den technischen Kern für die Entwicklung vertrauenswürdiger Agents abgeschlossen:
Sie haben ein vollständiges vertrauenswürdiges System erstellt, das die Anmeldedatenkette lokal erzwingt. Jetzt machen wir die App durch die Bereitstellung in der Produktion für echte Nutzer zugänglich und aktivieren den Verantwortlichkeitsverlauf, der Modul 9 ermöglicht.
Stellen Sie Ihren gehärteten Agenten in Google Cloud bereit.
8. Bereitstellung

Ihr vertrauenswürdiges Spenden-System ist jetzt mit drei spezialisierten Agents, die lokal arbeiten, vollständig:
Sie wird jedoch nur auf Ihrem Entwicklungssystem ausgeführt. Damit dieses System für echte Nutzer nützlich ist und die Nachvollziehbarkeit erfasst wird, die Vertrauenswürdigkeit beweist, müssen Sie es in der Produktion bereitstellen.
In diesem Modul erfahren Sie, wie Sie Ihren Agent in Google Cloud bereitstellen und von Anfang an Observability aktivieren. Das Flag --trace_to_cloud, das Sie bei der Bereitstellung verwenden, ermöglicht den Verantwortlichkeitsnachweis in Modul 9.
Bereitstellungsoptionen
Das ADK unterstützt mehrere Bereitstellungsziele. Jede hat unterschiedliche Merkmale in Bezug auf Komplexität, Sitzungsverwaltung, Skalierung und Kosten:
Faktor | Lokal ( | Agent Engine | Cloud Run |
Komplexität | Minimal | Niedrig | Mittel |
Sitzungspersistenz | Nur im Arbeitsspeicher (geht beim Neustart verloren) | Von Vertex AI verwaltet (automatisch) | Cloud SQL (PostgreSQL) oder In-Memory |
Infrastruktur | Keine (nur Entwicklercomputer) | Vollständig verwaltet | Container + optionale Datenbank |
Kaltstart | – | 100–500 ms | 100–2.000 ms |
Skalieren | Einzelne Instanz | Automatisch | Automatisch (auf Null) |
Kostenmodell | Kostenlos (lokale Verarbeitung) | Compute-basiert | Anfragebasiert + kostenlose Stufe |
UI-Support | Ja (integriert) | Nein (nur API) | Ja (über das Flag |
Beobachtbarkeit einrichten | Lokaler Trace Viewer | Automatisch mit | Erfordert das Flag |
Optimal für | Entwicklung und Tests | Produktions-Agents | Produktions-Agents |
Empfehlung:Für dieses vertrauenswürdige Spendersystem empfehlen wir Agent Engine als primäre Produktionsbereitstellung, da sie Folgendes bietet:
- Vollständig verwaltete Infrastruktur (keine Containerverwaltung)
- Integrierte Sitzungspersistenz über
VertexAiSessionService - Automatische Skalierung ohne Kaltstarts
- Einfachere Bereitstellung (keine Docker-Kenntnisse erforderlich)
- Direkte Cloud Trace-Einbindung
Zusätzliche Option: Google Kubernetes Engine (GKE)
Für fortgeschrittene Nutzer, die eine Steuerung auf Kubernetes-Ebene, benutzerdefinierte Netzwerke oder die Orchestrierung mehrerer Dienste benötigen, ist die GKE-Bereitstellung verfügbar. Diese Option bietet maximale Flexibilität, erfordert aber mehr Fachwissen (Clusterverwaltung, Manifeste, Dienstkonten).
Die GKE-Bereitstellung wird in diesem Codelab nicht behandelt, ist aber vollständig im ADK GKE Deployment Guide dokumentiert.
Vorbereitung
1. Google Cloud-Projekt einrichten
Sie benötigen ein Google Cloud-Projekt mit aktivierter Abrechnung. Wenn Sie kein Konto haben:
- Projekt erstellen: Google Cloud Console
- Abrechnung aktivieren: Abrechnung aktivieren
- Notieren Sie sich Ihre Projekt-ID (nicht den Projektnamen oder die Projektnummer).
2. Erneute Authentifizierung (optional)
Authentifizieren Sie sich bei Google Cloud:
gcloud auth application-default login
gcloud config set project YOUR_PROJECT_ID
Ersetzen Sie YOUR_PROJECT_ID durch Ihre tatsächliche Google Cloud-Projekt-ID.
Authentifizierung überprüfen:
gcloud config get-value project
# Should output: YOUR_PROJECT_ID
3. Umgebungsvariablen
Verwenden Sie diese Befehle, um die Datei .env automatisch auszufüllen:
# Get your current Project ID
PROJECT_ID=$(gcloud config get-value project)
STAGING_BUCKET_VALUE="gs://${PROJECT_ID}-staging"
ENV_FILE=".env"
# Check if STAGING_BUCKET is already set in the .env file
if grep -q "^STAGING_BUCKET=" "${ENV_FILE}"; then
# If it exists, replace the line
# The sed command finds the line starting with STAGING_BUCKET= and replaces the entire line.
# Using | as a delimiter to avoid issues with slashes in the bucket name.
sed -i "s|^STAGING_BUCKET=.*|STAGING_BUCKET=${STAGING_BUCKET_VALUE}|" "${ENV_FILE}"
echo "Updated STAGING_BUCKET in ${ENV_FILE}"
else
# If it doesn't exist, add it to the end of the file
echo "STAGING_BUCKET=${STAGING_BUCKET_VALUE}" >> "${ENV_FILE}"
echo "Added STAGING_BUCKET to ${ENV_FILE}"
fi
# Verify it was added or updated correctly
echo "Current STAGING_BUCKET setting:"
grep "^STAGING_BUCKET=" "${ENV_FILE}"
Hier sollten Sie dies sehen:
STAGING_BUCKET=gs://your-actual-project-id-staging
Wichtige Hinweise:
- Ersetzen Sie
YOUR_PROJECT_IDdurch Ihre tatsächliche Projekt-ID (oder verwenden Sie die Befehle oben). - Verwenden Sie für
GOOGLE_CLOUD_LOCATIONeine unterstützte Region. - Der Staging-Bucket wird automatisch erstellt, wenn er nicht vorhanden ist, wenn Sie das Bereitstellungsskript ausführen.
4. Erforderliche APIs aktivieren
Für den Bereitstellungsprozess müssen mehrere Google Cloud APIs aktiviert sein. Führen Sie diesen Befehl aus, um sie zu aktivieren:
gcloud services enable \
aiplatform.googleapis.com \
storage.googleapis.com \
cloudbuild.googleapis.com \
cloudtrace.googleapis.com \
compute.googleapis.com
Mit diesem Befehl wird Folgendes aktiviert:
- AI Platform API: Für Agent Engine- und Vertex AI-Modelle
- Cloud Storage API – für Staging-Bucket
- Cloud Build API – zum Erstellen von Containern (Cloud Run)
- Cloud Trace API: für Observability und Accountability-Trails
- Compute Engine API – Für die Verwaltung von Dienstkonten
Schritt 1: Bereitstellungsinfrastruktur verstehen
Ihr Projekt enthält ein einheitliches Bereitstellungsscript (deploy.sh), das alle Bereitstellungsmodi verarbeitet.
👉 Bereitstellungsskript prüfen (optional):
cat deploy.sh
Das Skript bietet drei Bereitstellungsmodi:
./deploy.sh local– Lokal mit In-Memory-Speicher ausführen./deploy.sh agent-engine– In Vertex AI Agent Engine bereitstellen (empfohlen)./deploy.sh cloud-run– Bereitstellung in Cloud Run mit optionaler Benutzeroberfläche
So funktioniert das genau:
Bei der Bereitstellung von Agent Engine führt das Skript Folgendes aus:
adk deploy agent_engine \
--project=$GOOGLE_CLOUD_PROJECT \
--region=$GOOGLE_CLOUD_LOCATION \
--staging_bucket=$STAGING_BUCKET \
--display_name="Charity Advisor" \
--trace_to_cloud \
charity_advisor
Bei der Cloud Run-Bereitstellung wird Folgendes ausgeführt:
adk deploy cloud_run \
--project=$GOOGLE_CLOUD_PROJECT \
--region=$GOOGLE_CLOUD_LOCATION \
--service_name="charity-advisor" \
--app_name="charity_advisor" \
--with_ui \
--trace_to_cloud \
charity_advisor
Das Flag --trace_to_cloud ist für beide Bereitstellungstypen entscheidend, da es die Cloud Trace-Integration für den Verantwortlichkeitsnachweis ermöglicht, den Sie in Modul 9 kennenlernen.
Schritt 2: Agent Engine-Wrapper vorbereiten
Für die Agent Engine ist ein bestimmter Einstiegspunkt erforderlich, der Ihren Agent für die verwaltete Laufzeitumgebung umschließt. Diese Datei wurde für Sie erstellt.
👉 Rezension
charity_advisor/agent_engine_app.py
:
"""Agent Engine application wrapper.
This file prepares the Charity Advisor agent for deployment to Vertex AI Agent Engine.
"""
from vertexai import agent_engines
from .agent import root_agent
# Wrap the agent in an AdkApp object for Agent Engine deployment
app = agent_engines.AdkApp(
agent=root_agent,
enable_tracing=True, # Enables Cloud Trace integration automatically
)
Warum diese Datei benötigt wird:
- Für die Agent Engine muss der Agent in ein
AdkApp-Objekt eingeschlossen werden. - Der Parameter
enable_tracing=Trueaktiviert die Cloud Trace-Integration automatisch. - Auf diesen Wrapper wird während der Bereitstellung von der ADK CLI verwiesen.
- Damit wird
VertexAiSessionServicefür die automatische Sitzungsbeibehaltung konfiguriert.
Schritt 3: In Agent Engine bereitstellen (EMPFOHLEN)
Agent Engine ist die empfohlene Produktionsbereitstellung für Ihr vertrauenswürdiges Spendersystem, da sie eine vollständig verwaltete Infrastruktur mit integrierter Sitzungspersistenz bietet.
Deployment ausführen
Über das Stammverzeichnis Ihres Projekts:
chmod +x deploy.sh
./deploy.sh agent-engine
Bereitstellungsphasen
Sehen Sie sich an, wie das Skript diese Phasen durchläuft:
Phase 1: API Enablement
✓ aiplatform.googleapis.com
✓ storage.googleapis.com
✓ cloudbuild.googleapis.com
✓ cloudtrace.googleapis.com
✓ compute.googleapis.com
Phase 2: IAM Setup
✓ Getting project number
✓ Granting Storage Object Admin
✓ Granting Vertex AI User
✓ Granting Cloud Trace Agent
Phase 3: Staging Bucket
✓ Creating gs://your-project-id-staging (if needed)
✓ Setting permissions
Phase 4: Validation
✓ Checking agent.py exists
✓ Verifying root_agent defined
✓ Checking agent_engine_app.py exists
✓ Validating requirements.txt
Phase 5: Build & Deploy
✓ Packaging agent code
✓ Uploading to staging bucket
✓ Creating Agent Engine instance
✓ Configuring session persistence
✓ Setting up Cloud Trace integration
✓ Running health checks
Dieser Vorgang dauert 5 bis 10 Minuten, da der Agent verpackt und in der Vertex AI-Infrastruktur bereitgestellt wird.
Agent Engine-ID speichern
Nach erfolgreicher Bereitstellung:
✅ Agent Engine created successfully!
Agent Engine ID: 7917477678498709504
Resource Name: projects/123456789/locations/us-central1/reasoningEngines/7917477678498709504
Endpoint: https://us-central1-aiplatform.googleapis.com/v1/...
⚠️ IMPORTANT: Save the Agent Engine ID from the output above
Add it to your .env file as:
AGENT_ENGINE_ID=7917477678498709504
This ID is required for:
- Testing the deployed agent
- Updating the deployment later
- Accessing logs and traces
Aktualisieren Sie Ihre .env-Datei sofort:
echo "AGENT_ENGINE_ID=7917477678498709504" >> .env
Was wurde bereitgestellt?
Ihre Agent Engine-Bereitstellung umfasst jetzt:
✅ Alle drei Agents (Shopping, Merchant, Credentials) werden in der verwalteten Laufzeit ausgeführt
✅ Vollständige Logik der Anmeldedatenkette (Intent → Cart → Payment mandates)
✅ Mechanismus zur Einwilligung der Nutzer mit Bestätigungs-Workflow
✅ Automatische Sitzungspersistenz über VertexAiSessionService
✅ Von Google verwaltete Infrastruktur mit automatischen Skalierung
✅ Cloud Trace-Integration für vollständige Beobachtbarkeit
Schritt 4: Bereitgestellten Agent testen
Umgebung aktualisieren
Prüfen Sie, ob Ihre .env die Agent Engine-ID enthält:
AGENT_ENGINE_ID=7917477678498709504 # From deployment output
GOOGLE_CLOUD_PROJECT=your-project-id
GOOGLE_CLOUD_LOCATION=us-central1
STAGING_BUCKET=gs://your-project-id-staging
Testskript ausführen
Ihr Projekt enthält ein Testskript speziell für Agent Engine-Bereitstellungen.
👉 Test ausführen:
python scripts/test_deployed_agent.py
Erwartete Ausgabe
Testing Agent Engine deployment...
Project: your-project-id
Location: us-central1
Agent Engine ID: 7917477678498709504
Endpoint: https://us-central1-aiplatform.googleapis.com/v1/...
Creating session...
✓ Session created: 4857885913439920384
Sending donation query...
✓ Response received:
Event 1: I'll help you donate $50 to a children's education charity...
Event 2: Here are some highly-rated children's education charities...
Event 3: Which charity would you like to support?...
✅ Test completed successfully!
Session ID: 4857885913439920384
This donation generated a trace in Cloud Trace.
View it in Module 9: Observability
To view traces:
https://console.cloud.google.com/traces/list?project=your-project-id
Checkliste für die Bestätigung
Prüfen Sie nach dem Test Folgendes:
✅ Kundenservicemitarbeiter antwortet auf Anfragen
✅ Alle drei Kundenservicemitarbeiter werden nacheinander ausgeführt (Shopping → Händler → Anmeldedaten)
✅ Zustimmungsmechanismus wird aktiviert (Bestätigung erforderlich)
✅ Sitzung bleibt über Anfragen hinweg bestehen
✅ Keine Authentifizierungsfehler
✅ Keine Verbindungszeitüberschreitungen
Wenn Fehler auftreten:
- Prüfen Sie, ob Ihre Umgebungsvariablen richtig festgelegt sind.
- Prüfen Sie, ob die APIs aktiviert sind:
gcloud services list --enabled - Agent Engine-Logs in der Vertex AI Console ansehen
- Prüfen Sie, ob die Datei
agent_engine_app.pyin Ihrem Ordnercharity_advisorvorhanden ist.
Schritt 5: In Cloud Run bereitstellen (optional)
Agent Engine wird zwar für eine optimierte Produktionsbereitstellung empfohlen, Cloud Run bietet jedoch mehr Kontrolle und unterstützt die ADK-Web-UI. Dieser Abschnitt ist optional.
Wann sollte Cloud Run verwendet werden?
Wählen Sie Cloud Run aus, wenn Sie Folgendes benötigen:
- Die ADK-Web-UI für die Nutzerinteraktion
- Volle Kontrolle über die Containerumgebung
- Benutzerdefinierte Datenbankkonfigurationen
- Einbindung in bestehende Cloud Run-Dienste
Deployment ausführen
chmod +x deploy.sh
./deploy.sh cloud-run
Was ändert sich?
Das Skript führt automatisch folgende Aktionen aus:
- Docker-Container mit Ihrem Agent-Code erstellen
- Cloud SQL-PostgreSQL-Datenbank erstellen (falls erforderlich)
- Datenbankverbindung konfigurieren
- Bereitstellen mit aktivierter ADK-Web-UI
Die Bereitstellung dauert aufgrund der Cloud SQL-Bereitstellung 10–15 Minuten.
Sitzungsverwaltung:
- Verwendet
DatabaseSessionServiceanstelle vonVertexAiSessionService - Erfordert Datenbankanmeldedaten in
.env(oder automatisch generiert) - Status wird in der PostgreSQL-Datenbank beibehalten
Unterstützung der Benutzeroberfläche:
- Web-UI verfügbar unter:
https://charity-advisor-xyz.a.run.app
Cloud Run-Bereitstellung testen
Wenn Sie die Bereitstellung in Cloud Run mit --with_ui vorgenommen haben, können Sie direkt in Ihrem Browser testen:
- Rufen Sie die Dienst-URL auf (in der Bereitstellungsausgabe angegeben).
- Das ADK-Webinterface wird angezeigt. Wählen Sie Ihren Agent aus dem Drop-down-Menü aus.
- Testspende starten:
I want to donate $50 to a children's education charity
- Ablauf der Ausführung beobachten
- :
- ShoppingAgent findet Wohltätigkeitsorganisationen und speichert Ihre Absicht
- MerchantAgent erstellt das Mandat für den Einkaufswagen.
- CredentialsProvider erstellt das Zahlungsauftragsmandat und fordert eine Bestätigung an
- Nach der Bestätigung wird die Zahlung verarbeitet
- Prüfen Sie, ob die Antwort Folgendes enthält:
- Empfehlungen für wohltätige Zwecke
- Bestätigungsanfrage
- Erfolgsmeldung nach der Genehmigung
Fehlerbehebung
Häufige Fragen und Probleme
Problem : ERROR: GOOGLE_CLOUD_PROJECT is not set
Lösung:Prüfen Sie, ob die Datei .env die richtige Projekt-ID enthält:
GOOGLE_CLOUD_PROJECT=your-actual-project-id
Problem:Staging-Bucket wird nicht automatisch erstellt
Lösung:Das Skript sollte den Bucket automatisch erstellen. Erstellen Sie ihn andernfalls manuell:
gsutil mb -p $GOOGLE_CLOUD_PROJECT -l $GOOGLE_CLOUD_LOCATION $STAGING_BUCKET
Zusammenfassung
Sie haben:
✅ Die von deploy.sh
bereitgestellte Bereitstellungsinfrastruktur verstanden ✅ Die Wrapper-Konfiguration der Agent Engine überprüft
✅ Das vertrauenswürdige Spendersystem in der Agent Engine bereitgestellt (empfohlen)
✅ Die Cloud Trace-Integration mit --trace_to_cloud
aktiviert ✅ Überprüft, ob der Agent zugänglich ist und funktioniert
✅ Die Grundlage für Verantwortlichkeitsprüfpfade in Modul 9 geschaffen
Im nächsten Modul erfahren Sie, was genau durch dieses Flag freigeschaltet wird: vollständige Transparenz bei jeder Spende, jeder Einwilligung und jedem Schritt der Anmeldedatenkette.
9. Beobachtbarkeit


Im ersten Modul haben Sie ein grundlegendes Problem kennengelernt: Wenn ein KI-Agent Geld verwaltet, wie können Sie dann nachweisen, was passiert ist?
Ein Nutzer könnte Folgendes behaupten:
- „Ich habe diese Organisation nie ausgewählt!“
- „Ich habe diese Zahlung nicht autorisiert!“
- „Das System hat mir ohne meine Zustimmung etwas in Rechnung gestellt!“
In einem herkömmlichen Blackbox-KI-System hätten Sie keine Möglichkeit, das Gegenteil zu beweisen. Ihr vertrauenswürdiges Spendersystem ist jedoch anders. In Modul 8 haben Sie die Bereitstellung mit dem Flag --trace_to_cloud vorgenommen. Das bedeutet, dass bei jeder Spende ein vollständiger, manipulationssicherer Audit-Trail in Cloud Trace erstellt wird.
In diesem Modul erfahren Sie, wie Sie diese Traces lesen und als Beweismittel verwenden. Du lernst Folgendes:
- Mit Cloud Trace Explorer Produktions-Traces finden
- Wasserfalldiagramm lesen, um den Ausführungsablauf zu verstehen
- Anmeldedatenkette finden (Intention → Warenkorb → Zahlungsermächtigungen)
- Einwilligungsmomente mit Zeitstempel-Nachweis finden
- Traces zur Beilegung von Streitigkeiten verwenden
- Traces für Compliance und Audits exportieren
Das ist es, was vertrauenswürdige Systeme von leistungsfähigen, aber undurchsichtigen Systemen unterscheidet: die Fähigkeit, mit forensischer Präzision nachzuweisen, was passiert ist.
Traces und Spans
Bevor Sie Traces in Cloud Trace ansehen, sollten Sie wissen, was Sie sehen.
Was ist ein Trace?
Ein Trace ist der vollständige Zeitablauf der Bearbeitung einer einzelnen Anfrage durch Ihren Agent. Es erfasst alles vom Senden einer Anfrage durch einen Nutzer bis zur endgültigen Antwort.
Jeder Trace zeigt Folgendes:
- Gesamtdauer der Anfrage
- Alle ausgeführten Vorgänge
- Wie Vorgänge zueinander in Beziehung stehen (über- und untergeordnete Beziehungen)
- Wann die einzelnen Vorgänge begonnen und beendet wurden
- Status „Erfolg“ oder „Fehler“
Für den Kundenservicemitarbeiter der Wohltätigkeitsorganisation:Ein Trace entspricht einem vollständigen Spendenablauf von „Ich möchte spenden“ bis „Zahlung erfolgreich“.
Was ist ein Span?
Ein Span stellt eine einzelne Arbeitseinheit in einem Trace dar. Spans sind die Bausteine eines Traces.
Gängige Zeiträume in Ihrem Spendersystem:
Span-Typ | Was wird dargestellt? | Beispiel |
| Ausführung eines Agenten |
|
| Anfrage an ein Sprachmodell |
|
| Ausführung von Toolfunktionen |
|
| Aus dem Sitzungsspeicher lesen |
|
| In den Sitzungsspeicher schreiben |
|
Jeder Zeitraum enthält:
- Name:Für welchen Vorgang steht diese Zeile?
- Dauer (Startzeit → Endzeit)
- Attribute:Metadaten wie Tool-Eingaben, Modellantworten und Tokenanzahl
- Status:Erfolg (
OK) oder Fehler (ERROR) - Über-/Untergeordnet-Beziehungen:Welche Vorgänge haben welche ausgelöst?
Wie Spans einen Trace bilden
Spannen werden ineinander verschachtelt, um die Kausalität darzustellen:
Root Span: CharityAdvisor.run (entire request)
└─ Child: DonationPipeline.run (sequential workflow)
├─ Child: ShoppingAgent.run
│ ├─ Grandchild: call_llm (Gemini processes charity search)
│ ├─ Grandchild: execute_tool (find_charities)
│ └─ Grandchild: execute_tool (save_user_choice)
├─ Child: MerchantAgent.run
│ ├─ Grandchild: call_llm (Gemini generates cart)
│ └─ Grandchild: execute_tool (create_cart_mandate)
└─ Child: CredentialsProvider.run
├─ Grandchild: call_llm (Gemini processes payment)
└─ Grandchild: execute_tool (create_payment_mandate) [CONSENT!]
Diese Hierarchie zeigt genau, was in welcher Reihenfolge passiert ist. Sie sehen, dass das Zahlungs-Mandat nach dem Warenkorb-Mandat erstellt wurde, das nach der Auswahl einer Organisation durch den Nutzer erstellt wurde.
Schritt 1: Auf Cloud Trace Explorer zugreifen
Sehen wir uns nun die tatsächlichen Traces Ihres bereitgestellten Agents an.
Cloud Trace aufrufen
- Google Cloud Console öffnen : console.cloud.google.com
- Wählen Sie oben in der Drop-down-Liste Ihr Projekt aus. Wenn Sie bereits daran gearbeitet haben, sollte es vorausgewählt sein.
- Cloud Trace Explorer aufrufen
- :
- Scrollen Sie in der linken Seitenleiste zum Abschnitt Observability (Beobachtbarkeit).
- Klicken Sie auf Trace.
- Oder verwenden Sie den Direktlink: console.cloud.google.com/traces/list
Was Sie sehen
Im Trace Explorer wird eine Liste aller Traces aus Ihrem Projekt angezeigt:
Spalte | Enthaltene Informationen |
Ersuchen | HTTP-Methode und Endpunkt (für API-Anfragen) |
Startzeit | Beginn der Anfrage |
Latenz | Gesamtdauer der Anfrage |
Spans | Anzahl der Vorgänge im Trace |
Jede Zeile steht für eine vollständige Anfrage an Ihren bereitgestellten Agent.
Test-Traces generieren (falls erforderlich)
Wenn Sie noch keine Routen sehen, ist die Liste möglicherweise leer, weil:
- Es wurden noch keine Anfragen an Ihren bereitgestellten Agenten gesendet.
- Es dauert 1–2 Minuten, bis Traces nach einer Anfrage angezeigt werden.
Test-Trace generieren:
Wenn Sie in Cloud Run mit UI bereitgestellt haben, rufen Sie die Dienst-URL auf und führen Sie eine Spende im Browser aus.
Wenn Sie die Bereitstellung in Agent Engine vorgenommen haben, führen Sie das Testskript aus Modul 8 aus:
python scripts/test_deployed_agent.py
Warten Sie 1–2 Minuten und aktualisieren Sie dann die Seite „Cloud Trace Explorer“. Jetzt sollten Sie die Traces sehen.
Traces filtern
Mit den Filteroptionen oben können Sie nach bestimmten Traces suchen:
- Zeitraum:Ändern Sie den Zeitraum bei Bedarf von „Letzte Stunde“ in „Letzte 24 Stunden“.
- Minimale Latenz / Maximale Latenz:Filter für langsame Anfragen
- Anfragefilter:Sie können nach bestimmten Vorgängen suchen, z.B. „DonationPipeline“)
Konzentrieren Sie sich bei diesem Modul auf Traces mit längeren Zeiträumen (>5 Sekunden), da diese vollständige Spendenabläufe darstellen, bei denen alle drei Agents ausgeführt werden.
Schritt 2: Vollständigen Spendenablauf ansehen
Klicken Sie in der Liste auf einen beliebigen Trace, um die Wasserfalldarstellung zu öffnen. Hier verbringen Sie die meiste Zeit mit der Analyse des Agent-Verhaltens.
Wasserfallansicht
Die Wasserfalldarstellung ist ein Gantt-Diagramm, das den gesamten Ausführungszeitplan zeigt:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Timeline (horizontal = time) →
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
invocation ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 8.2s
agent_run: CharityAdvisor ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 8.1s
agent_run: DonationPipeline ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 7.9s
agent_run: ShoppingAgent ▓▓▓▓▓▓ 2.1s
call_llm: gemini-2.5-flash ▓▓▓▓ 1.2s
execute_tool: find_charities ▓▓ 0.5s
execute_tool: save_user_choice ▓ 0.3s
agent_run: MerchantAgent ▓▓▓ 1.8s
call_llm: gemini-2.5-flash ▓▓ 0.9s
execute_tool: create_cart_mandate ▓ 0.7s
agent_run: CredentialsProvider ▓▓▓▓▓▓▓▓ 4.0s
call_llm: gemini-2.5-flash ▓▓ 0.8s
execute_tool: create_payment_mandate ▓▓▓▓▓ 3.0s [CONSENT]
Diagramm auswerten
Jeder Balken steht für einen Zeitraum:
- Horizontale Position:Beginn des Problems
- Dauer:Wie lange es gedauert hat
- Einzug:Hierarchische Beziehungen werden dargestellt.
- Farbe:Normalerweise blau für normal, rot für Fehler
Wichtige Beobachtungen aus diesem Beispiel-Trace:
✅ Gesamtdauer:8,2 Sekunden
✅ Sequenzielle Ausführung:ShoppingAgent wurde vor MerchantAgent abgeschlossen
✅ MerchantAgent abgeschlossen
vorher
CredentialsProvider wurde gestartet
✅ Einwilligung war der längste Vorgang:3,0 Sekunden für create_payment_mandate (da auf die Bestätigung des Nutzers gewartet wurde)
✅ LLM-Aufrufe sind sichtbar:Jeder Agent hat eine Gemini-Anfrage gestellt
✅ Tool-Aufrufe werden erfasst:Alle sechs Tools wurden erfolgreich ausgeführt
In dieser Visualisierung sehen Sie sofort, wo Zeit aufgewendet wird und in welcher Reihenfolge Vorgänge ausgeführt werden.
Für Details auf einen Zeitraum klicken
Klicken Sie auf den invocation-Bereich (den Stammbereich oben). Im rechten Bereich werden detaillierte Attribute angezeigt:
{
"http.method": "POST",
"http.status_code": 200,
"http.url": "https://charity-advisor-xyz.a.run.app/api/run",
"user_id": "test_user_123",
"session_id": "4857885913439920384",
"trace_id": "a1b2c3d4e5f6...",
"span_id": "1234567890abcdef"
}
Diese Attribute liefern Kontext zur gesamten Anfrage.
Schritt 3: Anmeldedatenkette finden
Ihr vertrauenswürdiges System verwendet eine Anmeldedatenkette, um die Autorisierung in jedem Schritt nachzuweisen:
IntentMandate (User chose charity)
↓
CartMandate (Merchant created cart, signed IntentMandate)
↓
PaymentMandate (Payment provider created payment, signed CartMandate)
Suchen wir die einzelnen Mandate im Trace.
IntentMandate finden
Klicken Sie unter „ShoppingAgent“ auf den execute_tool: save_user_choice-Bereich.
Im Bereich „Attribute“ sehen Sie:
{
"tool.name": "save_user_choice",
"tool.input.charity_name": "Save the Children",
"tool.input.amount": 50,
"tool.output.status": "success",
"tool.output.intent_mandate": {
"charity_name": "Save the Children",
"amount": 50,
"timestamp": "2024-11-08T15:30:12.345Z",
"signature": "a3f7b9c1d2e4..."
}
}
Das beweist:
- ✅ Nutzer hat „Save the Children“ ausgewählt
- ✅ Der Betrag war 50 $
- ✅ Die Auswahl wurde um 15:30:12 Uhr (UTC) aufgezeichnet.
- ✅ Signatur wurde generiert (in der Produktion wäre dies kryptografisch)
Das IntentMandate befindet sich jetzt im Sitzungsstatus und ist für nachfolgende Agents verfügbar.
CartMandate finden
Klicken Sie auf den execute_tool: create_cart_mandate-Span (unter „MerchantAgent“).
Im Attributbereich:
{
"tool.name": "create_cart_mandate",
"tool.input.intent_mandate": {
"charity_name": "Save the Children",
"amount": 50,
"signature": "a3f7b9c1d2e4..."
},
"tool.output.status": "success",
"tool.output.cart_mandate": {
"cart_id": "cart_7893",
"intent_signature": "a3f7b9c1d2e4...",
"cart_signature": "e8f2a9b3c7d1...",
"timestamp": "2024-11-08T15:30:14.789Z"
}
}
Das beweist:
- ✅ MerchantAgent hat das IntentMandate erhalten (Eingabe zeigt es)
- ✅ Der Einkaufswagen wurde mit der ID „cart_7893“ erstellt.
- ✅ Die Warenkorbsignatur verweist auf die IntentMandate-Signatur (Kettenlink).
- ✅ Erstellt um 15:30:14 Uhr UTC (2,4 Sekunden nach der Intention)
Das CartMandate verweist jetzt auf das IntentMandate und bildet so die Kette.
Zahlungsmandat finden
Klicken Sie auf den execute_tool: create_payment_mandate-Bereich (unter „CredentialsProvider“).
Im Attributbereich:
{
"tool.name": "create_payment_mandate",
"tool.input.cart_mandate": {
"cart_id": "cart_7893",
"intent_signature": "a3f7b9c1d2e4...",
"cart_signature": "e8f2a9b3c7d1..."
},
"tool.confirmation_required": true,
"tool.confirmation_timestamp": "2024-11-08T15:30:17.891Z",
"tool.user_response": "CONFIRMED",
"tool.wait_duration_ms": 29168,
"tool.output.status": "success",
"tool.output.payment_mandate": {
"payment_id": "pay_9821",
"cart_signature": "e8f2a9b3c7d1...",
"payment_signature": "b4c9e2a7f8d3...",
"timestamp": "2024-11-08T15:30:47.059Z"
}
}
Das beweist die vollständige Kette:
- ✅ CredentialsProvider hat das CartMandate erhalten (Eingabe zeigt es)
- ✅ Die Zahlung bezieht sich auf die CartMandate-Signatur (Kettenlink!).
- ✅ Bestätigung erforderlich (
confirmation_required: true) - ✅ Nutzer um 15:30:17 Uhr (UTC) bestätigt
- ✅ Das System hat 29,2 Sekunden auf die Entscheidung des Nutzers gewartet.
- ✅ Die Zahlung wurde nach der Bestätigung erstellt (Zeitstempel: 15:30:47).
Kette visualisieren
Der Trace belegt, dass die Berechtigungsnachweiskette korrekt ausgeführt wurde:
15:30:12 UTC → IntentMandate created (signature: a3f7...)
↓
15:30:14 UTC → CartMandate created (references: a3f7...)
↓
15:30:17 UTC → User consent requested
↓
15:30:47 UTC → PaymentMandate created (references: e8f2...)
Jedes Mandat verweist auf die Unterschrift des vorherigen. Die Kette ist manipulationssicher. Sie können sie überprüfen, indem Sie die Signaturen vergleichen.
Schritt 4: Leistung und Engpässe analysieren
Cloud Trace zeigt nicht nur, was passiert ist, sondern auch, wo Zeit verbracht wird, damit Sie die Leistung optimieren können.
Kritischen Pfad ermitteln
Suchen Sie in der Wasserfallansicht nach den längsten Zeiträumen im vertikalen Stapel. Sie stellen Ihre Leistungsengpässe dar.
Aus unserem Beispiel-Trace:
Total: 8.2 seconds
Breakdown:
- ShoppingAgent: 2.1s (26%)
- MerchantAgent: 1.8s (22%)
- CredentialsProvider: 4.0s (49%) ← Bottleneck
- Other overhead: 0.3s (3%)
Wichtige Erkenntnis:CredentialsProvider ist für 49% der Gesamtzeit verantwortlich. Warum?
Schlüsseln Sie den Bereich „CredentialsProvider“ auf:
CredentialsProvider: 4.0s
- call_llm: 0.8s (20%)
- create_payment_mandate: 3.0s (75%) ← User consent wait
- Other: 0.2s (5%)
Die Verzögerung von 3,0 Sekunden ist normal und gut – der Nutzer überlegt, bevor er die Bestätigung ausführt. Das ist kein Leistungsproblem, sondern ein Beweis für eine sorgfältige Einwilligung.
LLM-Kosten nachverfolgen
Klicken Sie auf einen beliebigen call_llm-Zeitraum, um die Tokennutzung zu sehen:
{
"llm.model": "gemini-2.5-flash",
"llm.usage.prompt_tokens": 487,
"llm.usage.completion_tokens": 156,
"llm.usage.total_tokens": 643,
"llm.response_time_ms": 1243
}
Anwendungsbeispiele:
- Kosten pro Anfrage nachverfolgen (Tokens × Modellpreise)
- Unnötig lange Prompts identifizieren
- Modellleistung vergleichen (Flash vs. Pro)
- Latenz im Vergleich zur Qualität optimieren
Beispielrechnung:
Gemini 2.5 Flash pricing (as of Nov 2024):
Input: $0.075 per 1M tokens
Output: $0.30 per 1M tokens
This request:
Input: 487 tokens × $0.075 / 1M = $0.000037
Output: 156 tokens × $0.30 / 1M = $0.000047
Total: = $0.000084 (~$0.00008)
For 10,000 donations/month:
10,000 × 3 agents × $0.00008 = $2.40/month in LLM costs
Diese detaillierte Übersicht hilft Ihnen, datengestützte Entscheidungen zur Modellauswahl zu treffen.
Traces vergleichen
Nach mehreren Traces filtern und Dauer vergleichen:
Trace 1: 8.2s (with consent wait: 3.0s)
Trace 2: 12.5s (with consent wait: 7.8s) ← User took longer
Trace 3: 5.1s (with consent wait: 0.2s) ← User clicked fast
Trace 4: 6.3s (with consent wait: 1.5s)
Erkenntnis:Die meisten Abweichungen sind auf die Entscheidungszeit der Nutzer und nicht auf die Systemleistung zurückzuführen. Die Ausführung des Core-Agents (ohne Einwilligung) dauert immer etwa 5 Sekunden.
Das bedeutet, dass das System zuverlässig funktioniert.
Richten Sie für Produktionssysteme Warnungen ein, um Probleme zu erkennen, bevor sich Nutzer beschweren.
Benachrichtigung bei hohen Fehlerraten
Benachrichtigung erstellen, wenn mehr als 5% der Traces Fehler enthalten:
- Rufen Sie Cloud Monitoring auf.
- Klicken Sie auf Benachrichtigungen → Richtlinie erstellen.
- Konfigurieren:
Resource: Cloud Trace Span Metric: Span error count Condition: Rate > 5% over 5 minutes Notification: Email your-team@example.com
Benachrichtigung bei hoher Latenz
So erstellen Sie eine Benachrichtigung, wenn die P95-Latenz 15 Sekunden überschreitet:
Resource: Cloud Trace
Metric: Span duration (95th percentile)
Condition: > 15000ms for 5 minutes
Notification: PagerDuty
So können Sie Leistungseinbußen erkennen, bevor sie sich auf die Nutzererfahrung auswirken.
Benachrichtigung bei fehlender Einwilligung
Eine Benachrichtigung erstellen, wenn Zahlungen ohne Bestätigung verarbeitet werden:
Resource: Cloud Trace Span
Filter: tool.name="create_payment_mandate" AND tool.confirmation_required!=true
Condition: Any match
Notification: Critical alert to security team
Dies ist ein Sicherheitsverstoß-Detektor. Wenn er ausgelöst wird, stimmt etwas mit Ihrem Einwilligungsmechanismus nicht.
Das haben Sie gelernt
Mit Cloud Trace haben Sie jetzt gelernt, wie Sie:
✅ Cloud Trace Explorer verwenden, um Produktions-Traces zu finden
✅ Wasserfalldiagramme lesen, um den vollständigen Ausführungsablauf zu sehen
✅ Anmeldedatenkette nachvollziehen über IntentMandate → CartMandate → PaymentMandate ✅ Traces als Beweismittel für die Beilegung von Streitigkeiten verwenden
✅ Leistung analysieren, um Engpässe zu identifizieren
✅ LLM-Kosten auf granularer Ebene nachvollziehen
Die Auswirkungen
Vergleich zweier Systeme, die dieselbe Beschwerde „Ich habe das nie autorisiert!“ bearbeiten:
System ohne Beobachtbarkeit
User: "I never authorized that $50 donation!"
You: "Our logs show the transaction completed successfully."
User: "But I didn't approve it!"
You: "The system requires confirmation before processing."
User: "I never saw any confirmation!"
You: "..." [no way to prove what happened]
Result: Refund issued, trust lost, user never returns.
System mit Cloud Trace
User: "I never authorized that $50 donation!"
You: "Let me pull up the trace from your session..."
[Shows waterfall with consent span]
You: "Here's the evidence:
- 15:30:17 UTC: System asked for confirmation
- Message shown: 'You are about to donate $50...'
- 15:30:47 UTC: You clicked 'CONFIRM'
- Wait time: 29.2 seconds
The system waited almost 30 seconds for your decision.
Here's the exact timestamp of your confirmation."
User: "Oh... I remember now. My mistake. Sorry!"
Result: Trust preserved, no refund needed, user continues using service.
Das ist die Stärke von Verantwortlichkeitsprüfpfaden. Sie gehen von „Vertrauen Sie uns“ zu „Wir zeigen Ihnen genau, was passiert ist“ über.
Weitere Informationen
Sie haben nun den technischen Kern für die Entwicklung vertrauenswürdiger Agents abgeschlossen:
✅ Modul 1–6:Vertrauenswürdige Architektur entworfen (Rollen, Anmeldedaten, Einwilligung)
✅ Modul 7:Komplexe Arbeitsabläufe orchestriert (SequentialAgent)
✅ Modul 8:Mit aktivierter Observability bereitgestellt
✅ Modul 9:Rechenschaftspflicht-Trails lesen und verwenden
Die von Ihnen entwickelte Architektur – Rollentrennung, Anmeldedatenketten, Einwilligungsmechanismen, vollständige Beobachtbarkeit – lässt sich direkt auf Produktionssysteme übertragen, in denen es um echtes Geld, echte Daten und echte Konsequenzen geht.
10. Ihr Weg nach vorn
Was Sie erstellt haben
Sie haben diesen Workshop mit einer Frage begonnen: „Wie entwickle ich KI-Agents, denen ich wirklich Geld anvertrauen kann?“
Sie haben jetzt die Antwort.
Ausgangspunkt (Modul 3):
simple_agent = Agent(
model="gemini-2.5-flash",
instruction="Find charities and donate",
tools=[google_search]
)
Ihr aktueller Stand (Modul 10):
- ✅ Drei spezialisierte Agenten mit Rollentrennung
- ✅ Drei überprüfbare Anmeldedaten (Absicht → Warenkorb → Zahlungsaufträge)
- ✅ Vollständige Anmeldedatenkette mit Ablaufvalidierung in jedem Schritt
- ✅ Verfahren zum Einholen von Einwilligungen mit Zeitstempel
- ✅ Bereitstellung in der Produktionsumgebung für Agent Engine mit Beobachtbarkeit
- ✅ Vollständiger Verantwortlichkeitsnachweis in Cloud Trace
- ✅ Gerichtsmedizinische Beweise für die Beilegung von Streitfällen
Workshop – Produktion: Die Lücke
Ihr System entspricht der richtigen Architektur und den richtigen Mustern, verwendet aber vereinfachte Funktionen, die für echtes Geld und echte Nutzer aktualisiert werden müssen.
Hier sehen Sie, was vereinfacht wurde und was für die Produktion erforderlich ist:
Komponente | Workshop-Implementierung | Produktionsanforderungen |
Signaturen | SHA-256-Hashes ( | Echte kryptografische Signaturen mit PKI oder JWT mit privaten Schlüsseln |
Zahlungsabwicklung | Simulierte Retouren ( | Integration mit echten Zahlungs-APIs (Stripe, PayPal, Square) |
Nutzerauthentifizierung | Implizites Vertrauen (keine Anmeldung erforderlich) | OAuth 2.0, WebAuthn oder Sitzungsverwaltung |
Verwaltung von Secrets | Umgebungsvariablen in der Datei | Google Secret Manager oder Cloud KMS mit Verschlüsselung |
Charity Database | Beispiel-JSON-Datei mit 9 Organisationen | Live-API-Integration (IRS Tax Exempt Organization Search, Charity Navigator API) |
Fehlerbehandlung | Einfacher try-catch-Block mit Fehlermeldungen | Wiederholungslogik mit exponentiellem Backoff, Unterbrechungen der Netzwerkverbindung, Warteschlangen für unzustellbare Nachrichten |
Tests | Manuelle Bestätigung über Skripts | Umfassende Suite von Unit-, Integrations- und E2E-Tests mit CI/CD |
Sitzungspersistenz | In-Memory (lokal) oder automatisch (Agent Engine) | Produktionsdatenbank mit Sicherungen und Notfallwiederherstellung |
Ratenbegrenzung | Keine (Bildungseinrichtung) | Ratenlimits pro Nutzer, IP-basiertes Drosseln, Missbrauchserkennung |
Wichtige Architekturmuster, die Sie beherrschen
Die Muster, die Sie in diesem Workshop kennengelernt haben, sind Produktionsmuster. Zweifeln Sie nicht daran.
Trennung von Rollen (AP2-Grundsatz 1)
Jeder Agent hat EINE klare Aufgabe und sieht NUR das, was er dafür benötigt. Wenn ein Agent gehackt wird, kann der Angreifer nicht auf die Daten anderer Agents zugreifen. Dadurch wird der Umfang einer Manipulation eingeschränkt.
Produktionssysteme, die diese Funktion verwenden:Zahlungsabwicklung, Dokument-Workflows, Genehmigungsketten, mehrstufige Formulare mit Validierungsschritten.
Nachweisbare Anmeldedaten (AP2-Grundsatz 2)
Jede Anmeldedaten hat eine Ablaufzeit, verweist auf die vorherigen Anmeldedaten und erfordert eine Validierung vor dem nächsten Schritt. Dadurch wird eine manipulationssichere Prüfkette erstellt.
Produktionswert:Vollständiger Nachweis, was wann und in welcher Reihenfolge passiert ist. Unerlässlich für die Beilegung von Streitigkeiten und die Einhaltung von Vorschriften.
Ausdrückliche Einwilligung (AP2-Grundsatz 3)
Zeitstempel als Nachweis dafür, dass der Nutzer die Aktion genehmigt hat. Kann nicht angefochten werden.
Produktionswert:Rechtliche Anforderung für Finanztransaktionen. Schützt sowohl Nutzer als auch Unternehmen.
Sequenzielle Orchestrierung (ADK-Muster)
Erzwingt die richtige Ausführungsreihenfolge. Verhindert das Überspringen von Schritten. Garantiert, dass jeder Agent die Ausgabe des vorherigen Agents sieht.
Produktionswert:Ideal für Systeme, in denen Nutzer sofortige Ergebnisse erwarten. Dieses Muster eignet sich für Spendenaktionen, Abrechnungsprozesse und Genehmigungsketten.
Vollständige Observability (OpenTelemetry + Cloud Trace)
Jede Entscheidung, jeder Tool-Aufruf, jeder Moment der Einwilligung und jede Übergabe von Anmeldedaten werden automatisch erfasst.
Produktionswert:Gerichtsmedizinische Beweise für Streitigkeiten. Daten zur Leistungsoptimierung. Compliance-Audit-Trails. Produktionsprobleme präzise beheben:
Ressourcen für das kontinuierliche Lernen
ADK-Dokumentation:
AP2 und zugehörige Standards:
Google Cloud-Dienste:
Ressourcen bereinigen
So löschen Sie Ihr Deployment, um laufende Gebühren zu vermeiden:
Agent Engine:Folgen Sie der Anleitung in der Dokumentation zu Agent Engine.
Cloud Run (falls bereitgestellt):
gcloud run services delete charity-advisor \
--region=$GOOGLE_CLOUD_LOCATION
Storage-Buckets:
gsutil -m rm -r gs://$GOOGLE_CLOUD_PROJECT-staging
gsutil -m rm -r gs://$GOOGLE_CLOUD_PROJECT-artifacts
Es geht weiter
Sie haben mit einer einfachen Frage begonnen und eine vollständige Antwort erstellt. Sie haben die grundlegenden Muster für vertrauenswürdige KI-Agents kennengelernt. Diese Muster lassen sich auf alle Bereiche übertragen, in denen KI-Agents sensible Vorgänge verarbeiten – Finanztransaktionen, Entscheidungen im Gesundheitswesen, Rechtsdokumente, Lieferkettenvorgänge.
Die Grundsätze werden übertragen. Das Vertrauensmodell funktioniert.
Jetzt können Sie etwas Vertrauenswürdiges entwickeln. ❤️
