10 בניית מיומנויות

Google ADK + Pydantic AI — Multimodal ו-Type Safety

שני frameworks שמשלימים את ה-SDK landscape בצורה ייחודית. Google ADK נותן לכם multimodal-first agents עם Gemini, workflow agents מובנים (Sequential, Parallel, Loop), A2A protocol, ו-free tier נדיב שמאפשר לרוץ בעלות קרובה לאפס. Pydantic AI מביא type safety אמיתי לעולם ה-agents — שגיאות נתפסות ב-development time, לא ב-production. בפרק הזה תבנו agents עם שניהם, תשוו ביניהם, ותבינו מתי כל אחד הוא הבחירה הנכונה.

מה יהיה לך בסוף הפרק הזה
מה תוכלו לעשות אחרי הפרק הזה
לפני שמתחילים
הפרויקט שלך — קו אדום לאורך הקורס

בפרקים 5-9 בניתם סוכנים עם Anthropic SDK, Vercel AI SDK, OpenAI SDK, LangGraph, ו-CrewAI. כל SDK הציע גישה שונה: לולאות, graphs, ו-crews. בפרק הזה מוסיפים עוד שתי גישות: Google ADK עם multimodal ו-workflow agents, ו-Pydantic AI עם type safety שתופס בעיות לפני ש-code רץ. ה-tools שבניתם בפרק 3 יתחברו ישירות לשני ה-frameworks. בפרק 11 תכירו את AutoGen, Mastra, ו-emerging frameworks — שלב אחרון לפני שעוברים ל-Patterns & Techniques.

מילון מונחים — פרק 10
מונח (English) עברית הסבר
Google ADK ערכת פיתוח סוכנים של Google Agent Development Kit — framework קוד פתוח (Apache 2.0) לבניית סוכני AI עם Gemini. זמין ב-Python, TypeScript, Java, Go
LlmAgent סוכן LLM ה-class המרכזי ב-ADK. מגדיר סוכן עם name, model, instruction, ו-tools. המקביל ל-Agent ב-SDKs אחרים
SequentialAgent סוכן סדרתי Workflow agent שמריץ sub-agents בסדר קבוע. הפלט של כל אחד זמין לבא
ParallelAgent סוכן מקבילי Workflow agent שמריץ sub-agents במקביל ומאחד תוצאות
LoopAgent סוכן לולאה Workflow agent שחוזר על sub-agent עד שתנאי מתקיים (max_iterations או escalate signal)
Grounding עיגון חיבור תשובות ה-LLM למידע עדכני מ-Google Search. מפחית hallucinations ומוסיף citations
A2A Protocol פרוטוקול סוכן-לסוכן Agent-to-Agent — פרוטוקול שגוגל יזמה לתקשורת בין סוכנים. מבוסס HTTP, SSE, JSON-RPC. כעת תחת Linux Foundation
Vertex AI Agent Engine מנוע סוכנים של Vertex שירות managed של Google Cloud להרצת ADK agents בפרודקשן. Google מנהלת scaling, monitoring, ותשתית
Pydantic AI פיידנטיק AI Framework קוד פתוח ל-type-safe Python agents. מהיוצר של Pydantic (Samuel Colvin). 15K+ GitHub stars
RunContext הקשר ריצה אובייקט ב-Pydantic AI שנושא dependencies לתוך tools. מאפשר dependency injection נקי
result_type סוג תוצאה פרמטר ב-Pydantic AI Agent שמגדיר Pydantic model כפלט. ה-framework מבטיח שהתוצאה תואמת לסכמה
Logfire לוגפייר פלטפורמת observability מבית Pydantic. אינטגרציה מובנית עם Pydantic AI לtracing, metrics, ו-debugging
Durable Execution ריצה עמידה יכולת של agent לשרוד קריסות, API failures, ו-restarts. ב-Pydantic AI זה מובנה; ב-LangGraph דרך checkpointing
Multimodal Agent סוכן רב-מודאלי סוכן שמסוגל לעבד טקסט, תמונות, אודיו, ווידאו. Gemini מאפשר את כל ארבעת ה-modalities
מתחיל 15 דקות חינם

Google ADK — סקירה ופילוסופיה

Google Agent Development Kit (ADK) הוא ה-framework הרשמי של Google לבניית סוכני AI. בזמן ש-Claude SDK מיועד ל-Claude, ו-OpenAI SDK ל-GPT — ADK מיועד ל-Gemini, אבל עם twist חשוב: הוא model-agnostic ויכול לעבוד גם עם Claude ו-GPT. המוטיבציה המרכזית לשימוש ב-ADK היא ה-ecosystem של Google Cloud ו-Gemini — multimodal capabilities, 2M token context, Google Search grounding, ו-free tier שלא קיים בשום מקום אחר.

הפילוסופיה של ADK:

Google ADK במספרים (מרץ 2026)

התקנה ו-Setup

pip install google-adk

קבלו Google AI API key חינם מ-Google AI Studio ושמרו ב-.env:

GOOGLE_API_KEY=AIza...

זה הכל. ה-free tier של Gemini מאפשר 15 requests לדקה — מספיק לכל התרגילים בפרק הזה בלי לשלם שקל.

A2A Protocol — סוכנים מדברים עם סוכנים

Google לא רק בנתה ADK — היא גם יזמה את A2A (Agent-to-Agent) Protocol, פרוטוקול פתוח לתקשורת בין סוכנים. כמו ש-MCP (פרק 3) סטנדרטיזציה את הדרך שסוכנים ניגשים ל-tools — A2A סטנדרטיזציה את הדרך שסוכנים מדברים זה עם זה. A2A מבוסס על HTTP, Server-Sent Events (SSE), ו-JSON-RPC — טכנולוגיות web מוכרות. כל סוכן שתומך ב-A2A יכול לתקשר עם כל סוכן אחר — גם אם הם נבנו ב-frameworks שונים, רצים על שרתים שונים, או אפילו שייכים לחברות שונות.

מבחינה מעשית, A2A עדיין בשלבים מוקדמים (מרץ 2026), אבל הכיוון ברור: עתיד שבו סוכנים של חברות שונות ישתפו פעולה. דמיינו סוכן marketing שלכם שמדבר ישירות עם סוכן analytics של לקוח — בלי API ייעודי, בלי אינטגרציה custom. Google העבירה את A2A ל-Linux Foundation, מה שמעיד על כוונה רצינית ליצור סטנדרט תעשייתי.

עשה עכשיו 5 דקות

בדקו את ה-free tier: היכנסו ל-Google AI Studio וצרו API key. בדקו ב-dashboard שה-free tier פעיל (15 RPM). אם יש לכם כבר key — הריצו pip install google-adk ובדקו שההתקנה הצליחה עם python -c "import google.adk; print('OK')".

מתחיל 20 דקות חינם (free tier)

ה-Agent הראשון שלכם עם Gemini

ADK משתמש ב-LlmAgent (או בקיצור Agent) בתור ה-building block המרכזי. כל agent מוגדר עם name, model, instruction, ו-tools. הריצה מתבצעת דרך Runner שמנהל sessions ו-state.

נתחיל עם הדוגמה הפשוטה ביותר שאפשר — agent בלי tools, בלי session management מורכב. רק כדי לראות שהכל עובד:

