In diesem Blog zeige ich dir, wie du mit Googles neuem Open-Source-Agent Development Kit (ADK) einen KI-gesteuerten Reiseassistenten mit mehreren Agenten erstellen kannst. Agent Development Kit (ADK) und dem A2A (Agent-zu-Agent) Protokoll.
Wir verwenden mehrere Agenten, um Flüge, Hotels und Aktivitätsempfehlungen zu verwalten, die über REST-APIs und FastAPI-Server kommunizieren. Am Ende verpacken wir das Ganze in ein sauberes Streamlit-Frontend für ein intuitives Nutzererlebnis.
Wir halten unsere Leserinnen und Leser mit The Median auf dem Laufenden, unserem kostenlosen Freitags-Newsletter, der die wichtigsten Meldungen der Woche aufschlüsselt. Melde dich an und bleibe in nur ein paar Minuten pro Woche auf dem Laufenden:
Was ist das Agent Development Kit (ADK) von Google?
Das ADK von Google ist ein modulares, produktionsreifes Framework für den Aufbau von LLM-gesteuerten Agenten. Es ist das gleiche Toolkit, das auch die Agenten in den Google-Produkten wie Agentspace und Customer Engagement Suite antreibt. Jetzt open-sourcedhilft es Entwicklern, leistungsstarke, flexible und interoperable Multi-Agenten-Anwendungen zu entwickeln.
Warum das Agent Development Kit (ADK) verwenden?
ADK bietet die Flexibilität von Python mit eingebauten Strukturen für Zustandsverwaltung, Rückrufe, Streaming und strukturierte Ein-/Ausgabe. Werfen wir einen Blick auf seine wichtigsten Funktionen:
Multi-Agent by Design: ADK kann Agenten in parallelen, sequenziellen oder hierarchischen Workflows zusammenstellen.
Model-agnostic: Es funktioniert mit Gemini, GPT-4o, Claude, Mistral und anderen über LiteLlm.
Modular und skalierbar: Der Nutzer kann spezialisierte Agenten definieren und mithilfe der integrierten Orchestrierung intelligent delegieren.
Streaming-fähig: Es unterstützt Echtzeit-Interaktion, einschließlich bidirektionalem Audio/Video.
Eingebaute Werkzeuge: Es unterstützt lokale CLI und Web UI für Debugging und Evaluierung.
Unterstützt den Einsatz: Mit ADK lassen sich Agenten einfach containerisieren und in verschiedenen Umgebungen einsetzen.
Was ist das Agent2Agent (A2A) Protokoll von Google?
Das Agent2Agent (A2A)-Protokoll ist ein offener, herstellerneutraler Standard, der von Google entwickelt wurde, um eine einfache Kommunikation und Zusammenarbeit zwischen KI-Agenten über verschiedene Plattformen und Frameworks hinweg zu ermöglichen.
ADK-Agenten stellen einen Standard-HTTP-Endpunkt /run und Metadaten über .well-known/agent.json zur Verfügung. Dies ermöglicht die Erkennung von Agenten und die einfache Kommunikation zwischen Agenten (oder sogar externen Orchestrierern wie LangGraph oder CrewAI).
Das Hinzufügen der A2A-Metadaten-Datei ist zwar optional, macht deine Agenten aber interoperabel mit dem breiteren Ökosystem von Agententools und Orchestrierern.
Projektübersicht: KI-gestützter Reiseplaner mit ADK und A2A
In diesem Projekt wird ein Reiseplaner erstellt, der:
Nimmt das Ziel, die Daten und das Budget als Eingabe.
Ruft drei verschiedene Agenten an:
flight_agent: Empfiehlt Flugoptionen.
stay_agent: Findet Hotels innerhalb des Budgets.
activities_agent: Schlägt ansprechende Aktivitäten vor.
Dann nutzt er eine zentrale host_agent, um alle Anfragen zu koordinieren.
Und schließlich verwendet er eine Streamlit UI für die Benutzerinteraktion.
Alle Agenten werden als separate FastAPI-Server gehostet und stellen einen /run Endpunkt zur Verfügung. Die Kommunikation findet über den gemeinsamen A2A-kompatiblen Client statt.
Hinweis: Dieses Projekt läuft der Einfachheit halber komplett auf deinem lokalen Rechner, aber du kannst jeden Agenten und die Benutzeroberfläche auf Cloud-Plattformen wie Render, Railway oder Google Cloud Run bereitstellen, um einen skalierbaren Zugang zu erhalten.
Schritt 1: Voraussetzungen
Beginnen wir mit der Installation der folgenden Bibliotheken:
Richte dann deinen OpenAI API-Schlüssel ein - du kannst auch einen anderen Modellanbieter verwenden. Um zu erfahren, wie du deinen OpenAI-API-Schlüssel einrichtest, empfehle ich dir dieses einführende Tutorial zur GPT-4o API.
Bevor wir intelligente Agenten bauen können, müssen wir eine gemeinsame Sprache definieren, in der sie miteinander sprechen können. In unserem Fall geschieht dies mit Hilfe von:
Ein gemeinsames Schema für die Eingabe (definiert über Pydantic)
Ein REST-Client-Dienstprogramm zum Aufrufen von Agenten
Ein REST-Server-Wrapper, um den /run Endpunkt für alle Agenten zu standardisieren
Diese werden in den Ordnern shared/ und common/ abgelegt, damit der Code modular bleibt. Schauen wir uns jede einzelne davon an.
Erstellen einer shared/schemas.py Datei
Wir definieren ein TravelRequest Schema mit Pydantic. So wird sichergestellt, dass alle Agenten sich über die Struktur der eingehenden Anfragen einig sind, die das Reiseziel, die Reisedaten und das Budget des Nutzers umfasst.
from pydantic import BaseModel
classTravelRequest(BaseModel):
destination:str
start_date:str
end_date:str
budget:floatBereitgestellt von
Dieser Kurs hilft bei:
Konsistente Eingaben für alle Agenten.
Hinzufügen einer automatischen Validierung mit FastAPI.
Vereinfachung der Wiederverwendung von Code.
Erstellen einer common/a2a_client.py Datei
Dieses leichtgewichtige asynchrone Dienstprogramm ermöglicht es jedem Agenten (insbesondere dem Host), einen anderen Agenten über das A2A-Protokoll aufzurufen, indem er den Endpunkt /run aufruft.
Dieses Dienstprogramm sendet asynchron eine POST-Anfrage an den /run Endpunkt eines anderen Agenten mit httpx. Sie gibt die geparste JSON-Antwort zurück und gibt einen Fehler aus, wenn die Anfrage fehlschlägt.
Wir werden dieses Dienstprogramm in unserem Host-Agenten verwenden, um flight_agent, stay_agent und activities_agent aufzurufen.
Erstellen einer common/a2a_server.py Datei
Anstatt für jeden Agenten eine eigene FastAPI-Route zu schreiben, verallgemeinern wir sie mit der Funktion create_app(agent), die die
Die Bedienung des Agenten am /run
Erhalt eines Reiseantrags
Rückgabe einer strukturierten Antwort
from fastapi import FastAPI
import uvicorn
defcreate_app(agent):
app = FastAPI()@app.post("/run")asyncdefrun(payload:dict):returnawait agent.execute(payload)return appBereitgestellt von
Dieses Dienstprogramm erstellt eine FastAPI-App mit einer Standardroute /run, die die Ausführung an den angegebenen Agenten delegiert. Sie gewährleistet eine einheitliche Agent-to-Agent (A2A)-Schnittstelle für alle Dienste, die strukturierte JSON-Eingaben verwenden.
Diese gemeinsamen Komponenten machen unser Multi-Agenten-System wartungsfreundlicher, wiederverwendbar und entsprechen Googles A2A-Philosophie des einfachen, strukturierten Nachrichtenaustauschs zwischen Agenten.
Schritt 3: Aufbau des Multi-Agenten-Systems mit ADK und A2A
Nachdem wir nun die gemeinsamen Verträge und Dienstprogramme eingerichtet haben, können wir mit dem Aufbau der einzelnen Agenten beginnen. Um dies in ein wirklich modulares Multi-Agenten-System zu verwandeln, verwenden wir das A2A-Protokoll von Google - eine einfache HTTP-basierte Schnittstelle, über die Agenten konsistent und interoperabel kommunizieren können.
A2A (Agent-to-Agent) ermöglicht die Plug-and-Play-Koordination zwischen Agenten, egal ob es sich um lokale Python-Funktionen oder um gehostete Agenten in Netzwerken handelt. Jeder Agent stellt einen /run Endpunkt mit einem gemeinsamen Schema zur Verfügung und fungiert als Dienst.
In unserer Demo haben wir vier Agenten:
host_agent: Orchestriert alle anderen Agenten
flight_agent: Findet passende Flüge
stay_agent: Schlägt Unterkünfte vor
activities_agent: Empfiehlt, sich an lokalen Aktivitäten zu beteiligen
Alle Agenten sind ähnlich strukturiert, mit 3 Dateien und einem Unterordner:
agents/
├── host_agent/
│ │ ├── agent.py # Optional if host logic is minimal
│ │ ├── task_manager.py # Calls other agents and aggregates responses
│ │ ├── __main__.py # Starts FastAPI app via common/a2a_server.py
│ │ └── .well-known/
│ │ └── agent.json # A2A Agent Card metadata
├── flight_agent/
├── stay_agent/
└── activities_agent/Bereitgestellt von
Jeder Agent verwendet google.adk.agents.Agent, einen LiteLlm Modell-Wrapper und Runner zur Ausführung. Beginne damit, die folgenden Dateien im Ordner activities_agent zu erstellen und wiederhole das Gleiche für flight_agent und stay_agent.
Erstellen einer agent.py Datei
Definieren wir nun die Logik für unsere activities_agent, die dafür verantwortlich ist, auf der Grundlage der Reiseroute des Nutzers ansprechende lokale Erlebnisse zu generieren.
Schritt 1: Importe
Wir beginnen damit, wichtige Module zu importieren, um unseren Agenten zu konfigurieren und auszuführen.
from google.adk.agents import Agent
from google.adk.models.lite_llm import LiteLlm
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types
import jsonBereitgestellt von
Dieser Agent nutzt die Komponenten von Google ADK wie Agent, ' Runner, ' und LiteLlm und verwaltet den Status mit InMemorySessionService.. Die Bibliothek Types wird für die Erstellung von strukturierten Prompts verwendet.
Schritt 2: Aktivitäten Agent
Jetzt instanziieren wir den Agenten selbst mithilfe der ADK-Agentenklasse.
activities_agent = Agent(
name="activities_agent",
model=LiteLlm("openai/gpt-4o"),
description="Suggests interesting activities for the user at a destination.",
instruction=("Given a destination, dates, and budget, suggest 2-3 engaging tourist or cultural activities. ""For each activity, provide a name, a short description, price estimate, and duration in hours. ""Respond in plain English. Keep it concise and well-formatted."))Bereitgestellt von
Der Parameter Anweisung definiert die Systemaufforderung, die das Verhalten des LLM steuert. Obwohl in diesem Beispiel einfaches Englisch verwendet wird, kannst du die Anweisung so anpassen, dass sie strukturiertes JSON zurückgibt, um das Parsen zu erleichtern.
Schritt 3: Sitzungsmanagement
Um die Interaktionen der Nutzer/innen zu verfolgen, konfigurieren wir einen Lernpfad (Runner) und die Sitzungsinformationen.
Die Runner verwaltet die Agentenausführung für eine bestimmte App-Sitzung. Während die Klasse InMemorySessionService den Kontext im Speicher speichert. Dann definieren wir Benutzer- und Sitzungs-IDs. In der Produktion können diese jedoch dynamisch oder benutzerspezifisch sein. Dadurch wird sichergestellt, dass eine neue ADK-Sitzung existiert, bevor Aufforderungen an den LLM-Agenten gesendet werden.
Schritt 4: Ausführen der Agentenlogik
Die Funktion execute() bearbeitet eingehende Anfragen, erstellt eine Eingabeaufforderung, ruft das Modell auf und analysiert die Ausgabe.
asyncdefexecute(request):
session_service.create_session(
app_name="activities_app",
user_id=USER_ID,
session_id=SESSION_ID
)
prompt =(f"User is flying to {request['destination']} from {request['start_date']} to {request['end_date']}, "f"with a budget of {request['budget']}. Suggest 2-3 activities, each with name, description, price estimate, and duration. "f"Respond in JSON format using the key 'activities' with a list of activity objects.")
message = types.Content(role="user", parts=[types.Part(text=prompt)])asyncfor event in runner.run_async(user_id=USER_ID, session_id=SESSION_ID, new_message=message):if event.is_final_response():
response_text = event.content.parts[0].text
try:
parsed = json.loads(response_text)if"activities"in parsed andisinstance(parsed["activities"],list):return{"activities": parsed["activities"]}else:print("'activities' key missing or not a list in response JSON")return{"activities": response_text}# fallback to raw textexcept json.JSONDecodeError as e:print("JSON parsing failed:", e)print("Response content:", response_text)return{"activities": response_text}# fallback to raw textBereitgestellt von
Die Funktion execute() erstellt dynamisch eine Eingabeaufforderung mit den Parametern der eingehenden Anfrage wie Zielort, Daten und Budget. Hier ist, was unter der Haube passiert:
Die Eingabeaufforderung weist das Modell an, ein strukturiertes JSON-Objekt mit einer Aktivitätenliste zurückzugeben.
Ein Content Objekt wird erstellt und an den ADK Runner übergeben, der asynchron auf die endgültige Antwort des Modells mit einem Streaming-Generator wartet.
Sobald die endgültige Antwort eingegangen ist, extrahiert der Agent die Rohtextausgabe und versucht, sie als JSON zu parsen.
Wenn das Parsen erfolgreich war und der erwartete Aktivitätsschlüssel existiert, werden die strukturierten Daten zurückgegeben.
Wenn der Schlüssel fehlt oder fehlerhaft ist, wird als Rückfall die Rohtext-Antwort zurückgegeben, damit die Benutzeroberfläche noch eine brauchbare Ausgabe hat.
Dieser duale Ansatz sorgt für einen reibungslosen Ablauf, wenn der LLM Klartext statt strukturiertem JSON zurückgibt.
Diese Strategie verbessert die Robustheit und die Benutzerfreundlichkeit, vor allem, wenn die Modellergebnisse aufgrund der Temperatur oder der Interpretation der Eingabeaufforderung leicht variieren.
Erstellen einer task_manager.py Datei
Nachdem wir die execute() Logik in agent.py definiert haben, verbinden wir sie mit dem ADK-kompatiblen Server-Setup unter task_manager.py.
from.agent import execute
asyncdefrun(payload):returnawait execute(payload)Bereitgestellt von
Diese Datei dient als dünner Wrapper um die zuvor definierte Funktion execute(). Sie macht die Methode run() für externe Module verfügbar, insbesondere für das Serverskript in __main__.py.
Erstellen einer __main__.py Datei
Die Datei __main__.py startet einen FastAPI-Server auf Port 8003, der den Agenten am Endpunkt /run bedient.
from common.a2a_server import create_app
from.task_manager import run
app = create_app(agent=type("Agent",(),{"execute": run}))if __name__ =="__main__":import uvicorn
uvicorn.run(app, port=8003)Bereitgestellt von
Hier ist, was passiert ist:
Die create_app() (aus common/a2a_server.py) wickelt unseren Agenten in eine A2A-kompatible FastAPI-Schnittstelle ein.
Wir konstruieren dynamisch ein Objekt mit einer execute() Methode, damit ADK run() richtig aufrufen kann.
Diese Trennung ermöglicht es uns, zustandslose API-Schnittstellen beizubehalten und gleichzeitig die zentrale Agentenlogik wiederzuverwenden.
Erstellen einer .well-known/agent.json Datei
Wir verwenden diese JSON-Datei, um die Identität und den Zweck des Agenten gemäß dem A2A-Protokoll (Agent-to-Agent) zu beschreiben.
{"name":"activity_agent","description":"Agent providing activity details."}Bereitgestellt von
Hinweis: Die Datei .well-known/agent.json wird zwar nicht direkt von unseren Agenten in diesem Projekt verwendet, aber sie entspricht der A2A-Spezifikation und ist wichtig für die Entdeckung, die Introspektion und die zukünftige Kompatibilität mit Orchestratoren wie LangGraph, CrewAI oder Googles Agentenregistrierung.
Eine ähnliche Logik wird auch für flight_agent und stay_agent verwendet.
Schritt 4: Koordinierung mit host_agent
Die host_agent fungiert als zentraler Planer für die Demo. Die host_agent ist ein Beispiel für das Steuerungsmuster in Multi-Agenten-Systemen. Es trennt Entscheidungsfindung und Ausführung, so dass sich jeder nachgelagerte Agent auf seine Nische konzentrieren kann, während die Koordinationslogik zentralisiert wird. Das vereinfacht nicht nur das Testen und Skalieren, sondern spiegelt auch die reale Microservice-Architektur in verteilten Systemen wider.
Er sendet dieselbe Nutzlast an alle drei Agenten über ihre /run APIs und führt die Ergebnisse zusammen. Fügen wir die folgenden Dateien zum Ordner host_agent hinzu.
Erstellen einer agent.py Datei
Beginnen wir mit den Basisimporten.
from google.adk.agents import Agent
from google.adk.models.lite_llm import LiteLlm
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import typesBereitgestellt von
Dieser Importblock enthält alle Kernbausteine, die benötigt werden, um einen LLM-basierten Agenten mit dem Google ADK zu definieren und auszuführen: Agent Klasse, leichtgewichtiger LLM-Wrapper, Runner für die Ausführung und In-Memory-Session-Management.
host_agent = Agent(
name="host_agent",
model=LiteLlm("openai/gpt-4o"),
description="Coordinates travel planning by calling flight, stay, and activity agents.",
instruction="You are the host agent responsible for orchestrating trip planning tasks. ""You call external agents to gather flights, stays, and activities, then return a final result.")
session_service = InMemorySessionService()
runner = Runner(
agent=host_agent,
app_name="host_app",
session_service=session_service
)
USER_ID ="user_host"
SESSION_ID ="session_host"Bereitgestellt von
Der obige Code definiert einen ADK-Agenten auf oberster Ebene, der für die Koordinierung des gesamten Reiseplans verantwortlich ist. In dieser Implementierung rufen wir zwar keine Unteragenten aus dem LLM auf, aber die Systemaufforderung bereitet die Rolle für eine künftige Erweiterung vor, bei der der LLM möglicherweise die Verwendung von Werkzeugen und Metaüberlegungen übernehmen könnte.
asyncdefexecute(request):# Ensure session exists
session_service.create_session(
app_name="host_app",
user_id=USER_ID,
session_id=SESSION_ID
)
prompt =(f"Plan a trip to {request['destination']} from {request['start_date']} to {request['end_date']} "f"within a total budget of {request['budget']}. Call the flights, stays, and activities agents for results.")
message = types.Content(role="user", parts=[types.Part(text=prompt)])asyncfor event in runner.run_async(user_id=USER_ID, session_id=SESSION_ID, new_message=message):if event.is_final_response():return{"summary": event.content.parts[0].text}Bereitgestellt von
Diese execute() Funktion dient als Haupteinstiegspunkt in das LLM des Host-Agenten. Es:
Initialisiert eine Sitzung (für Speicherunterstützung, falls erforderlich)
Baut dynamisch eine Benutzerführung auf
Sendet es mit ADKs runner.run_async() an das Modell method
Erwartet und extrahiert schließlich die endgültige Antwort
Erstellen einer task_manager.py Datei
Der Aufgabenmanager führt die Orchestrierungslogik aus, indem er Remote-Agenten aufruft und den gesamten Arbeitsablauf der Reiseplanung abwickelt. Für die praktische Umsetzung definieren wir die Service-URLs für jeden Child-Agent. Diese Endpunkte entsprechen dem A2A /run protocol and expect a shared TravelRequest` JSON Schema.
from common.a2a_client import call_agent
FLIGHT_URL ="http://localhost:8001/run"
STAY_URL ="http://localhost:8002/run"
ACTIVITIES_URL ="http://localhost:8003/run"Bereitgestellt von
Jetzt definieren wir die Nutzlast.
asyncdefrun(payload):#Print what the host agent is sendingprint("Incoming payload:", payload)
flights =await call_agent(FLIGHT_URL, payload)
stay =await call_agent(STAY_URL, payload)
activities =await call_agent(ACTIVITIES_URL, payload)# Log outputsprint("flights:", flights)print("stay:", stay)print("activities:", activities)# Ensure all are dicts before access
flights = flights ifisinstance(flights,dict)else{}
stay = stay ifisinstance(stay,dict)else{}
activities = activities ifisinstance(activities,dict)else{}return{"flights": flights.get("flights","No flights returned."),"stay": stay.get("stays","No stay options returned."),"activities": activities.get("activities","No activities found.")}Bereitgestellt von
Diese Funktion verwendet die Hilfsfunktion call_agent(), um die Nutzlast an jeden nachgelagerten Dienst zu senden, und protokolliert die Eingaben und Ausgaben, damit sie während der Entwicklung sichtbar sind. In dieser Datei befindet sich die eigentliche Orchestrierungslogik.
Erstellen einer __main__.py Datei
Die Datei __main__.py dient als Einstiegspunkt für den FastAPI-Server, der den Host-Agenten umhüllt.
from common.a2a_server import create_app
from.task_manager import run
app = create_app(agent=type("Agent",(),{"execute": run}))if __name__ =="__main__":import uvicorn
uvicorn.run(app, port=8000)Bereitgestellt von
Die Hauptdatei macht Folgendes:
Es verwendet create_app() von common/a2a_server.py, um eine FastAPI-Anwendung mit einem standardisierten /run Endpunkt zu erstellen.
Dann übergibt er ein einfaches agentenähnliches Objekt mit einer execute() Methode, die intern an die task_manager.run() Funktion delegiert.
Zum Schluss wird der FastAPI-Server über uvicorn an einem bestimmten Port (normalerweise 8000) gestartet.
Dadurch wird die Schnittstelle des Host-Agenten mit anderen nachgelagerten Agenten abgeglichen und die Konsistenz im gesamten System gewahrt.
Erstellen einer .well-known/agent.json Datei
Diese Datei funktioniert wie ein klassisches Multi-Agenten-Muster, bei dem ein zentraler Knotenpunkt Aufgaben delegiert und zusammenstellt.
{"name":"host_agent","description":"Coordinates travel planning among specialized agents."}Bereitgestellt von
Das ist zwar optional, aber es ist eine gute Praxis, dies in alle Agentenverzeichnisse aufzunehmen, wie bereits erklärt.
Schritt 5: Erstellen der Benutzeroberfläche mit Streamlit
Schließlich wollen wir eine einfache App entwickeln, in der die Nutzer ihre Vorlieben eingeben können und eine strukturierte Reiseroute erhalten. Beginne damit, eine travel_ui.py Datei im Stammverzeichnis zu erstellen und füge den folgenden Code hinzu.
Wir importieren grundlegende Bibliotheken wie Streamlit und Requests für die UI-Unterstützung.
st.set_page_config(page_title="ADK-Powered Travel Planner", page_icon="✈️")
st.title("🌍 ADK-Powered Travel Planner")
origin = st.text_input("Where are you flying from?", placeholder="e.g., New York")
destination = st.text_input("Destination", placeholder="e.g., Paris")
start_date = st.date_input("Start Date")
end_date = st.date_input("End Date")
budget = st.number_input("Budget (in USD)", min_value=100, step=50)if st.button("Plan My Trip ✨"):ifnotall([origin, destination, start_date, end_date, budget]):
st.warning("Please fill in all the details.")else:
payload ={"origin": origin,"destination": destination,"start_date":str(start_date),"end_date":str(end_date),"budget": budget
}
response = requests.post("http://localhost:8000/run", json=payload)if response.ok:
data = response.json()
st.subheader("✈️ Flights")
st.markdown(data["flights"])
st.subheader("🏨 Stays")
st.markdown(data["stay"])
st.subheader("🗺️ Activities")
st.markdown(data["activities"])else:
st.error("Failed to fetch travel plan. Please try again.")Bereitgestellt von
Die Streamlit-App bietet eine benutzerfreundliche Oberfläche für die Interaktion mit dem Multi-Agenten-Reiseplaner, der auf ADK basiert. Hier sind ein paar Dinge, die wir im obigen Code ansprechen.
Er verwendet text_input, date_input und number_input, um Herkunft, Ziel, Datum und Budget zu erfassen.
Wenn du auf "Meine Reise planen" klickst, werden die Eingaben überprüft, um sicherzustellen, dass kein Feld leer bleibt.
Wenn er gültig ist, erstellt er einen JSON-Payload und sendet eine POST-Anfrage an die host_agent. http://localhost:8000/run.
Die host_agent ruft alle untergeordneten Agenten (Flug, Aufenthalt, Aktivität) auf, fasst deren Antworten zusammen und liefert einen einheitlichen Reiseplan.
Die Antwort wird geparst und mit der Methode st.markdown() unter separaten Überschriften für Flüge, Aufenthalte und Aktivitäten angezeigt.
Wenn das Backend fehlschlägt, wird eine Fallback-Fehlermeldung mit st.error() angezeigt.
Führe nun den folgenden Befehl in deinem Terminal aus:
uvicorn agents.host_agent.__main__:app --port8000&
uvicorn agents.flight_agent.__main__:app --port8001&
uvicorn agents.stay_agent.__main__:app --port8002&
uvicorn agents.activities_agent.__main__:app --port8003&
streamlit run travel_ui.pyBereitgestellt von
Wenn ein Nutzer auf "Meine Reise planen" klickt, übernimmt der Host-Agent die Aufgabe, aktiviert die Agenten und zeigt die Ergebnisse in der Benutzeroberfläche an:
Deine gesamte Dateistruktur würde etwa so aussehen:
Und das war's! Ich habe alles, was wir gebaut haben, in diesem GitHub-Projekt.
Fazit
Mit ein paar FastAPI-Apps und ADK-Agenten haben wir einen kollaborativen Reiseplaner gebaut, der:
Kommuniziert über das A2A-Protokoll
Nutzt LLM-Agenten für Flüge, Aufenthalte und Aktivitäten
Fasst die Ergebnisse zusammen und zeigt sie in einer übersichtlichen Streamlit-Benutzeroberfläche an
Auch wenn alle Agenten unter der Haube dasselbe Modell verwenden, ist dieses System ein Multi-Agenten-System, d.h. die Agenten haben unterschiedliche Rollen, isolierte Verantwortlichkeiten und eine strukturierte Kommunikation.
Ich bin Google Developers Expertin für ML (Gen AI), dreifache Kaggle-Expertin und Women-Techmakers-Botschafterin mit über drei Jahren Erfahrung in der Tech-Branche. 2020 habe ich ein Health-Tech-Startup mitgegründet und absolviere derzeit einen Master in Informatik an der Georgia Tech mit Schwerpunkt Machine Learning.
Lerne die wichtigsten Arten von KI-Agenten kennen, wie sie mit ihrer Umgebung interagieren und wie sie in verschiedenen Branchen eingesetzt werden. Verstehe einfache reflexive, modellbasierte, zielbasierte, nutzenbasierte, lernende Agenten und mehr.
Lerne, wie man mit JSON in Python arbeitet, einschließlich Serialisierung, Deserialisierung, Formatierung, Leistungsoptimierung, Umgang mit APIs und Verständnis der Einschränkungen und Alternativen von JSON.
Lerne mehr über abstrakte Klassen in Python, wozu sie gut sind und wie du mit dem Modul „abc“ einheitliche Schnittstellen sicherstellen kannst. Enthält praktische Beispiele und bewährte Methoden für eine effektive Umsetzung.
In diesem Blog zeige ich dir, wie du mit Googles neuem Open-Source-Agent Development Kit (ADK) einen KI-gesteuerten Reiseassistenten mit mehreren Agenten erstellen kannst. Agent Development Kit (ADK) und dem A2A (Agent-zu-Agent) Protokoll.
Wir verwenden mehrere Agenten, um Flüge, Hotels und Aktivitätsempfehlungen zu verwalten, die über REST-APIs und FastAPI-Server kommunizieren. Am Ende verpacken wir das Ganze in ein sauberes Streamlit-Frontend für ein intuitives Nutzererlebnis.
Wir halten unsere Leserinnen und Leser mit The Median auf dem Laufenden, unserem kostenlosen Freitags-Newsletter, der die wichtigsten Meldungen der Woche aufschlüsselt. Melde dich an und bleibe in nur ein paar Minuten pro Woche auf dem Laufenden:
Was ist das Agent Development Kit (ADK) von Google?
Das ADK von Google ist ein modulares, produktionsreifes Framework für den Aufbau von LLM-gesteuerten Agenten. Es ist das gleiche Toolkit, das auch die Agenten in den Google-Produkten wie Agentspace und Customer Engagement Suite antreibt. Jetzt open-sourcedhilft es Entwicklern, leistungsstarke, flexible und interoperable Multi-Agenten-Anwendungen zu entwickeln.
Warum das Agent Development Kit (ADK) verwenden?
ADK bietet die Flexibilität von Python mit eingebauten Strukturen für Zustandsverwaltung, Rückrufe, Streaming und strukturierte Ein-/Ausgabe. Werfen wir einen Blick auf seine wichtigsten Funktionen:
LiteLlm.Was ist das Agent2Agent (A2A) Protokoll von Google?
Das Agent2Agent (A2A)-Protokoll ist ein offener, herstellerneutraler Standard, der von Google entwickelt wurde, um eine einfache Kommunikation und Zusammenarbeit zwischen KI-Agenten über verschiedene Plattformen und Frameworks hinweg zu ermöglichen.
ADK-Agenten stellen einen Standard-HTTP-Endpunkt
/runund Metadaten über.well-known/agent.jsonzur Verfügung. Dies ermöglicht die Erkennung von Agenten und die einfache Kommunikation zwischen Agenten (oder sogar externen Orchestrierern wie LangGraph oder CrewAI).Das Hinzufügen der A2A-Metadaten-Datei ist zwar optional, macht deine Agenten aber interoperabel mit dem breiteren Ökosystem von Agententools und Orchestrierern.
Projektübersicht: KI-gestützter Reiseplaner mit ADK und A2A
In diesem Projekt wird ein Reiseplaner erstellt, der:
flight_agent: Empfiehlt Flugoptionen.stay_agent: Findet Hotels innerhalb des Budgets.activities_agent: Schlägt ansprechende Aktivitäten vor.host_agent, um alle Anfragen zu koordinieren.Alle Agenten werden als separate FastAPI-Server gehostet und stellen einen
/runEndpunkt zur Verfügung. Die Kommunikation findet über den gemeinsamen A2A-kompatiblen Client statt.Hinweis: Dieses Projekt läuft der Einfachheit halber komplett auf deinem lokalen Rechner, aber du kannst jeden Agenten und die Benutzeroberfläche auf Cloud-Plattformen wie Render, Railway oder Google Cloud Run bereitstellen, um einen skalierbaren Zugang zu erhalten.
Schritt 1: Voraussetzungen
Beginnen wir mit der Installation der folgenden Bibliotheken:
Richte dann deinen OpenAI API-Schlüssel ein - du kannst auch einen anderen Modellanbieter verwenden. Um zu erfahren, wie du deinen OpenAI-API-Schlüssel einrichtest, empfehle ich dir dieses einführende Tutorial zur GPT-4o API.
Schritt 2: Gemeinsames Schema und Dienstprogramme
Bevor wir intelligente Agenten bauen können, müssen wir eine gemeinsame Sprache definieren, in der sie miteinander sprechen können. In unserem Fall geschieht dies mit Hilfe von:
/runEndpunkt für alle Agenten zu standardisierenDiese werden in den Ordnern
shared/undcommon/abgelegt, damit der Code modular bleibt. Schauen wir uns jede einzelne davon an.Erstellen einer
shared/schemas.pyDateiWir definieren ein
TravelRequestSchema mit Pydantic. So wird sichergestellt, dass alle Agenten sich über die Struktur der eingehenden Anfragen einig sind, die das Reiseziel, die Reisedaten und das Budget des Nutzers umfasst.Dieser Kurs hilft bei:
Erstellen einer
common/a2a_client.pyDateiDieses leichtgewichtige asynchrone Dienstprogramm ermöglicht es jedem Agenten (insbesondere dem Host), einen anderen Agenten über das A2A-Protokoll aufzurufen, indem er den Endpunkt
/runaufruft.Dieses Dienstprogramm sendet asynchron eine POST-Anfrage an den
/runEndpunkt eines anderen Agenten mithttpx. Sie gibt die geparste JSON-Antwort zurück und gibt einen Fehler aus, wenn die Anfrage fehlschlägt.Wir werden dieses Dienstprogramm in unserem Host-Agenten verwenden, um
flight_agent,stay_agentundactivities_agentaufzurufen.Erstellen einer
common/a2a_server.pyDateiAnstatt für jeden Agenten eine eigene FastAPI-Route zu schreiben, verallgemeinern wir sie mit der Funktion
create_app(agent), die die/runDieses Dienstprogramm erstellt eine FastAPI-App mit einer Standardroute
/run, die die Ausführung an den angegebenen Agenten delegiert. Sie gewährleistet eine einheitliche Agent-to-Agent (A2A)-Schnittstelle für alle Dienste, die strukturierte JSON-Eingaben verwenden.Diese gemeinsamen Komponenten machen unser Multi-Agenten-System wartungsfreundlicher, wiederverwendbar und entsprechen Googles A2A-Philosophie des einfachen, strukturierten Nachrichtenaustauschs zwischen Agenten.
Schritt 3: Aufbau des Multi-Agenten-Systems mit ADK und A2A
Nachdem wir nun die gemeinsamen Verträge und Dienstprogramme eingerichtet haben, können wir mit dem Aufbau der einzelnen Agenten beginnen. Um dies in ein wirklich modulares Multi-Agenten-System zu verwandeln, verwenden wir das A2A-Protokoll von Google - eine einfache HTTP-basierte Schnittstelle, über die Agenten konsistent und interoperabel kommunizieren können.
A2A (Agent-to-Agent) ermöglicht die Plug-and-Play-Koordination zwischen Agenten, egal ob es sich um lokale Python-Funktionen oder um gehostete Agenten in Netzwerken handelt. Jeder Agent stellt einen
/runEndpunkt mit einem gemeinsamen Schema zur Verfügung und fungiert als Dienst.In unserer Demo haben wir vier Agenten:
host_agent: Orchestriert alle anderen Agentenflight_agent: Findet passende Flügestay_agent: Schlägt Unterkünfte voractivities_agent: Empfiehlt, sich an lokalen Aktivitäten zu beteiligenAlle Agenten sind ähnlich strukturiert, mit 3 Dateien und einem Unterordner:
Jeder Agent verwendet
google.adk.agents.Agent, einenLiteLlmModell-Wrapper undRunnerzur Ausführung. Beginne damit, die folgenden Dateien im Ordneractivities_agentzu erstellen und wiederhole das Gleiche fürflight_agentundstay_agent.Erstellen einer
agent.pyDateiDefinieren wir nun die Logik für unsere
activities_agent, die dafür verantwortlich ist, auf der Grundlage der Reiseroute des Nutzers ansprechende lokale Erlebnisse zu generieren.Schritt 1: Importe
Wir beginnen damit, wichtige Module zu importieren, um unseren Agenten zu konfigurieren und auszuführen.
Dieser Agent nutzt die Komponenten von Google ADK wie
Agent, 'Runner, ' undLiteLlmund verwaltet den Status mitInMemorySessionService.. Die BibliothekTypeswird für die Erstellung von strukturierten Prompts verwendet.Schritt 2: Aktivitäten Agent
Jetzt instanziieren wir den Agenten selbst mithilfe der ADK-Agentenklasse.
Der Parameter Anweisung definiert die Systemaufforderung, die das Verhalten des LLM steuert. Obwohl in diesem Beispiel einfaches Englisch verwendet wird, kannst du die Anweisung so anpassen, dass sie strukturiertes JSON zurückgibt, um das Parsen zu erleichtern.
Schritt 3: Sitzungsmanagement
Um die Interaktionen der Nutzer/innen zu verfolgen, konfigurieren wir einen Lernpfad (Runner) und die Sitzungsinformationen.
Die
Runnerverwaltet die Agentenausführung für eine bestimmte App-Sitzung. Während die KlasseInMemorySessionServiceden Kontext im Speicher speichert. Dann definieren wir Benutzer- und Sitzungs-IDs. In der Produktion können diese jedoch dynamisch oder benutzerspezifisch sein. Dadurch wird sichergestellt, dass eine neue ADK-Sitzung existiert, bevor Aufforderungen an den LLM-Agenten gesendet werden.Schritt 4: Ausführen der Agentenlogik
Die Funktion
execute()bearbeitet eingehende Anfragen, erstellt eine Eingabeaufforderung, ruft das Modell auf und analysiert die Ausgabe.Die Funktion
execute()erstellt dynamisch eine Eingabeaufforderung mit den Parametern der eingehenden Anfrage wie Zielort, Daten und Budget. Hier ist, was unter der Haube passiert:ContentObjekt wird erstellt und an den ADK Runner übergeben, der asynchron auf die endgültige Antwort des Modells mit einem Streaming-Generator wartet.Diese Strategie verbessert die Robustheit und die Benutzerfreundlichkeit, vor allem, wenn die Modellergebnisse aufgrund der Temperatur oder der Interpretation der Eingabeaufforderung leicht variieren.
Erstellen einer
task_manager.pyDateiNachdem wir die
execute()Logik inagent.pydefiniert haben, verbinden wir sie mit dem ADK-kompatiblen Server-Setup untertask_manager.py.Diese Datei dient als dünner Wrapper um die zuvor definierte Funktion
execute(). Sie macht die Methoderun()für externe Module verfügbar, insbesondere für das Serverskript in__main__.py.Erstellen einer
__main__.pyDateiDie Datei
__main__.pystartet einen FastAPI-Server auf Port 8003, der den Agenten am Endpunkt/runbedient.Hier ist, was passiert ist:
create_app()(aus common/a2a_server.py) wickelt unseren Agenten in eine A2A-kompatible FastAPI-Schnittstelle ein.execute()Methode, damit ADKrun()richtig aufrufen kann.Erstellen einer
.well-known/agent.jsonDateiWir verwenden diese JSON-Datei, um die Identität und den Zweck des Agenten gemäß dem A2A-Protokoll (Agent-to-Agent) zu beschreiben.
Hinweis: Die Datei
.well-known/agent.jsonwird zwar nicht direkt von unseren Agenten in diesem Projekt verwendet, aber sie entspricht der A2A-Spezifikation und ist wichtig für die Entdeckung, die Introspektion und die zukünftige Kompatibilität mit Orchestratoren wie LangGraph, CrewAI oder Googles Agentenregistrierung.Eine ähnliche Logik wird auch für
flight_agentundstay_agentverwendet.Schritt 4: Koordinierung mit
host_agentDie
host_agentfungiert als zentraler Planer für die Demo. Diehost_agentist ein Beispiel für das Steuerungsmuster in Multi-Agenten-Systemen. Es trennt Entscheidungsfindung und Ausführung, so dass sich jeder nachgelagerte Agent auf seine Nische konzentrieren kann, während die Koordinationslogik zentralisiert wird. Das vereinfacht nicht nur das Testen und Skalieren, sondern spiegelt auch die reale Microservice-Architektur in verteilten Systemen wider.Er sendet dieselbe Nutzlast an alle drei Agenten über ihre
/runAPIs und führt die Ergebnisse zusammen. Fügen wir die folgenden Dateien zum Ordnerhost_agenthinzu.Erstellen einer
agent.pyDateiBeginnen wir mit den Basisimporten.
Dieser Importblock enthält alle Kernbausteine, die benötigt werden, um einen LLM-basierten Agenten mit dem Google ADK zu definieren und auszuführen:
AgentKlasse, leichtgewichtiger LLM-Wrapper,Runnerfür die Ausführung und In-Memory-Session-Management.Der obige Code definiert einen ADK-Agenten auf oberster Ebene, der für die Koordinierung des gesamten Reiseplans verantwortlich ist. In dieser Implementierung rufen wir zwar keine Unteragenten aus dem LLM auf, aber die Systemaufforderung bereitet die Rolle für eine künftige Erweiterung vor, bei der der LLM möglicherweise die Verwendung von Werkzeugen und Metaüberlegungen übernehmen könnte.
Diese
execute()Funktion dient als Haupteinstiegspunkt in das LLM des Host-Agenten. Es:methodErstellen einer
task_manager.pyDateiDer Aufgabenmanager führt die Orchestrierungslogik aus, indem er Remote-Agenten aufruft und den gesamten Arbeitsablauf der Reiseplanung abwickelt. Für die praktische Umsetzung definieren wir die Service-URLs für jeden Child-Agent. Diese Endpunkte entsprechen dem A2A /run
protocol and expect a sharedTravelRequest` JSON Schema.Jetzt definieren wir die Nutzlast.
Diese Funktion verwendet die Hilfsfunktion
call_agent(), um die Nutzlast an jeden nachgelagerten Dienst zu senden, und protokolliert die Eingaben und Ausgaben, damit sie während der Entwicklung sichtbar sind. In dieser Datei befindet sich die eigentliche Orchestrierungslogik.Erstellen einer
__main__.pyDateiDie Datei
__main__.pydient als Einstiegspunkt für den FastAPI-Server, der den Host-Agenten umhüllt.Die Hauptdatei macht Folgendes:
create_app()voncommon/a2a_server.py, um eine FastAPI-Anwendung mit einem standardisierten/runEndpunkt zu erstellen.execute()Methode, die intern an dietask_manager.run()Funktion delegiert.uvicornan einem bestimmten Port (normalerweise 8000) gestartet.Dadurch wird die Schnittstelle des Host-Agenten mit anderen nachgelagerten Agenten abgeglichen und die Konsistenz im gesamten System gewahrt.
Erstellen einer
.well-known/agent.jsonDateiDiese Datei funktioniert wie ein klassisches Multi-Agenten-Muster, bei dem ein zentraler Knotenpunkt Aufgaben delegiert und zusammenstellt.
Das ist zwar optional, aber es ist eine gute Praxis, dies in alle Agentenverzeichnisse aufzunehmen, wie bereits erklärt.
Schritt 5: Erstellen der Benutzeroberfläche mit Streamlit
Schließlich wollen wir eine einfache App entwickeln, in der die Nutzer ihre Vorlieben eingeben können und eine strukturierte Reiseroute erhalten. Beginne damit, eine
travel_ui.pyDatei im Stammverzeichnis zu erstellen und füge den folgenden Code hinzu.Wir importieren grundlegende Bibliotheken wie Streamlit und Requests für die UI-Unterstützung.
Die Streamlit-App bietet eine benutzerfreundliche Oberfläche für die Interaktion mit dem Multi-Agenten-Reiseplaner, der auf ADK basiert. Hier sind ein paar Dinge, die wir im obigen Code ansprechen.
text_input,date_inputundnumber_input, um Herkunft, Ziel, Datum und Budget zu erfassen.host_agent.http://localhost:8000/run.host_agentruft alle untergeordneten Agenten (Flug, Aufenthalt, Aktivität) auf, fasst deren Antworten zusammen und liefert einen einheitlichen Reiseplan.st.markdown()unter separaten Überschriften für Flüge, Aufenthalte und Aktivitäten angezeigt.st.error()angezeigt.Führe nun den folgenden Befehl in deinem Terminal aus:
Wenn ein Nutzer auf "Meine Reise planen" klickt, übernimmt der Host-Agent die Aufgabe, aktiviert die Agenten und zeigt die Ergebnisse in der Benutzeroberfläche an:
Deine gesamte Dateistruktur würde etwa so aussehen:
Und das war's! Ich habe alles, was wir gebaut haben, in diesem GitHub-Projekt.
Fazit
Mit ein paar FastAPI-Apps und ADK-Agenten haben wir einen kollaborativen Reiseplaner gebaut, der:
Auch wenn alle Agenten unter der Haube dasselbe Modell verwenden, ist dieses System ein Multi-Agenten-System, d.h. die Agenten haben unterschiedliche Rollen, isolierte Verantwortlichkeiten und eine strukturierte Kommunikation.
Hier sind ein paar Ressourcen für den Anfang: