We’ll have an intro workshop Saturday during lunch time.

Sign up to get $300 free credits + $100 hackathon credits

<aside>

  1. Get badge - https://developers.google.com/profile/badges/events/cloud/ai-for-science-world-models-hack
  2. Check in - https://developers.google.com/profile/badges/events/cloud/ai-for-science-world-models-hack/award
  3. Google cloud sign up - https://cloud.google.com/ </aside>

The Agent Development Kit is Google's open-source framework for building AI agents that reason, call tools, and coordinate.

Code-first, you declare an agent, give it tools, it plans/acts in a loop. Model-flexible (Gemini + OpenAI/Anthropic/local), Python/TS/Go/Java.

uv pip install google-adk

Core mental model. An agent is an LLM wired to tools, functions it may call.

It reads each result and decides the next call. Everything below is just "what do you let it call?"

These are examples. You should design your own.

Tool pattern 1 — a plate-reader data-analysis agent

The agent doesn't parse curves itself; it calls deterministic code and reasons over the output. Give it a few tools and an instruction, and it becomes an analyst:

from google.adk.agents import Agent
import numpy as np
from scipy.optimize import curve_fit

def load_plate(run_id: str) -> dict:
    """Return raw OD/fluorescence per well + plate map."""
    return reader.export(run_id)   # your driver / CSV / vendor API

def fit_dose_response(conc: list[float], signal: list[float]) -> dict:
    """4-parameter logistic fit -> IC50, Hill slope, R^2."""
    def ll4(x, bottom, top, ic50, hill):
        return bottom + (top - bottom) / (1 + (x / ic50) ** hill)
    p, _ = curve_fit(ll4, conc, signal, maxfev=10000)
    resid = signal - ll4(np.array(conc), *p)
    r2 = 1 - np.sum(resid**2) / np.sum((signal - np.mean(signal))**2)
    return {"ic50": p[2], "hill": p[3], "r2": float(r2)}

def flag_qc(plate: dict) -> dict:
    """Z'-factor, edge effects, saturated wells."""
    return qc.check(plate)

analyst = Agent(
    name="plate_analyst",
    model="gemini-2.5-flash",
    instruction=(
        "Load the run, run QC first. If Z' < 0.5, stop and report why. "
        "Otherwise fit each dose series, rank hits by IC50, and summarize "
        "anomalies (edge effects, saturation) in plain language."
    ),
    tools=[load_plate, fit_dose_response, flag_qc],
)
# adk web   → chat with it + see every tool call in the trace viewer

The model handles messy branching ("QC failed because of edge effects, so re-run columns 1 and 12") without you scripting every path.

Tool pattern 2 — a literature-search agent

Two routes, both easy to explore:

(a) Wrap an API as a function tool — full control over query + parsing:

def search_pubmed(query: str, max_results: int = 10) -> list[dict]:
    """Return title/abstract/DOI for recent matches."""
    return pubmed_client.search(query, retmax=max_results)

def get_chembl_activity(target: str) -> list[dict]:
    """Known actives + assay data for a target."""
    return chembl.activities(target)

scout = Agent(
    name="lit_scout",
    model="gemini-2.5-flash",
    instruction="Given a hit, find prior art: known actives, related assays, "
                "contradicting results. Cite DOIs. Say when evidence is thin.",
    tools=[search_pubmed, get_chembl_activity],
)