דוגמה: ADK — הסוכן הפשוט ביותר (5 שורות)
from google.adk.agents import Agent
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types
import asyncio

# Minimal agent - no tools, just conversation
hello_agent = Agent(
    name="hello_agent",
    model="gemini-2.5-flash",
    instruction="You are a friendly assistant. Respond in Hebrew.",
)

async def main():
    session_service = InMemorySessionService()
    runner = Runner(
        agent=hello_agent,
        app_name="hello_app",
        session_service=session_service,
    )
    session = await session_service.create_session(
        app_name="hello_app", user_id="user_1",
    )
    message = types.Content(
        role="user",
        parts=[types.Part(text="שלום! מי אתה?")]
    )
    response = await runner.run_async(
        session_id=session.id,
        user_id="user_1",
        new_message=message,
    )
    for event in response:
        if event.is_final_response():
            print(event.content.parts[0].text)

asyncio.run(main())

כן, ADK דורש קצת יותר boilerplate מ-Pydantic AI (שם זה agent.run_sync("שלום") בשורה אחת). אבל ה-boilerplate הזה נותן לכם session management, state, ו-event streaming מהיום הראשון — דברים שתצטרכו ממילא בפרודקשן.

עכשיו נוסיף tools. הנה agent עם פונקציית weather שמדגים איך ADK הופך פונקציות Python רגילות ל-tools:

דוגמה: סוכן ADK עם tool
from google.adk.agents import Agent
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types
import asyncio

# --- Define a tool ---
def get_weather(city: str) -> dict:
    """Get the current weather for a city."""
    # In production, call a real weather API
    weather_data = {
        "Tel Aviv": {"temp": 28, "condition": "Sunny"},
        "Jerusalem": {"temp": 22, "condition": "Partly cloudy"},
        "Haifa": {"temp": 25, "condition": "Humid"},
    }
    return weather_data.get(city, {"temp": 20, "condition": "Unknown"})

# --- Define the agent ---
weather_agent = Agent(
    name="weather_agent",
    model="gemini-2.5-flash",
    instruction="""You are a helpful weather assistant.
    When asked about weather, use the get_weather tool.
    Always respond in the user's language.
    Be concise but friendly.""",
    tools=[get_weather],
)

# --- Run the agent ---
async def main():
    session_service = InMemorySessionService()
    runner = Runner(
        agent=weather_agent,
        app_name="weather_app",
        session_service=session_service,
    )

    session = await session_service.create_session(
        app_name="weather_app",
        user_id="user_1",
    )

    message = types.Content(
        role="user",
        parts=[types.Part(text="What's the weather in Tel Aviv?")]
    )

    response = await runner.run_async(
        session_id=session.id,
        user_id="user_1",
        new_message=message,
    )

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

asyncio.run(main())

כמה דברים חשובים לשים לב אליהם:

עשה עכשיו 10 דקות

בנו את ה-weather agent: העתיקו את הקוד למעלה, הוסיפו עוד 3 ערים ישראליות ל-weather_data, והריצו. שנו את ה-instruction לעברית ("אתה עוזר מזג אוויר חביב...") ובדקו שהסוכן עונה בעברית. נסו לשאול שאלה על עיר שלא קיימת — איך הסוכן מגיב?

ADK Web UI — ממשק פיתוח מובנה

ADK מגיע עם ממשק web מובנה לבדיקת סוכנים. זו אחת היתרונות הגדולים — לא צריך לבנות UI בעצמכם לזמן פיתוח:

דוגמה: הפעלת ADK Web UI
# Structure your project:
# my_agent/
#   __init__.py
#   agent.py  (must export `root_agent`)

# In agent.py:
from google.adk.agents import Agent

root_agent = Agent(
    name="my_agent",
    model="gemini-2.5-flash",
    instruction="You are a helpful assistant.",
    tools=[],
)

# From terminal, in parent directory:
# adk web my_agent

הפקודה adk web מפעילה שרת מקומי עם chat interface, trace viewer, ו-state inspector. מצוין ל-debugging ולמדידת ביצועים.

בינוני 25 דקות ~$0.05

Multimodal — ראייה, שמיעה, חיפוש

היתרון המשמעותי ביותר של Gemini — ולכן של ADK — הוא multimodal. Gemini מעבד טקסט, תמונות, וידאו, אודיו, ו-PDFs natively ב-prompt אחד. זה מאפשר לבנות סוכנים שרואים, שומעים, ומנתחים מסמכים — לא רק סוכנים שקוראים טקסט.

ניתוח תמונות — סוכן שרואה

דוגמה: סוכן שמנתח תמונות
from google.adk.agents import Agent
from google.genai import types
import base64
from pathlib import Path

# Agent that analyzes images
vision_agent = Agent(
    name="vision_agent",
    model="gemini-2.5-flash",
    instruction="""You are a visual analysis expert.
    When given an image, provide:
    1. A brief description of what you see
    2. Key objects and their positions
    3. Any text visible in the image
    4. Relevant insights for the user's question
    Be specific and factual. Do not hallucinate details.""",
)

# To send an image, include it in the Content:
async def analyze_image(runner, session, image_path: str, question: str):
    image_bytes = Path(image_path).read_bytes()

    message = types.Content(
        role="user",
        parts=[
            types.Part.from_image(
                image=types.Image(
                    image_bytes=image_bytes,
                    mime_type="image/jpeg",
                )
            ),
            types.Part(text=question),
        ],
    )

    response = await runner.run_async(
        session_id=session.id,
        user_id="user_1",
        new_message=message,
    )
    return response

Use case למשווקים: סוכן multimodal יכול לנתח screenshots של מודעות מתחרים, לזהות אלמנטים עיצוביים, לקרוא טקסט מתוך תמונות (OCR), ולהשוות creative שונים. במקום לשבת שעה על competitor analysis — שלחו 10 screenshots לסוכן ותקבלו דוח מובנה תוך דקה. סוכן vision של ADK מצטיין במיוחד בניתוח UI/UX, קריאת infographics, וזיהוי branding patterns.

Google Search Grounding — סוכן שמחפש

אחד ה-features החזקים ביותר של ADK: הסוכן יכול לחפש ב-Google Search כדי לבסס תשובות על מידע עדכני. זה מפחית hallucinations ומוסיף citations אוטומטיים.

דוגמה: סוכן עם Google Search
from google.adk.agents import Agent
from google.adk.tools import google_search

research_agent = Agent(
    name="research_agent",
    model="gemini-2.5-flash",
    instruction="""You are a research assistant.
    Use Google Search to find current, accurate information.
    Always cite your sources.
    Focus on factual, verifiable claims.""",
    tools=[google_search],
)

# The agent will automatically search Google when
# it needs current information. Results come with
# citations and source URLs.
זהירות: Google Search — עלויות ב-production

Google Search grounding חינם ב-AI Studio, אבל ב-Vertex AI הוא עולה $35 per 1K grounded queries. ב-prototyping זה לא בעיה (free tier), אבל ב-production — חשבו על זה. אם אתם צריכים search בזול, שקלו Serper API ($50 ל-50K queries) או Tavily.

Long Context — 2M tokens

Gemini תומך ב-context window של 2 מיליון tokens — פי 10 מ-Claude (200K) ופי 16 מ-GPT-4o (128K). בפועל זה אומר:

