Google ADK + Anchor: Browser Agents with Google's Agent Development Kit

Hands On
Jun 18
by Idan Raman
Google ADK + Anchor: Browser Agents with Google's Agent Development Kit

Google's Agent Development Kit (ADK) hit 2.0 GA in early 2026, shipping graph-based workflows, \ multi-agent fan-out/fan-in, and first-class Gemini integration. If you're already running Gemini models in production, \ ADK is the natural glue for your agentic workflows. The one gap: ADK doesn't ship with browser access. Anchor fills it.

This guide shows you how to pair ADK with Anchor's managed cloud browsers \ to build a research agent that browses the web in parallel, returning structured results back into your ADK agent graph.

Why Google ADK?

ADK gives you three things that matter for production browser agents:

  1. Graph workflows – deterministic fan-out/fan-in patterns let you spawn N browser sessions and merge results cleanly.
  2. Multi-agent architecture – delegate browsing to specialized sub-agents while a coordinator handles reasoning.
  3. Gemini-native – direct access to Gemini 2.5 Pro's 1M-token context window for summarizing long scraped pages.

Setup

pip install google-adk anchor-browser playwright
playwright install chromium
export ANCHOR_API_KEY="your_anchor_key"
export GOOGLE_API_KEY="your_google_key"

Building a Browser Tool

ADK tools are plain Python functions — pass them to Agent(tools=[...]) and ADK infers the schema \ from type hints and the docstring automatically.

import os
from anchor_browser import AnchorClient
from playwright.sync_api import sync_playwright

anchor = AnchorClient(api_key=os.environ["ANCHOR_API_KEY"])

def browse_url(url: str) -> dict:
    "Navigate to a URL and return the page title and body text (first 4 000 chars)."
    session = anchor.sessions.create(
        proxy_country="us",
        options={"adblock": True},
    )
    pw = sync_playwright().start()
    browser = pw.chromium.connect_over_cdp(session.ws_endpoint)
    page = browser.contexts[0].pages[0]

    page.goto(url, wait_until="domcontentloaded")
    title = page.title()
    body  = page.locator("body").inner_text()[:4000]

    browser.close()
    pw.stop()
    anchor.sessions.stop(session.id)

    return {"title": title, "content": body, "url": url}

A few things worth noting:

  • Each anchor.sessions.create() spins up an isolated cloud browser with a real IP and fingerprint — anti-bot systems see it as a normal user.
  • We cap inner_text at 4,000 characters so the Gemini context budget stays manageable per tool call.
  • proxy_country="us" routes the session through a US residential IP — useful when target sites geo-gate content.
  • options={"adblock": True} strips cookie banners that waste tokens and break navigation.
  • anchor.sessions.stop() frees the session immediately; without it you hold it open until timeout.

Your First ADK Browser Agent

from google.adk.agents.llm_agent import Agent
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types

root_agent = Agent(
    model="gemini-2.5-flash",
    name="web_researcher",
    description="A research agent that browses the web and summarizes findings.",
    instruction=(
        "You are a research assistant. When given a topic, "
        "browse specific URLs for relevant information "
        "and return a concise summary with key facts."
    ),
    tools=[browse_url],
)

session_service = InMemorySessionService()
runner = Runner(
    agent=root_agent,
    app_name="anchor_researcher",
    session_service=session_service,
)

session = session_service.create_session(
    app_name="anchor_researcher",
    user_id="user_01",
)

response = runner.run(
    user_id="user_01",
    session_id=session.id,
    new_message=types.Content(
        role="user",
        parts=[types.Part(text="Summarize the latest Playwright release notes.")],
    ),
)

for event in response:
    if event.is_final_response():
        print(event.content.parts[0].text)

The agent decides on its own which URL to fetch, calls browse_url, and synthesizes the result — you never hardcode the URL.

Parallel Browsing with ADK Graph Workflows

ADK 2.0 graph workflows support fan-out. Spawn multiple Anchor sessions simultaneously and merge results with ParallelAgent:

from google.adk.agents import ParallelAgent, SequentialAgent

# Sub-agent that browses one competitor page
browser_agent = Agent(
    model="gemini-2.5-flash",
    name="browser_agent",
    instruction="Browse the given URL and return all pricing information found.",
    tools=[browse_url],
)

# Coordinator: run three browser_agents in parallel, then a sequentially chained step
coordinator = SequentialAgent(
    name="pricing_researcher",
    sub_agents=[
        ParallelAgent(
            name="parallel_browsers",
            sub_agents=[browser_agent, browser_agent, browser_agent],
        )
    ],
)

Each browser_agent instance gets its own Anchor session — fully isolated fingerprints, separate IP addresses, no shared state.

Structured Output with Pydantic

For pipelines that need typed data, combine ADK's tool calling with Pydantic validation in the tool itself:

from pydantic import BaseModel
from typing import List

class PricingTier(BaseModel):
    plan: str
    monthly_usd: float
    features: List[str]

def scrape_pricing(url: str) -> dict:
    "Fetch a pricing page and return tiers as structured JSON."
    raw = browse_url(url)

    # Ask a lightweight model to extract structure from raw text
    from google.genai import Client
    client = Client()
    resp = client.models.generate_content(
        model="gemini-2.5-flash",
        contents=f"Extract pricing tiers as JSON matching this schema: {PricingTier.schema()}\n\n{raw['content']}",
    )
    return json.loads(resp.text)

Production Tips

  • Scope sessions to runs. Create a fresh Anchor session per agent run and close it in a finally block to avoid session bleed across concurrent jobs.
  • Use gemini-2.5-flash over Pro for high-throughput tasks. The latency improvement is significant when you're fanning out across 10+ pages simultaneously.
  • Cap concurrency. Anchor handles parallel sessions gracefully, but your Google API quota limits the number of simultaneous ADK tool-call evaluations.
  • Swap InMemorySessionService for a database-backed store in production — ADK supports PostgreSQL and Firestore backends for persistent multi-turn workflows.

What's Next

Try Anchor free and run your first ADK browser agent in minutes →

Stay ahead in browser automation

We respect your inbox. Privacy policy

Welcome aboard! Thanks for signing up
Oops! Something went wrong while submitting the form.