Cursus
In deze blog laat ik je stap voor stap zien hoe je een multi-agent, AI-aangedreven reisassistent bouwt met Google's nieuwe open-source Agent Development Kit (ADK) en het A2A (Agent-to-Agent)-protocol.
We gebruiken meerdere agents voor vluchten, hotels en activiteiten, die met elkaar communiceren via REST-API’s en FastAPI-servers. Tot slot verpakken we alles in een strakke Streamlit-frontend voor een intuïtieve gebruikerservaring.
Aan het einde raad ik je aan je kennis uit te breiden door een klantenservice-assistent met ADK te bouwen via onze cursus Building AI Agents With Google ADK.
We houden onze lezers op de hoogte van het laatste AI-nieuws met The Median, onze gratis vrijdagse nieuwsbrief met de belangrijkste verhalen van de week. Abonneer je en blijf scherp in een paar minuten per week:
Wat is Google’s Agent Development Kit (ADK)?
Google's ADK is een modulaire, productieklare framework voor het bouwen van LLM-aangedreven agents. Het is dezelfde toolkit die agents binnen Google-producten aandrijft, zoals Agentspace en Customer Engagement Suite. Nu open source helpt het ontwikkelaars krachtige, flexibele en interoperabele multi-agenttoepassingen te bouwen.
Waarom de Agent Development Kit (ADK) gebruiken?
ADK biedt de flexibiliteit van Python met ingebouwde structuren voor statebeheer, callbacks, streaming en gestructureerde input/output. Dit zijn de belangrijkste functies:
- Multi-agent by design: ADK kan agents samenstellen in parallelle, sequentiële of hiërarchische workflows.
- Model-agnostisch: Werkt met Gemini, GPT-4o, Claude, Mistral en anderen via
LiteLlm. - Modulair en schaalbaar: Je kunt gespecialiseerde agents definiëren en slim delegeren met ingebouwde orkestratie.
- Klaar voor streaming: Ondersteunt realtime interactie, inclusief bidirectionele audio/video.
- Ingebouwde tooling: Ondersteunt lokale CLI en web-UI voor debuggen en evaluatie.
- Ondersteunt deployment: ADK containeriseert en deployt agents eenvoudig in verschillende omgevingen.
Wat is Google’s Agent2Agent (A2A)-protocol?
Het Agent2Agent (A2A)-protocol is een open, leveranciersneutrale standaard ontwikkeld door Google om eenvoudige communicatie en samenwerking tussen AI-agents mogelijk te maken op diverse platforms en frameworks.
ADK-agents stellen een standaard /run-HTTP-endpoint en metadata via .well-known/agent.json beschikbaar. Dit maakt agentdiscovery en eenvoudige communicatie tussen agents mogelijk (of zelfs met externe orkestrators zoals LangGraph of CrewAI).
Optioneel weliswaar, maar door het A2A-metadatabestand toe te voegen worden je agents interoperabel met het bredere ecosysteem van agenttools en -orkestrators. Je kunt meer leren over Google ADK in de videotutorial hieronder of in onze praktische ADK-cursus.
Projectoverzicht: AI-aangedreven reisplanner met ADK en A2A
Dit project bouwt een reisplanner die:
- Bestemming, data en budget als input neemt.
- Drie afzonderlijke agents aanroept:
flight_agent: beveelt vluchtopties aan.stay_agent: Vindt hotels binnen het budget.activities_agent: Stelt leuke activiteiten voor.- Vervolgens een centrale
host_agentgebruikt om alle requests te orkestreren. - Tot slot een Streamlit-UI gebruikt voor de interactie met de gebruiker.
Alle agents worden gehost als afzonderlijke FastAPI-servers en stellen een /run-endpoint beschikbaar. De communicatie verloopt via de gedeelde A2A-compatibele client.
Let op: Dit project draait volledig lokaal voor de eenvoud, maar je kunt elke agent en de UI eenvoudig deployen naar cloudplatforms zoals Render, Railway of Google Cloud Run voor schaalbare toegang.
Stap 1: Vereisten
Laten we beginnen met het installeren van de volgende libraries:
pip install google-adk litellm fastapi uvicorn httpx pydantic openai streamlit
Stel daarna je OpenAI-API-sleutel in—je mag ook een andere modelprovider gebruiken. Wil je leren hoe je de OpenAI-API-sleutel instelt? Dan raad ik deze introductietutorial over de GPT-4o API aan.
export OPENAI_API_KEY="your_key_here"
Stap 2: Gedeeld schema en utilities
Voordat we slimme agents kunnen bouwen, moeten we een gemeenschappelijke taal definiëren waarmee ze met elkaar kunnen praten. In onze setup doen we dat met:
- Een gedeeld schema voor input (gedefinieerd via Pydantic)
- Een REST-clientutility om agents aan te roepen
- Een REST-serverwrapper om het
/run-endpoint bij alle agents te standaardiseren
Deze plaatsen we in de mappen shared/ en common/ om de code modulair te houden. Laten we ze één voor één bekijken.
Een shared/schemas.py-bestand maken
We definiëren een TravelRequest-schema met Pydantic. Dit zorgt ervoor dat alle agents overeenkomen over de structuur van binnenkomende requests, met bestemming, reisdata en het budget van de gebruiker.
from pydantic import BaseModel
class TravelRequest(BaseModel):
destination: str
start_date: str
end_date: str
budget: float
Deze klasse helpt bij:
- Consistente input voor alle agents.
- Automatische validatie met FastAPI.
- Vereenvoudigde herbruikbaarheid van code.
Een common/a2a_client.py-bestand maken
Deze lichte async-utility laat elke agent (vooral de host) een andere agent aanroepen via het A2A-protocol door het /run-endpoint te gebruiken.
import httpx
async def call_agent(url, payload):
async with httpx.AsyncClient() as client:
response = await client.post(url, json=payload, timeout=60.0)
response.raise_for_status()
return response.json()
Deze utility stuurt asynchroon een POST-request naar het /run-endpoint van een andere agent met httpx. Het retourneert de geparste JSON-respons en geeft een fout als het request mislukt.
We gebruiken deze utility in onze host-agent om de flight_agent, stay_agent en activities_agent aan te roepen.
Een common/a2a_server.py-bestand maken
In plaats van voor elke agent een eigen FastAPI-route te schrijven, generaliseren we dat met de functie create_app(agent), die het volgende afhandelt:
- De agent aanbieden op
/run - Een reisrequest ontvangen
- Een gestructureerde respons teruggeven
from fastapi import FastAPI
import uvicorn
def create_app(agent):
app = FastAPI()
@app.post("/run")
async def run(payload: dict):
return await agent.execute(payload)
return app
Deze utility maakt een FastAPI-app met een standaard /run-route die de uitvoering delegeert naar de meegegeven agent. Het zorgt voor een consistente agent-to-agent (A2A)-interface voor alle services met gestructureerde JSON-input.
Samen maken deze gedeelde componenten ons multi-agentsysteem beter onderhoudbaar, herbruikbaar en in lijn met Google’s A2A-filosofie van eenvoudige, gestructureerde interagent-berichten.
Stap 3: Het multi-agentsysteem bouwen met ADK en A2A
Nu de gedeelde contracten en utilities klaar zijn, bouwen we de individuele agents. Om dit echt modulair en multi-agent te maken, gebruiken we Google’s A2A-protocol—een eenvoudige, op HTTP gebaseerde interface waarmee agents consistent en interoperabel communiceren.
A2A (Agent-to-Agent) maakt plug-and-play-coördinatie tussen agents mogelijk, of het nu lokale Pythonfuncties zijn of services over netwerken. Elke agent stelt een /run-endpoint met een gemeenschappelijk schema beschikbaar en gedraagt zich als een service.
In onze demo hebben we vier agents:
host_agent: orkestreert alle andere agentsflight_agent: vindt geschikte vluchtenstay_agent: stelt accommodaties vooractivities_agent: beveelt leuke lokale activiteiten aan
Alle agents zijn vergelijkbaar opgebouwd, met 3 bestanden en een submap:
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/
Elke agent gebruikt google.adk.agents.Agent, een LiteLlm-modelwrapper en Runner voor uitvoering. Maak eerst de volgende bestanden in de map activities_agent en herhaal hetzelfde voor flight_agent en stay_agent.
Een agent.py-bestand maken
Laten we nu de logica definiëren voor onze activities_agent, die verantwoordelijk is voor het genereren van leuke lokale ervaringen op basis van de reisplanning van de gebruiker.
Stap 1: Imports
We beginnen met het importeren van essentiële modules om onze agent te configureren en uit te voeren.
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 json
Deze agent gebruikt componenten uit Google ADK zoals Agent, Runner en LiteLlm, en regelt statebeheer met InMemorySessionService. De bibliotheek types wordt gebruikt voor het opbouwen van gestructureerde prompts.
Stap 2: Activities-agent
Nu maken we de agent zelf aan met de Agent-klasse van ADK.
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."
)
)
De parameter instruction definieert de systeemprompt die het gedrag van de LLM stuurt. Hoewel dit voorbeeld Engels gebruikt, kun je de instructie aanpassen om gestructureerde JSON terug te geven voor eenvoudiger parsen.
Stap 3: Sessiebeheer
Vervolgens configureren we een Runner met sessie-informatie om gebruikersinteracties bij te houden.
session_service = InMemorySessionService()
runner = Runner(
agent=activities_agent,
app_name="activities_app",
session_service=session_service
)
USER_ID = "user_activities"
SESSION_ID = "session_activities"
De Runner beheert de uitvoering van de agent voor een specifieke app-sessie. De klasse InMemorySessionService slaat de context op in het geheugen. Daarna definiëren we user- en sessie-ID’s. In productie kunnen deze dynamisch of gebruikersspecifiek zijn. Dit zorgt ervoor dat er een frisse ADK-sessie bestaat voordat we prompts naar de LLM-agent sturen.
Stap 4: De agentlogica uitvoeren
De functie execute() verwerkt binnenkomende requests, bouwt een prompt, roept het model aan en parseert de output.
async def execute(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)])
async for 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 and isinstance(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 text
except json.JSONDecodeError as e:
print("JSON parsing failed:", e)
print("Response content:", response_text)
return {"activities": response_text} # fallback to raw text
De functie execute() bouwt dynamisch een prompt met de binnenkomende parameters zoals bestemming, data en budget. Onder de motorkap gebeurt het volgende:
- De prompt instrueert het model om een gestructureerd JSON-object met een activiteitenlijst terug te geven.
- Er wordt een
Content-object geconstrueerd en doorgegeven aan de ADK Runner, die asynchroon wacht op de definitieve respons via een streaminggenerator. - Wanneer de definitieve respons binnenkomt, extraheert de agent de ruwe tekstoutput en probeert deze als JSON te parsen.
- Als het parsen slaagt en de verwachte sleutel activities bestaat, wordt de gestructureerde data teruggegeven.
- Als de sleutel ontbreekt of misvormd is, valt de agent terug op de ruwe tekst, zodat de UI toch bruikbare output heeft.
- Deze dubbele afhandeling zorgt voor gratievolle degradatie wanneer de LLM platte tekst terugstuurt in plaats van gestructureerde JSON.
Deze strategie verbetert de robuustheid en gebruikerservaring, vooral wanneer modeloutputs licht variëren door temperatuur of promptinterpretatie.
Een task_manager.py-bestand maken
Na het definiëren van de execute()-logica in agent.py koppelen we die nu aan de ADK-compatibele serveropzet met task_manager.py.
from .agent import execute
async def run(payload):
return await execute(payload)
Dit bestand fungeert als een dunne wrapper rond de eerder gedefinieerde functie execute(). Het stelt de methode run() beschikbaar voor externe modules, met name het serverscript in __main__.py.
Een __main__.py-bestand maken
Het bestand __main__.py start een FastAPI-server op poort 8003 en bedient de agent op het /run-endpoint.
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)
Wat gebeurt hier:
- De functie
create_app()(uit common/a2a_server.py) verpakt onze agent in een standaard A2A-compatibele FastAPI-interface. - We construeren dynamisch een object met een methode
execute()zodat ADKrun()correct kan aanroepen. - Deze scheiding laat ons stateless API-interfaces behouden terwijl we de kernlogica van de agent hergebruiken.
Een .well-known/agent.json-bestand maken
We gebruiken dit JSON-bestand om de identiteit en het doel van de agent te beschrijven volgens het A2A (Agent-to-Agent)-protocol.
{
"name": "activity_agent",
"description": "Agent providing activity details."
}
Let op: Hoewel het bestand .well-known/agent.json in dit project niet direct door onze agents wordt gebruikt, voldoet het aan de A2A-specificatie en is het belangrijk voor discovery, introspectie en toekomstige compatibiliteit met orkestrators zoals LangGraph, CrewAI of Google’s agent registry.
Vergelijkbare logica wordt ook gebruikt voor flight_agent en stay_agent.
Stap 4: Coördineren met host_agent
De host_agent fungeert als centrale planner voor de demo. De host_agent illustreert het controllerpatroon in multi-agentsystemen. Het scheidt besluitvorming en uitvoering, waardoor elke downstream agent zich op zijn niche kan richten terwijl de coördinatielogica wordt gecentraliseerd. Dit vereenvoudigt niet alleen testen en schalen, maar weerspiegelt ook echte microservice-architectuur in gedistribueerde systemen.
Hij stuurt dezelfde payload naar alle drie de agents via hun /run-API’s en voegt de resultaten samen. Voeg de volgende bestanden toe aan de map host_agent.
Een agent.py-bestand maken
We beginnen met basisimports.
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
Dit importblok haalt alle kernbouwstenen binnen die nodig zijn om een LLM-gebaseerde agent te definiëren en uit te voeren met Google ADK: de klasse Agent, de lichte LLM-wrapper, de Runner voor de uitvoering en in-memory sessiebeheer.
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"
De bovenstaande code definieert een top-level ADK-agent die verantwoordelijk is voor het coördineren van het volledige reisplan. Hoewel we in deze implementatie geen subagents vanuit de LLM aanroepen, zet de systeemprompt de rol klaar voor een toekomstige uitbreiding waarin de LLM mogelijk tools gebruikt en metareasoning toepast.
async def execute(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)])
async for 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}
Deze functie execute() dient als hoofdingang voor de LLM van de host-agent. Hij:
- Initialiseert een sessie (voor geheugenondersteuning indien nodig)
- Stelt dynamisch een gebruikersprompt samen
- Stuurt die naar het model met ADK’s methode
runner.run_async() - Wacht ten slotte op de definitieve respons en extraheert die
Een task_manager.py-bestand maken
De taskmanager voert de orkestratielogica uit door externe agents aan te roepen en de volledige workflow voor reisplanning af te handelen. Voor de praktische implementatie definiëren we de service-URL’s voor elke child-agent. Deze endpoints voldoen aan het A2A-/run-protocol en verwachten een gedeeld 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"
Nu definiëren we de payload.
async def run(payload):
#Print what the host agent is sending
print("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 outputs
print("flights:", flights)
print("stay:", stay)
print("activities:", activities)
# Ensure all are dicts before access
flights = flights if isinstance(flights, dict) else {}
stay = stay if isinstance(stay, dict) else {}
activities = activities if isinstance(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.")
}
Deze functie gebruikt de helper call_agent() om de payload naar elke downstreamservice te sturen en logt input en output voor zichtbaarheid tijdens de ontwikkeling. In dit bestand leeft in wezen de echte orkestratielogica.
Een __main__.py-bestand maken
Het bestand __main__.py fungeert als entrypoint voor de FastAPI-server die de host-agent verpakt.
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)
Het main-bestand doet het volgende:
- Het gebruikt
create_app()uitcommon/a2a_server.pyom een FastAPI-applicatie te genereren met een gestandaardiseerd/run-endpoint. - Vervolgens geeft het een eenvoudig agent-achtig object met een
execute()-methode door, dat intern delegeert naar de functietask_manager.run(). - Ten slotte start het de FastAPI-server met
uvicornop een opgegeven poort (meestal 8000).
Dit brengt de interface van de host-agent in lijn met die van de downstreamagents en houdt consistentie in het hele systeem.
Een .well-known/agent.json-bestand maken
Dit bestand past in een klassiek multi-agentpatroon waarin een centraal knooppunt taken delegeert en samenstelt.
{
"name": "host_agent",
"description": "Coordinates travel planning among specialized agents."
}
Hoewel optioneel, is het een goede gewoonte om dit in alle agentmappen op te nemen, zoals eerder uitgelegd.
Stap 5: De UI bouwen met Streamlit
Tot slot bouwen we een eenvoudige app waarin gebruikers hun voorkeuren invoeren en een gestructureerde reisplanning ontvangen. Maak in de hoofdmap een bestand travel_ui.py en voeg de onderstaande code toe.
import streamlit as st
import requests
We importeren basisbibliotheken zoals Streamlit en requests voor UI-ondersteuning.
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 ✨"):
if not all([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.")
De Streamlit-app biedt een gebruiksvriendelijke UI om met de multi-agent reisplanner te werken die met ADK is gebouwd. Dit doen we hierboven:
- We gebruiken
text_input,date_inputennumber_inputom vertrekplaats, bestemming, data en budget te verzamelen. - Na het klikken op “Plan My Trip” worden de inputs gevalideerd om te zorgen dat niets leeg is.
- Als alles geldig is, wordt een JSON-payload opgebouwd en een POST-request gestuurd naar de
host_agentophttp://localhost:8000/run. - De
host_agentroept alle child-agents aan (vluchten, verblijf, activiteiten), voegt hun antwoorden samen en retourneert een eenduidig reisplan. - De respons wordt geparsed en weergegeven met
st.markdown()onder aparte koppen voor vluchten, verblijven en activiteiten. - Als de backend faalt, tonen we een foutmelding met
st.error().
Voer nu lokaal in je terminal de volgende commando’s uit:
uvicorn agents.host_agent.__main__:app --port 8000 &
uvicorn agents.flight_agent.__main__:app --port 8001 &
uvicorn agents.stay_agent.__main__:app --port 8002 &
uvicorn agents.activities_agent.__main__:app --port 8003 &
streamlit run travel_ui.py
Wanneer een gebruiker op “Plan My Trip” klikt, neemt de host-agent het over, activeert de agents en toont de resultaten in de UI:

Je totale mappenstructuur ziet er ongeveer zo uit:
ADK_demo/
├── agents/
│ ├── host_agent/
│ │ ├── agent.py
│ │ ├── task_manager.py
│ │ ├── __main__.py
│ │ └── .well-known/
│ │ └── agent.json
│ │
│ ├── flight_agent/
│ │ ├── agent.py
│ │ ├── task_manager.py
│ │ ├── __main__.py
│ │ └── .well-known/
│ │ └── agent.json
│ │
│ ├── stay_agent/
│ │ ├── agent.py
│ │ ├── task_manager.py
│ │ ├── __main__.py
│ │ └── .well-known/
│ │ └── agent.json
│ │
│ └── activities_agent/
│ ├── agent.py
│ ├── task_manager.py
│ ├── __main__.py
│ └── .well-known/
│ └── agent.json
│
├── common/
│ ├── a2a_client.py # Utility to send requests to other agents
│ └── a2a_server.py # Shared FastAPI A2A-compatible server template
│
├── shared/
│ └── schemas.py # Shared Pydantic schema
│
├── streamlit_app.py # Frontend UI for user input and response rendering
├── requirements.txt
└── README.md




En dat is het! Ik heb alles wat we hebben gebouwd samengebracht in dit GitHub-project.
Conclusie
Met slechts een paar FastAPI-apps en ADK-agents hebben we een samenwerkende reisplanner gebouwd die:
- Communiceert via het A2A-protocol
- LLM-agents gebruikt voor vluchten, verblijven en activiteiten
- Resultaten aggregeert en toont in een overzichtelijke Streamlit-UI
Hoewel alle agents onder de motorkap hetzelfde model gebruiken, is het systeem in gedrag wel degelijk multi-agent: agents hebben afzonderlijke rollen, geïsoleerde verantwoordelijkheden en gestructureerde communicatie.
Hier zijn enkele bronnen om te starten:
Ik ben een Google Developers Expert in ML (Gen AI), een Kaggle 3x Expert en een Women Techmakers Ambassador met meer dan 3 jaar ervaring in tech. In 2020 heb ik een healthtech-startup mee opgericht en ik volg een master computer science aan Georgia Tech, met als specialisatie machine learning.