אבל יש trade-off: ככל שה-context ארוך יותר, הזמן והעלות עולים. Gemini Flash-Lite עם 2M tokens context עדיין יעלה $200 per 1M tokens — זה לא free tier.

עשה עכשיו 10 דקות

בנו vision agent: קחו screenshot של אתר שלכם (או כל אתר) ושלחו אותו ל-vision agent עם השאלה "What can be improved in the UX of this website?". בדקו את איכות התשובה. Gemini טוב במיוחד בניתוח UI/UX של screenshots.

בינוני 20 דקות חינם

Tools ב-ADK — Built-in ו-Custom

ADK מציע שלוש קטגוריות של tools:

  1. Built-in tools: Google Search, Code Execution, Vertex AI extensions
  2. Custom tools: פונקציות Python שאתם מגדירים (כמו הדוגמה למעלה)
  3. MCP tools: חיבור ל-MCP servers חיצוניים

Custom Tools — פונקציות Python

ב-ADK, כל פונקציית Python עם type hints ו-docstring יכולה להפוך ל-tool. ADK קורא את ה-signature ואת ה-docstring כדי לייצר tool schema אוטומטית:

דוגמה: Custom tools עם type hints
from typing import Optional

def search_products(
    query: str,
    category: Optional[str] = None,
    max_results: int = 5,
) -> list[dict]:
    """Search for products in the catalog.

    Args:
        query: Search keywords (e.g., "wireless headphones")
        category: Optional category filter (e.g., "electronics")
        max_results: Maximum number of results to return (default: 5)

    Returns:
        A list of matching products with name, price, and rating.
    """
    # Your product search logic here
    return [
        {"name": "Example Product", "price": 99.99, "rating": 4.5}
    ]

def calculate_discount(
    original_price: float,
    discount_percent: float,
) -> dict:
    """Calculate the discounted price.

    Args:
        original_price: The original price in dollars
        discount_percent: The discount percentage (0-100)

    Returns:
        Original price, discount amount, and final price.
    """
    discount_amount = original_price * (discount_percent / 100)
    final_price = original_price - discount_amount
    return {
        "original": original_price,
        "discount": round(discount_amount, 2),
        "final": round(final_price, 2),
    }

# Use in agent:
shop_agent = Agent(
    name="shop_agent",
    model="gemini-2.5-flash",
    instruction="You help customers find and compare products.",
    tools=[search_products, calculate_discount],
)

הכלל: ה-docstring הוא ה-prompt engineering של tools. ככל שה-docstring יותר ברור — ה-LLM ישתמש ב-tool יותר נכון. תמיד כתבו docstring מפורט עם Args ו-Returns.

Code Execution — הסוכן שכותב קוד

דוגמה: סוכן עם Code Execution
from google.adk.agents import Agent
from google.adk.tools import built_in_code_execution

analyst_agent = Agent(
    name="data_analyst",
    model="gemini-2.5-flash",
    instruction="""You are a data analyst.
    When asked to analyze data, write and execute Python code.
    Use matplotlib for charts, pandas for data manipulation.
    Always show your calculations.""",
    tools=[built_in_code_execution],
)

# The agent can now write and run Python code
# in a sandboxed environment, create charts,
# and return results.

Code Execution רץ ב-sandboxed environment עם גישה ל-numpy, pandas, matplotlib, ועוד. הסוכן יכול לכתוב קוד, להריץ אותו, לראות את התוצאה, ולתקן שגיאות — הכל אוטומטית.

MCP Tools — חיבור לעולם החיצון

כמו שלמדנו בפרק 3, MCP (Model Context Protocol) הוא הסטנדרט לחיבור סוכנים ל-tools חיצוניים. ADK תומך ב-MCP natively — אתם יכולים לחבר כל MCP server כ-tool provider:

דוגמה: חיבור MCP server ל-ADK
from google.adk.agents import Agent
from google.adk.tools.mcp_tool import MCPToolset, SseServerParams

# Connect to an MCP server (e.g., filesystem server)
mcp_tools = MCPToolset(
    connection_params=SseServerParams(
        url="http://localhost:3001/sse",
    )
)

# Agent with both custom tools and MCP tools
file_agent = Agent(
    name="file_agent",
    model="gemini-2.5-flash",
    instruction="""You can read and analyze files.
    Use the available tools to access the filesystem.""",
    tools=[mcp_tools],
)

המשמעות המעשית: אם כבר בניתם MCP server בפרק 3, אתם יכולים לחבר אותו ל-ADK agent בלי לשכתב שום tool. הserver שעובד עם Claude SDK — עובד גם עם ADK. זה הכוח של סטנדרטים פתוחים.

עשה עכשיו 5 דקות

הוסיפו Code Execution: קחו את ה-weather agent מהדוגמה הקודמת והוסיפו built_in_code_execution לרשימת ה-tools. בקשו מהסוכן: "Get weather for Tel Aviv, Jerusalem, and Haifa, then create a comparison chart". הסוכן יקרא ל-tool, יקבל data, ואז יכתוב קוד matplotlib ליצירת graph.

בינוני 25 דקות ~$0.10

Multi-Agent — Sequential, Parallel, Loop

כאן ADK באמת בולט. במקום שה-LLM יחליט מתי לקרוא לאיזה sub-agent (כמו ב-CrewAI Hierarchical), ADK מציע Workflow Agents — patterns דטרמיניסטיים שמבטיחים שהדברים ירוצו בדיוק כמו שרציתם:

Workflow Agent מתי להשתמש דוגמה
SequentialAgent כשמשימות צריכות לרוץ בסדר קבוע Research → Write → Review
ParallelAgent כשמשימות עצמאיות יכולות לרוץ במקביל Search Google + Search Database + Check Cache
LoopAgent כשצריך לחזור עד שתנאי מתקיים Write draft → Review → fix (until quality > 8)
דוגמה: Research Pipeline עם SequentialAgent
from google.adk.agents import Agent, SequentialAgent
from google.adk.tools import google_search

# Agent 1: Researcher
researcher = Agent(
    name="researcher",
    model="gemini-2.5-flash",
    instruction="""You are a research specialist.
    Search for information on the given topic.
    Write detailed research notes with sources.
    Save your findings to state['research_notes'].""",
    tools=[google_search],
)

# Agent 2: Analyst
analyst = Agent(
    name="analyst",
    model="gemini-2.5-flash",
    instruction="""You are a data analyst.
    Read the research notes from state['research_notes'].
    Identify key trends, statistics, and insights.
    Organize findings into a structured analysis.
    Save to state['analysis'].""",
)

# Agent 3: Writer
writer = Agent(
    name="writer",
    model="gemini-2.5-flash",
    instruction="""You are a professional content writer.
    Read the analysis from state['analysis'].
    Write a polished, engaging article (500-800 words).
    Include an executive summary, key findings, and conclusion.""",
)

# Pipeline: researcher -> analyst -> writer
research_pipeline = SequentialAgent(
    name="research_pipeline",
    sub_agents=[researcher, analyst, writer],
)

# This is now your root_agent:
root_agent = research_pipeline

ParallelAgent — ריצה במקביל

דוגמה: ParallelAgent לאיסוף מידע
from google.adk.agents import Agent, ParallelAgent, SequentialAgent

# Three agents that search different sources simultaneously
web_searcher = Agent(
    name="web_searcher",
    model="gemini-2.5-flash",
    instruction="Search the web for the given topic. Focus on recent news.",
    tools=[google_search],
)

academic_searcher = Agent(
    name="academic_searcher",
    model="gemini-2.5-flash",
    instruction="Find academic papers and research on the topic.",
)

market_searcher = Agent(
    name="market_searcher",
    model="gemini-2.5-flash",
    instruction="Find market data, company reports, and industry analysis.",
)

# Run all three searches simultaneously
parallel_search = ParallelAgent(
    name="parallel_search",
    sub_agents=[web_searcher, academic_searcher, market_searcher],
)

# Then synthesize results
synthesizer = Agent(
    name="synthesizer",
    model="gemini-2.5-flash",
    instruction="""Combine findings from all three searches.
    Create a comprehensive report with sections from each source.""",
)

# Full pipeline: parallel search -> synthesize
root_agent = SequentialAgent(
    name="full_pipeline",
    sub_agents=[parallel_search, synthesizer],
)

LoopAgent — שיפור איטרטיבי

דוגמה: LoopAgent לכתיבה עם שיפור
from google.adk.agents import Agent, LoopAgent

# Writer drafts content
drafter = Agent(
    name="drafter",
    model="gemini-2.5-flash",
    instruction="""Write or improve the current draft.
    If there is reviewer feedback in state, address it.
    Save your draft to state['current_draft'].""",
)

# Reviewer evaluates quality (1-10)
reviewer = Agent(
    name="reviewer",
    model="gemini-2.5-flash",
    instruction="""Review the draft in state['current_draft'].
    Score it 1-10 on clarity, accuracy, and engagement.
    If score >= 8, call the escalate tool to finish.
    If score < 8, provide specific improvement suggestions.""",
)

# Loop: write -> review -> repeat until quality >= 8
editing_loop = LoopAgent(
    name="editing_loop",
    sub_agents=[drafter, reviewer],
    max_iterations=3,  # Safety limit
)
עשה עכשיו 15 דקות

בנו Research Pipeline: צרו SequentialAgent עם researcher → analyst → writer. הריצו על הנושא "AI agents market in Israel 2026". בדקו את ה-output — האם כל שלב קיבל את המידע מהשלב הקודם? כמה זמן הריצה לקחה?

תרגיל 1 (בינוני): Multi-Agent Content Pipeline 30 דקות

מטרה: בניית pipeline מלא שמשלב את כל סוגי ה-Workflow Agents.

  1. צרו ParallelAgent עם 2 researchers (web + academic)
  2. עטפו ב-SequentialAgent: parallel research → analysis agent → writing agent
  3. הוסיפו LoopAgent על ה-writing agent + reviewer (max 2 iterations)
  4. הריצו על נושא לבחירתכם ובדקו את כל ה-outputs

Success criteria: Pipeline רץ end-to-end. Research agents מייצרים findings שונים. Writer משתפר אחרי review.

עלות: ~$0.10-0.20 (Gemini Flash free tier)

בינוני 15 דקות חינם

State, Memory ו-Artifacts

ADK מנהל שלושה סוגים של מידע:

דוגמה: שימוש ב-Session State
from google.adk.agents import Agent
from google.adk.tools import ToolContext

def save_preference(
    key: str,
    value: str,
    tool_context: ToolContext,
) -> str:
    """Save a user preference to session state.

    Args:
        key: The preference name (e.g., "language", "format")
        value: The preference value (e.g., "Hebrew", "markdown")

    Returns:
        Confirmation message.
    """
    tool_context.state[key] = value
    return f"Saved {key} = {value}"

def get_preference(
    key: str,
    tool_context: ToolContext,
) -> str:
    """Get a user preference from session state.

    Args:
        key: The preference name to look up

    Returns:
        The preference value, or 'not set' if not found.
    """
    return tool_context.state.get(key, "not set")

preferences_agent = Agent(
    name="preferences_agent",
    model="gemini-2.5-flash",
    instruction="""You remember user preferences.
    Save preferences when the user tells you something.
    Use saved preferences to personalize responses.""",
    tools=[save_preference, get_preference],
)

ToolContext הוא ה-dependency injection mechanism של ADK. כשפונקציה מקבלת פרמטר מסוג ToolContext, ADK מזריק אותו אוטומטית — ה-LLM לא רואה אותו ולא צריך לשלוח אותו.

Persistent State — Firestore / Database

לפרודקשן, החליפו InMemorySessionService ב-DatabaseSessionService שמתחבר ל-Firestore או PostgreSQL. State נשמר בין restarts — המשתמש יכול לחזור אחרי שבוע והסוכן ימשיך מאיפה שהפסיק.

דוגמה: Persistent sessions עם DatabaseSessionService
from google.adk.sessions import DatabaseSessionService

# For production - sessions survive restarts
session_service = DatabaseSessionService(
    db_url="postgresql://user:pass@localhost/agents_db"
)

# Or with Firestore (Google Cloud native)
# session_service = FirestoreSessionService(
#     project_id="my-gcp-project",
#     collection="agent_sessions",
# )

# Use exactly like InMemorySessionService:
runner = Runner(
    agent=my_agent,
    app_name="production_app",
    session_service=session_service,
)

ההבדל בין InMemory ל-Database הוא שורה אחת. זו דוגמה טובה לdesign של ADK — הinterface זהה, רק ה-backend משתנה. פתחו עם InMemory לפיתוח, עברו ל-Database לstaging/production.

Artifacts — קבצים שהסוכן מייצר

Artifacts הם קבצים שסוכנים מייצרים במהלך עבודתם — דוחות PDF, תמונות שנוצרו, קבצי CSV עם data. ADK שומר אותם עם metadata (מי יצר, מתי, באיזה session) ומאפשר גישה דרך artifact service. בfree tier, artifacts נשמרים בזיכרון; ב-Vertex AI הם נשמרים ב-Cloud Storage אוטומטית.

בינוני 15 דקות $0 (documentation)

Vertex AI — Deploy לפרודקשן

Vertex AI Agent Engine הוא managed service של Google Cloud להרצת ADK agents. Google מנהלת scaling, monitoring, ותשתית — אתם מתמקדים בלוגיקת ה-agent.

דוגמה: Deploy ל-Vertex AI Agent Engine
from google.adk.agents import Agent
from vertexai import agent_engines

# Define your agent as usual
my_agent = Agent(
    name="production_agent",
    model="gemini-2.5-flash",
    instruction="You are a production-ready assistant.",
    tools=[...],
)

# Deploy to Vertex AI Agent Engine
remote_agent = agent_engines.create(
    agent_engine=my_agent,
    requirements=["google-adk"],
    display_name="My Production Agent",
)

# Now query it via REST API or SDK
response = remote_agent.query(
    user_id="user_123",
    message="Hello!",
)
print(response)

Vertex AI Agent Engine מספק:

הקשר ישראלי: Google Cloud regions

ל-Google Cloud יש region ב-tel-aviv (me-west1). זה אומר שהסוכנים שלכם יכולים לרוץ מישראל עם latency נמוך. לעסקים שצריכים data residency בישראל — זה פתרון מעולה. אבל שימו לב: לא כל ה-Vertex AI services זמינים ב-me-west1. בדקו תמיד ב-documentation.

Framework: מתי להשתמש ב-Google ADK

"The ADK Decision Triangle" — שלושה סימנים שאתם צריכים ADK:

  1. Multimodal: הסוכן צריך לעבד תמונות, וידאו, או אודיו — לא רק טקסט
  2. Google ecosystem: אתם כבר ב-GCP, Firestore, BigQuery, או Google Workspace
  3. Cost sensitivity: אתם צריכים אלפי agent calls ביום ולא יכולים לשלם $5/1M tokens של Opus 4.6

סימנים שאתם לא צריכים ADK:

מתחיל 15 דקות חינם

Pydantic AI — סקירה ופילוסופיה

Pydantic AI שונה מ-Pydantic הרגיל — זו ספרייה שנבנתה מאפס לסוכני AI עם type safety, dependency injection ו-structured output מובנים. Pydantic AI הוא framework ל-agents שמביא את הפילוסופיה של type safety לעולם ה-AI agents. נבנה על ידי Samuel Colvin — היוצר של Pydantic עצמו, הספרייה שנמצאת בבסיס של FastAPI, LangChain, ורוב ה-Python ecosystem המודרני.

הפילוסופיה:

Pydantic AI במספרים (מרץ 2026)

התקנה ו-Setup

pip install pydantic-ai

לתמיכה בכל ה-providers:

pip install 'pydantic-ai[openai,anthropic,google]'

שימו לב: Pydantic AI צריך Pydantic v2+. אם אתם על v1 — שדרגו עם pip install --upgrade pydantic.

Pydantic v2 — תאימות ומעבר מ-v1

Pydantic v2 הוא דרישה מחייבת ל-Pydantic AI. אם הפרויקט שלכם עדיין על Pydantic v1 (שנשתחרר ב-2019), תצטרכו לשדרג. הנה הנקודות המרכזיות:

דוגמה: הבדלים עיקריים בין Pydantic v1 ל-v2
# --- Pydantic v1 (old) ---
from pydantic import BaseModel, validator

class UserV1(BaseModel):
    name: str
    age: int

    @validator("age")
    def check_age(cls, v):
        if v < 0:
            raise ValueError("Age must be positive")
        return v

    class Config:
        orm_mode = True

# --- Pydantic v2 (current - required for Pydantic AI) ---
from pydantic import BaseModel, field_validator, ConfigDict

class UserV2(BaseModel):
    model_config = ConfigDict(from_attributes=True)  # was orm_mode

    name: str
    age: int

    @field_validator("age")
    @classmethod
    def check_age(cls, v: int) -> int:
        if v < 0:
            raise ValueError("Age must be positive")
        return v

השינויים המרכזיים ב-v2:

בדיקת גרסה לפני שמתחילים

הריצו python -c "import pydantic; print(pydantic.__version__)". אם התוצאה מתחילה ב-1.x — אתם צריכים לשדרג. שימו לב: Pydantic v2 כולל pydantic.v1 compatibility module, אבל Pydantic AI לא משתמש בו — הוא דורש v2 native. אם יש לכם קוד ישן שתלוי ב-v1, שקלו venv נפרד לפרויקטי Pydantic AI.

מתחיל 20 דקות ~$0.05

ה-Agent הראשון עם Pydantic AI

Agent ב-Pydantic AI מוגדר דרך class Agent עם model, system prompt, result type, ו-tools. ה-API נקי ו-Pythonic:

דוגמה: סוכן Pydantic AI בסיסי
from pydantic_ai import Agent

# Simplest possible agent
simple_agent = Agent(
    model="openai:gpt-4o-mini",
    system_prompt="You are a helpful assistant. Be concise.",
)

# Synchronous usage (for scripts)
result = simple_agent.run_sync("What is the capital of Israel?")
print(result.output)  # "The capital of Israel is Jerusalem."

# Async usage (for production)
import asyncio

async def main():
    result = await simple_agent.run("What is the capital of Israel?")
    print(result.output)

asyncio.run(main())

שלוש שורות להגדרת agent, שורה אחת להרצה. שימו לב ל-run_sync לשימוש ב-scripts פשוטים ול-run (async) לproduction code. הגמישות הזו חשובה — אתם יכולים לנסות רעיון ב-3 שורות בJupyter notebook, ואז להעביר את אותו agent ל-FastAPI server בלי לשנות את ההגדרה. אבל הכוח האמיתי של Pydantic AI הוא ב-structured output ו-type safety:

דוגמה: Structured Output עם Pydantic Model
from pydantic import BaseModel
from pydantic_ai import Agent

class CityInfo(BaseModel):
    """Information about a city."""
    name: str
    country: str
    population: int
    known_for: list[str]
    best_season_to_visit: str

# Agent with typed result
city_agent = Agent(
    model="openai:gpt-4o-mini",
    system_prompt="You are a travel expert. Provide accurate city information.",
    result_type=CityInfo,  # <- The magic!
)

result = city_agent.run_sync("Tell me about Tel Aviv")
city: CityInfo = result.output

# Now you have a fully typed object:
print(city.name)           # "Tel Aviv"
print(city.population)     # 460613
print(city.known_for)      # ["beaches", "nightlife", "startups", ...]
print(city.best_season_to_visit)  # "Spring (March-May)"

# Type checking works! Your IDE shows autocomplete.
# If the LLM returns invalid data, Pydantic validates
# and asks the LLM to try again automatically.

שימו לב למה שקורה כאן: result_type=CityInfo אומר ל-Pydantic AI שהתוצאה חייבת להיות CityInfo תקין. אם ה-LLM מחזיר JSON שלא עובר validation — Pydantic AI מבקש ממנו לתקן אוטומטית. אתם מקבלים Python object עם autocomplete, type checking, ו-validation — לא string שצריך לפרסר בעצמכם.

דוגמה מעשית: Lead Qualification Agent

הנה דוגמה מעשית יותר — סוכן שמסווג לידים נכנסים עבור חברת SaaS ישראלית. שימו לב איך result_type הופך את הפלט ממשפט חופשי ("This lead looks promising") לאובייקט מובנה שאפשר לשמור ב-CRM, לסנן, ולהציג ב-dashboard:

דוגמה: Lead Qualification עם Pydantic AI
from pydantic import BaseModel, Field
from pydantic_ai import Agent
from enum import Enum

class LeadScore(str, Enum):
    HOT = "hot"
    WARM = "warm"
    COLD = "cold"

class QualifiedLead(BaseModel):
    """Structured lead qualification result."""
    company_name: str
    score: LeadScore
    estimated_deal_size_usd: int = Field(ge=0)
    icp_match_percent: int = Field(ge=0, le=100)
    next_action: str
    reasoning: str
    disqualification_reason: str | None = None

lead_agent = Agent(
    model="openai:gpt-4o-mini",
    system_prompt="""You are a lead qualification specialist for
    an Israeli B2B SaaS company selling marketing automation.
    Our ICP: companies with 50-500 employees, B2B,
    tech/finance/healthcare, based in US/EU/IL.
    Qualify each lead as hot/warm/cold based on fit.""",
    result_type=QualifiedLead,
)

# Run qualification
result = lead_agent.run_sync(
    "New inbound lead: Sarah Chen, VP Marketing at HealthTech Inc. "
    "200 employees, Series B, San Francisco. Downloaded our ROI "
    "calculator and requested a demo."
)

lead = result.output
print(f"Score: {lead.score}")          # LeadScore.HOT
print(f"Deal size: ${lead.estimated_deal_size_usd:,}")
print(f"ICP match: {lead.icp_match_percent}%")
print(f"Next: {lead.next_action}")

# This is a real Python object - use it in your code:
if lead.score == LeadScore.HOT and lead.icp_match_percent > 80:
    # Auto-assign to senior AE, send to CRM
    assign_to_senior_rep(lead)
elif lead.score == LeadScore.COLD:
    # Add to nurture sequence
    add_to_nurture(lead)

שימו לב ל-Field(ge=0, le=100) — constraints ברמת השדה. אם ה-LLM מחזיר icp_match_percent: 150, Pydantic תופס את זה ומבקש תיקון. זה validation שנכנס חינם — אתם לא כותבים if score > 100: raise בעצמכם. בסביבת production עם אלפי לידים ביום, ה-validation הזה חוסך שעות של debugging.

עשה עכשיו 10 דקות

בנו city agent: העתיקו את הקוד, החליפו את ה-model ל-"anthropic:claude-sonnet-4-20250514" (או "google-gla:gemini-2.5-flash"), והריצו על 3 ערים שונות. שנו את ה-CityInfo model — הוסיפו average_rent_usd: Optional[int] ובדקו שהסוכן ממלא את השדה הנוסף. שימו לב איך autocomplete עובד על ה-result.

מודלים שונים — אותו קוד

אחד היתרונות הגדולים של Pydantic AI: אתם יכולים להחליף model בלי לשנות שום קוד אחר:

דוגמה: אותו agent, מודלים שונים
from pydantic_ai import Agent

agent = Agent(
    model="openai:gpt-4o-mini",          # OpenAI
    # model="anthropic:claude-sonnet-4-20250514",  # Anthropic
    # model="google-gla:gemini-2.5-flash",       # Google
    # model="groq:llama-3.3-70b-versatile",   # Groq
    # model="ollama:llama3.2",                 # Local (Ollama)
    system_prompt="You are helpful.",
)

# Or override at runtime:
result = agent.run_sync(
    "Hello!",
    model="anthropic:claude-sonnet-4-20250514",  # Use Claude for this run
)
בינוני 25 דקות ~$0.10

Tools, Dependencies ו-Structured Output

Tools ב-Pydantic AI מוגדרים עם decorator @agent.tool. מה שמיוחד: הם מקבלים dependencies דרך RunContext — זה dependency injection pattern שמאפשר לכם להעביר database connections, API clients, ו-configuration לתוך tools בצורה נקייה ו-type-safe:

דוגמה: Tools עם Dependencies
from dataclasses import dataclass
from pydantic import BaseModel
from pydantic_ai import Agent, RunContext

# --- Define dependencies ---
@dataclass
class MarketingDeps:
    """Dependencies injected into tools at runtime."""
    api_key: str
    company_name: str
    target_audience: str

# --- Define result type ---
class MarketingReport(BaseModel):
    """Structured marketing report."""
    company: str
    target_audience: str
    competitors: list[str]
    recommendations: list[str]
    estimated_budget_usd: int

# --- Create agent with deps type ---
marketing_agent = Agent(
    model="openai:gpt-4o",
    system_prompt="""You are a senior marketing strategist.
    Analyze the market and provide actionable recommendations.
    Use the tools available to gather data.""",
    deps_type=MarketingDeps,
    result_type=MarketingReport,
)

# --- Define tools with @agent.tool ---
@marketing_agent.tool
async def search_competitors(
    ctx: RunContext[MarketingDeps],
    industry: str,
) -> list[dict]:
    """Search for competitors in the given industry.

    Args:
        industry: The industry to search (e.g., "SaaS", "e-commerce")

    Returns:
        List of competitors with name and description.
    """
    # Access dependencies via ctx.deps
    company = ctx.deps.company_name

    # In production, call a real API
    return [
        {"name": "Competitor A", "description": f"Main rival to {company}"},
        {"name": "Competitor B", "description": "Rising challenger"},
    ]

@marketing_agent.tool
async def get_audience_insights(
    ctx: RunContext[MarketingDeps],
) -> dict:
    """Get insights about the target audience.

    Returns:
        Demographics, interests, and behavior patterns.
    """
    audience = ctx.deps.target_audience
    return {
        "segment": audience,
        "avg_age": 28,
        "interests": ["technology", "startups", "innovation"],
        "preferred_channels": ["LinkedIn", "Twitter", "YouTube"],
    }

# --- Run the agent ---
async def main():
    deps = MarketingDeps(
        api_key="sk-...",
        company_name="TechStartup IL",
        target_audience="Israeli tech professionals",
    )

    result = await marketing_agent.run(
        "Create a marketing strategy for our company",
        deps=deps,
    )

    report: MarketingReport = result.output
    print(f"Company: {report.company}")
    print(f"Budget: ${report.estimated_budget_usd}")
    for rec in report.recommendations:
        print(f"  - {rec}")

שימו לב לכמה דברים מרכזיים:

System Prompt Functions — prompts דינמיים

דוגמה: Dynamic System Prompt
from pydantic_ai import Agent, RunContext
from datetime import date

agent = Agent(
    model="openai:gpt-4o-mini",
    deps_type=MarketingDeps,
    result_type=MarketingReport,
)

@agent.system_prompt
async def dynamic_prompt(ctx: RunContext[MarketingDeps]) -> str:
    """Generate system prompt based on dependencies."""
    return f"""You are a marketing strategist for {ctx.deps.company_name}.
    Today's date: {date.today()}.
    Target audience: {ctx.deps.target_audience}.
    Focus on the Israeli market and local competitors.
    Provide recommendations in both Hebrew and English."""

System prompts יכולים להיות פונקציות — הם רצים לפני כל ריצת agent ויכולים להתבסס על dependencies, תאריך, או כל context אחר. זה הרבה יותר גמיש מ-string סטטי.

Streaming — תוצאות בזמן אמת

ב-production, אתם לא רוצים שהמשתמש יחכה 10 שניות לתוצאה מלאה. Pydantic AI תומך ב-streaming עם run_stream — ה-output מגיע בחלקים, token אחרי token:

דוגמה: Streaming עם Pydantic AI
from pydantic_ai import Agent

agent = Agent(
    model="openai:gpt-4o-mini",
    system_prompt="You are a marketing copywriter. Write in Hebrew.",
)

async def stream_response():
    async with agent.run_stream("כתוב 3 כותרות לקמפיין השקה") as result:
        async for chunk in result.stream_text():
            print(chunk, end="", flush=True)
        # After stream completes, get usage info:
        final = await result.get_output()
        print(f"\n\nTokens used: {result.usage().total_tokens}")

עם result_type מוגדר, streaming עובד אחרת — אתם מקבלים partial objects שמתמלאים בהדרגה. זה שימושי ל-UI שמציג טופס שמתמלא בזמן אמת.

Error Handling — טיפול בשגיאות graceful

Pydantic AI מגדיר exception types ברורים שמאפשרים טיפול מדויק בשגיאות:

דוגמה: Error handling patterns
from pydantic_ai import Agent
from pydantic_ai.exceptions import (
    UnexpectedModelBehavior,
    UserError,
)

agent = Agent(
    model="openai:gpt-4o-mini",
    system_prompt="You are helpful.",
    result_type=MyResultModel,
)

try:
    result = agent.run_sync("Analyze this lead")
except UnexpectedModelBehavior as e:
    # Model returned invalid output after max retries
    print(f"Model failed to produce valid output: {e}")
    # Fallback: use a different model or return default
    result = agent.run_sync(
        "Analyze this lead",
        model="anthropic:claude-sonnet-4-20250514",  # Try different model
    )
except UserError as e:
    # Configuration error (wrong model name, missing deps, etc.)
    print(f"Configuration error: {e}")
except Exception as e:
    # Network errors, API rate limits, etc.
    print(f"Unexpected error: {e}")

UnexpectedModelBehavior נזרק כשה-LLM לא מצליח לייצר output תקין גם אחרי retries אוטומטיים. ב-production, תפסו את ה-exception הזה ונסו model אחר — זו אחת היתרונות של model-agnostic: ה-fallback הוא שורה אחת.

תרגיל 2 (בינוני): Type-Safe Marketing Agent 30 דקות

מטרה: בניית agent שלם עם Pydantic AI, כולל tools, dependencies, ו-structured output.

  1. הגדירו @dataclass ל-dependencies: API key, company name, industry
  2. הגדירו 3 Pydantic models: CompetitorInfo, AudienceProfile, MarketingStrategy
  3. צרו agent עם result_type=MarketingStrategy
  4. הגדירו 3 tools: search_competitors, analyze_audience, estimate_budget
  5. הריצו עם deps של חברה ישראלית (אמיתית או בדויה)
  6. Bonus: הריצו את אותו agent עם שני models שונים (OpenAI + Anthropic) והשוו תוצאות

Success criteria: Result is a valid MarketingStrategy object. Type checking passes. Tools receive correct deps.

עלות: ~$0.10

תרגיל 3 (מתקדם): Pydantic AI + MCP Integration 35 דקות

מטרה: חיבור Pydantic AI agent ל-MCP server חיצוני.

  1. התקינו MCP SDK: pip install mcp
  2. צרו Pydantic AI agent שמשתמש ב-MCP server כ-tool provider
  3. השתמשו ב-filesystem MCP server לקריאת קבצים מקומיים
  4. ה-agent צריך לקרוא קובץ, לנתח את התוכן, ולהחזיר structured output
  5. Bonus: הוסיפו dynamic system prompt שמתעדכן בהתאם ל-directory שנקרא

Success criteria: Agent reads files via MCP, analyzes content, returns typed result.

עלות: ~$0.05

מתחיל 20 דקות חינם

ADK vs Pydantic AI vs שאר ה-SDKs

בפרקים 5-10 כיסינו 6 SDKs. הנה ההשוואה המלאה בין Google ADK ו-Pydantic AI לשאר ה-SDKs שלמדנו:

קריטריון Google ADK Pydantic AI LangGraph CrewAI
פילוסופיה Multimodal + Google Cloud Type safety + Pythonic Maximum control (graphs) Simplicity (crews/teams)
שפות Python, TS, Java, Go Python בלבד Python, TS Python בלבד
Multi-model Gemini-optimized, model-agnostic כל provider (best) כל provider כל provider (via LiteLLM)
Multi-agent Workflow Agents (best predictability) Agent delegation Graph nodes (best flexibility) Crews (best simplicity)
Structured output Yes Pydantic models (best) Yes output_pydantic
Type safety Basic Full (best) — IDE + runtime TypedDict / Pydantic Limited
Durable execution Via Vertex AI Built-in Checkpointing (best) Limited
Multimodal Native (best) — text/image/video/audio Via model capabilities Via model capabilities Via model capabilities
Free tier Yes — generous (Gemini) SDK free; model costs vary SDK free; model costs vary 50 exec/mo on AMP
Deploy Vertex AI Agent Engine Any (self-deploy) LangGraph Platform CrewAI AMP
Observability Vertex AI monitoring Logfire (built-in) LangSmith AMP dashboard
Best for Multimodal, GCP, cost-sensitive Type-safe Python, model-agnostic Complex production workflows Fast multi-agent prototyping

Decision Matrix: איזה SDK לאיזה use case

Use Case Best Choice Runner Up למה
Image/video analysis agent Google ADK Claude SDK Gemini multimodal + ADK vision tools
Type-safe business logic agent Pydantic AI LangGraph Full type safety, IDE support, validation
Complex multi-step workflow LangGraph Google ADK Graph-based, checkpointing, human-in-loop
Quick multi-agent prototype CrewAI Google ADK Fastest path to working multi-agent team
Budget-sensitive high-volume Google ADK Pydantic AI + Gemini Flash-Lite: $0.10/$0.40 per 1M tokens
Model comparison / A-B testing Pydantic AI LangGraph Swap model in one line, same code
Israeli startup (lean team) Pydantic AI / ADK CrewAI ADK for GCP + free tier; Pydantic AI for type safety
Framework: ADK + Pydantic AI — Complementary Patterns

"The Two-Framework Strategy" — ADK ו-Pydantic AI לא מתחרים, הם משלימים:

שאלה ADK Pydantic AI
הסוכן צריך לראות תמונות? ADK ✓
צריך type safety מקסימלי? Pydantic AI ✓
צריך predictable pipeline? ADK Workflow Agents ✓
רוצים להחליף model בקלות? Pydantic AI ✓
כבר ב-Google Cloud? ADK ✓
צריך durable execution מובנה? via Vertex Pydantic AI ✓

Pattern מעשי: חברות רבות משתמשות ב-Pydantic AI כ-"agent engine" מרכזי (type safety, validation, structured output) ומחברות ADK agents ספציפית למשימות multimodal או Google Cloud integrations. זו לא בחירה בינארית.

הקשר ישראלי: בחירת SDK לסטארטאפ ישראלי

שוק ה-tech הישראלי מציב אתגרים ייחודיים בבחירת SDK. הנה שיקולים שרלוונטיים במיוחד לסטארטאפים ולחברות ישראליות:

ההמלצה למשווקים דיגיטליים בישראל: התחילו עם Pydantic AI כי ה-learning curve הקצרה ביותר וה-model agnostic design מאפשר ניסוי מהיר עם מודלים שונים. הוסיפו ADK כשאתם צריכים multimodal (ניתוח תמונות מוצרים, screenshots של מתחרים) או כשעלויות API הופכות למשמעותיות.

עשה עכשיו 10 דקות

השוו API surface: פתחו שני חלונות — בצד אחד את ה-ADK agent שבניתם, בצד שני את ה-Pydantic AI agent. שימו לב להבדלים: ADK = Runner + SessionService + async events. Pydantic AI = agent.run_sync() + typed result. מי יותר פשוט? מי נותן יותר שליטה? עכשיו קחו את ה-Pydantic AI agent, שנו את ה-model string ל-provider אחר (למשל "google-gla:gemini-2.5-flash"), והריצו שוב — הקוד לא משתנה בכלל. השוו תוצאות.

תרגיל 4 (מתקדם): Same Agent, Two Frameworks 45 דקות

מטרה: בניית אותו סוכן ב-ADK וב-Pydantic AI — ולהשוות.

  1. הגדירו use case: product review agent שמקבל שם מוצר, מחפש reviews, ומחזיר סיכום מובנה
  2. ADK version: LlmAgent עם Google Search tool, session state, SequentialAgent (search → analyze)
  3. Pydantic AI version: Agent עם result_type=ProductReview, tools עם RunContext, deps לAPI access
  4. הריצו שניהם על אותו מוצר
  5. השוו: איכות output, זמן ריצה, קלות development, type safety
  6. כתבו 3 משפטים: "ADK better for..., Pydantic AI better for..., No difference in..."

Success criteria: Both agents produce valid product reviews. Comparison document shows clear tradeoffs.

עלות: ~$0.20

מתחיל 10 דקות חינם

טעויות נפוצות — ואיך להימנע מהן

טעות 1: שכחת type hints ב-ADK tools

מה קורה: כותבים def get_data(query): בלי type hints.

למה זה בעיה: ADK משתמש ב-type hints כדי לייצר tool schema. בלי hints, ה-schema לא מדויק וה-LLM לא יודע מה לשלוח. למשל, בלי query: str — ה-LLM עלול לשלוח int, list, או None.

הפתרון: תמיד כתבו type hints מלאים: def get_data(query: str, max_results: int = 10) -> dict:. כתבו גם docstring עם Args section. ADK קורא את שניהם.

טעות 2: התעלמות מ-result_type ב-Pydantic AI

מה קורה: משתמשים ב-Pydantic AI בלי להגדיר result_type — ומקבלים string חופשי.

למה זה בעיה: כל היתרון של Pydantic AI הוא ה-type safety. בלי result_type, אתם מקבלים string שצריך לפרסר — בדיוק כמו כל SDK אחר. שיללתם את ה-feature המרכזי.

הפתרון: תמיד הגדירו result_type עם Pydantic model. גם אם התוצאה פשוטה — class SimpleResult(BaseModel): answer: str; confidence: float עדיף על string.

טעות 3: שימוש ב-Gemini Pro כשמספיק Flash

מה קורה: משתמשים ב-gemini-2.5-pro לכל agent.

למה זה בעיה: Pro עולה $1.25/$10.00 per 1M tokens. Flash עולה $0.30/$2.50, ו-Flash-Lite $0.10/$0.40. ב-80% מהמשימות, Flash מספיק — אתם משלמים פי 4-12 יותר מדי.

הפתרון: התחילו תמיד עם gemini-2.5-flash. עברו ל-Pro רק אם הפלט לא מספיק טוב. לtasks פשוטים (classification, extraction, routing) — flash-lite מספיק ב-$0.10 per 1M.

טעות 4: LoopAgent בלי max_iterations

מה קורה: LoopAgent בלי הגבלת iterations, הסוכן לעולם לא מרוצה מהתוצאה.

למה זה בעיה: ה-loop רץ שוב ושוב, כל iteration = LLM calls נוספים. ראינו מקרים של 20+ iterations שעלו $10+ על task אחד.

הפתרון: תמיד הגדירו max_iterations=3 (או 5 למקסימום). ודאו שה-reviewer agent יודע לקרוא ל-escalate כשהאיכות מספקת.

טעות 5: deps חשופים ב-Pydantic AI

מה קורה: שמים API keys ישירות ב-dependencies בלי הגנה.

למה זה בעיה: dependencies עוברים ל-tools, אבל ה-type system לא מגן מפני logging לא מכוון. אם tool עושה print(ctx.deps) או logging — ה-API key נחשף בlogs.

הפתרון: עטפו API keys ב-SecretStr של Pydantic: api_key: SecretStr. כך הם לא נחשפים ב-repr, logging, או serialization. תמיד.

שגרת עבודה — פרק 10
תדירותמשימהזמן
יומיבדקו agent runs — הצלחות, כשלונות, latency5 דק'
יומיבדקו API costs — Gemini usage, per-model breakdown5 דק'
שבועיReview של tool docstrings — שפרו על בסיס tool-calling errors10 דק'
שבועיבדקו SDK versions: pip install --upgrade google-adk pydantic-ai5 דק'
חודשיModel benchmark — האם Flash-Lite מספיק? האם Pro שווה את ההפרש?20 דק'
חודשיType coverage audit — כל tool עם type hints? כל agent עם result_type?15 דק'
אם אתם עושים רק דבר אחד מהפרק הזה 15 דקות

בנו Pydantic AI agent עם result_type שמחזיר Pydantic model. הריצו אותו, קבלו typed result, ושחקו עם autocomplete ב-IDE. ברגע שתרגישו את ה-type safety — שהתוצאה היא Python object עם שדות ידועים, לא string שצריך לפרסר — תבינו למה Pydantic AI משנה את הדרך שאנחנו בונים agents. וזה לוקח 10 שורות קוד.

עשה עכשיו 5 דקות

הפעילו ADK Web UI: ארגנו את ה-ADK agent בתיקייה עם __init__.py ו-agent.py שמייצא root_agent. הריצו adk web my_agent ופתחו בדפדפן. שלחו כמה הודעות וראו את ה-trace viewer — כל tool call, כל LLM response, כל state change מוצגים. זה ה-debugging experience שכל SDK צריך.

בדוק את עצמך — 5 שאלות
  1. מהם שלושת סוגי ה-Workflow Agents ב-ADK ומתי משתמשים בכל אחד? (רמז: Sequential, Parallel, Loop)
  2. מה ההבדל בין Google Search grounding ב-AI Studio לבין Vertex AI מבחינת עלות? (רמז: חינם vs $35/1K)
  3. הסבירו את result_type ב-Pydantic AI — מה קורה כשה-LLM מחזיר תוצאה שלא עוברת validation? (רמז: auto-retry)
  4. מה התפקיד של RunContext ב-Pydantic AI ואיך הוא מיישם dependency injection? (רמז: ctx.deps, type parameter, invisible to LLM)
  5. תנו 2 use cases שבהם ADK עדיף ו-2 שבהם Pydantic AI עדיף. (רמז: multimodal vs type safety, GCP vs model-agnostic)

עברתם 4 מתוך 5? מצוין — אתם מוכנים לפרק 11.

סיכום הפרק

בפרק הזה למדתם שני frameworks שמשלימים את ה-SDK landscape: Google ADK — ה-framework הרשמי של Google לבניית סוכני Gemini עם multimodal capabilities, workflow agents (Sequential, Parallel, Loop), Google Search grounding, ו-free tier נדיב; ו-Pydantic AI — framework ל-type-safe Python agents עם structured output, dependency injection, ו-model-agnostic design.

הנקודה המרכזית: ADK הוא הבחירה הנכונה כשצריכים multimodal, Google Cloud integration, או עלויות נמוכות. Pydantic AI הוא הבחירה הנכונה כשרוצים type safety מקסימלי, model flexibility, ו-Pythonic API. הם לא מתחרים — אפשר (וכדאי) להשתמש בשניהם בפרויקטים שונים.

בפרק הבא (פרק 11) תכירו את AutoGen, Mastra, ו-Emerging Frameworks — שאר הנוף שצריך להכיר: Microsoft Agent Framework, AG2, Mastra, ו-Smolagents. אחרי פרק 11 תהיה לכם תמונה מלאה של כל ה-SDKs בשוק.

צ'קליסט — סיכום פרק 10