1. מבוא

בשיעור Codelab הזה נסביר איך ליצור מערכות מתקדמות של סוכנים באמצעות תהליכי עבודה וגרפים בערכה לפיתוח סוכנים (ADK). תטמיעו דפוסי ארכיטקטורה נפוצים, תתזמנו אינטראקציות של אדם בתהליך (HITL) ותטפלו בהרצה אסינכרונית ארוכה. בנוסף, תלמדו איך לשלב בסיסי ידע ארגוניים וזיכרון מתמשך כדי להתאים אישית את התנהגות הנציג ולשפר אותה. לבסוף, תשתמשו ביכולות האלה כדי להפעיל צינור אוטומטי ליצירת סרטונים.
התרחיש
אתם מפעילים ערוץ דיגיטלי ב-VibeTube עם קהל פעיל ורשימה הולכת וגדלה של רעיונות קריאייטיביים. כדי ליצור כל סרטון, צריך לבצע פעולות רציפות בכמה שלבים: מחקר של פורמטים פופולריים, סיכום של משוב הצופים, פיתוח תסריטים, בדיקה של עמידה בדרישות המדיניות ויצירה של קליפים. מודלים גנרטיביים יכולים ליצור נכסים בודדים, אבל כדי לספק גרסאות עקביות צריך ארכיטקטורת סוכנים מתואמת.
כדי להפוך את מחזור החיים הזה לאוטומטי, תבנו את VibeStudio. צינור העיבוד הזה מבצע מחקר שגרתי במקביל, מציג אפשרויות שנבחרו בקפידה לאישור על ידי אדם, מיישם שערים אוטומטיים של מדיניות לפני יצירת הסרטון ושומר על ההקשר לאורך כל תהליך הייצור.

מה לומדים

- הבסיס להנדסת גרפים: ארכיטקטורות של סוכנים מרובי-שלבים דורשות זרימת בקרה מפורשת ונתיבי ביצוע מובנים. אתם יוצרים ADK
Workflowבאמצעות טופלים של קצה, נקודת הכניסהSTART, JoinNodeלצבירה מקבילית של fan-out, וצמתי נתב דטרמיניסטיים כדי לנהל את הביצוע על סמך מצב. - מצבי סוכן וקריאות חוזרות (callback) של מחזור החיים: משימות מיוחדות דורשות התנהגויות תפעוליות שונות וגבולות גזרה דטרמיניסטיים. מגדירים מופעי ADK
Agentבאמצעות מצביchat,single_turnו-taskשמופעלים על ידי כלי כצמתים של תהליך עבודה, ומחילים מיירטים באמצעותbefore_model_callbackו-after_agent_callback. - תיזמור של אדם בתהליך: צינורות עיבוד נתונים מושהים בנקודות ביקורת יצירתיות קריטיות כדי לאפשר שיקול דעת אנושי. אתם מטמיעים את
RequestInputכדי להשהות את הביצוע של תהליך העבודה, לאכוף סכימות של תגובות מובנות ולחדש את הביצוע בלי להשאיר תהליכי זמן ריצה במצב המתנה. - זיכרון היררכי של סוכנים: מערכות ייצור מפרידות בין מצב ביצוע זמני לבין הקשר עמיד. אתם מנהלים את מצב הסשן לטווח קצר באמצעות
Event(state=...)וקישור פרמטרים, ומחברים את Memory Bank של GEAP כדי לחלץ, לאחד ולשמור את העדפות היוצרים בין הפעלות. - התבססות על בסיסי ידע ארגוניים: סוכנים אוטונומיים צריכים הקשר דינמי של הדומיין וסנטימנט הקהל. אתם מחברים קורפוס של GEAP RAG Engine כצומת אחזור ייעודי ב-fan-out המקבילי כדי לעגן סמנטית את הפלטים של הסוכן.
- תהליכי עבודה ופריסה ממושכים: עיבוד וידאו מולטימודאלי פועל באופן אסינכרוני לאורך פרקי זמן ממושכים. מטמיעים את
LongRunningFunctionToolעם אישורי שיחה בהמתנה כדי להשהות את תהליך העבודה ולחדש אותו לפי מזהה השיחה, ופורסים את צינור עיבוד הנתונים שהושלם באמצעות ADKRunnerב-Cloud Run.
איך ה-Codelab הזה מאורגן
ה-Codelab הזה משמש כהפניה למושגים ולארכיטקטורה. בכל חלק מוסבר על מבני ה-ADK שהוטמעו בשלב המתאים בכלי, מוצג קוד לדוגמה ומוצגים עקרונות עיצוב מרכזיים. חשוב לעיין בכל קטע לפני שמבצעים את התרגיל המתאים בסביבת העבודה.
העבודה המעשית מתבצעת בסביבת העבודה של VibeStudio, ממשק אינטרנטי נלווה שכולל עורך קוד אינטראקטיבי, כלי אימות בזמן ריצה וכלי מוטמע לבדיקת ADK. מספרי השלבים בסביבת העבודה תואמים ישירות למספרי השלבים ב-codelab הזה, כדי שההתקדמות שלכם תהיה מסונכרנת. עריכות בגרף הבסיסי נשמרות בין השלבים, והסביבת העבודה מאמתת באופן אוטומטי את הדרישות המוקדמות כשמתקדמים.
בסיום התרגילים בסביבת העבודה, תרכיבו צינור (pipeline) של סוכן מקצה לקצה ותפרוסו אפליקציית VibeStudio פעילה ב-Cloud Run כדי ליצור תוכן וידאו.
הסביבה מורכבת משלושה רכיבים עיקריים: VibeStudio Workbench (ממשק האינטרנט המקומי לעריכת קוד ולאימות בזמן ריצה), הקצה העורפי (ADK Workflow וארגזי חול של שלבים ב-agent/) ו-Google Cloud (מודלים של Gemini, GEAP Memory Bank, RAG Engine ויצירת סרטונים ב-Veo).
2. הגדרה
מימוש שוברי הפרסום לסדנאות
אם אתם משתתפים בשיעור Lab בהנחיית מדריך, המדריך יקצה קרדיטים לפרויקט שלכם ב-Google Cloud. פועלים לפי ההוראות של המדריך כדי לממש את הקרדיטים ולוודא שהחיוב פעיל בחשבון לפני שממשיכים.
פתיחת Cloud Shell
Cloud Shell היא סביבת פיתוח מבוססת-דפדפן עם gcloud, Python ו-git שמותקנים מראש.
כדי להפעיל את Cloud Shell:
- נכנסים למסוף Google Cloud.
- בכותרת הניווט העליונה, לוחצים על Activate Cloud Shell (הסמל של חלון הטרמינל).

סשן טרמינל ייפתח בחלק התחתון של חלון הדפדפן.
שכפול המאגר והפעלתו
כדי לשכפל את הפרויקט, מריצים את הפקודות הבאות במסוף Cloud Shell:
git clone https://github.com/gca-americas/vibetube-studio cd ~/vibetube-studio
הנחיות להגדרה
במהלך ההגדרה תתבקשו לספק את הפרטים הבאים:
- מזהה פרויקט בענן ב-Google Cloud: כשמוצגת בקשה מ-
setup_project.sh, מקישים על Enter כדי ליצור פרויקט חדש באופן אוטומטי. אם אתם מעדיפים להשתמש בפרויקט קיים (למשל פרויקט שהוקצה מראש), מזינים את מזהה הפרויקט ומוודאים שהאיות נכון ושהחיוב פעיל. - קוד האירוע: מזינים את קוד החדר שקיבלתם מהמורה. אם לא קיבלתם כרטיס, כדאי לבדוק עם עוזר הוראה או עם שכן. אם אתם משלימים את שיעור ה-Lab הזה בבית, מקישים על Enter כדי לאשר את החדר
sandboxשמוגדר כברירת מחדל. - השם המוצג של הערוץ: מזינים את השם או את הכינוי המועדף לערוץ כשמופיעה ההנחיה ב-
setup_codelab.sh, או לוחצים על Enter כדי לאשר את ברירת המחדל שנוצרה מחשבון Google.
מריצים את שני סקריפטי ההגדרה לפי הסדר:
./setup_project.sh ./setup_codelab.sh
-
setup_project.sh: יוצר או משתמש מחדש בפרויקט בענן של Google עם חיוב פעיל, שומר את מזהה הפרויקט ב-~/project_id.txtומגדיר את ההקשר הפעילgcloud. -
setup_codelab.sh: מתקין אתuvואת יחסי התלות של Python ב-.venv, מפעיל את Cloud APIs הנדרשים של Google Cloud, מגדיר את הגדרות הערוץ ב-.env, מאמת את הגישה למודל באמצעות Gemini, מקצה משאבים של Memory Bank ו-RAG, בונה את ממשק סביבת העבודה ומפעיל את VibeStudio Workbench.
הסקריפט מריץ את בדיקת הטרום-הפעלה ומתחיל את VibeStudio Workbench ברקע. בשורה האחרונה מוצג הקישור לפתיחה.
7 · Preflight
✓ python 3.12
✓ auth path A: Vertex via ADC (STUDIO_VERTEX=1)
✓ Google Cloud ADC (project <your-project>)
✓ stage0_prompt loads
...
✓ stage6_video loads (13 edges)
✓ aiplatform.googleapis.com enabled (Gemini, Veo, Memory Bank, RAG Engine)
✓ vectorsearch.googleapis.com enabled (the vector store a RAG corpus is built on)
✓ Memory Bank connected
✓ RAG corpus connected
✓ VibeStudio Workbench running on port 4600
PREFLIGHT GREEN
Setup finished. The VibeStudio Workbench is already running.
Open this and start at step 1
https://4600-<your cloud shell host>/step/story
It runs in the background. You do not need to start anything else.
log runs/lab.log
stop kill $(cat runs/lab.pid)
start scripts/start.sh
לוחצים על הקישור. אותה כתובת זמינה גם בקטע תצוגה מקדימה באינטרנט → שינוי יציאה → 4600.
כדי לבדוק מחדש את הסביבה בכל שלב, מריצים את הפקודה python scripts/preflight.py. כדי להפעיל מחדש את סביבת העבודה, מריצים את הפקודה scripts/restart.sh. כדי להגדיר שוב, מריצים את ./setup_codelab.sh. ההגדרות וההתקדמות יישמרו.
אחרי שפותחים את הקובץ, קוראים את שלב 1, הסיפור כדי להבין את התרחיש, ואת שלב 2, מה יוצרים כדי להבין את הצורה של הגרף הסופי. לאף אחד מהם אין תרגיל. ואז חוזרים לכאן כדי לבצע את שלב 3.

כל חלק מעשי ב-VibeStudio Workbench מסתיים בחלונית אימות שקוראת את הארטיפקטים האמיתיים: הקובץ בדיסק והסשנים שנכתבו על ידי ההרצות.
פריסת מאגר
מאגר המידע מחולק ללוגיקה של תהליך העבודה המרכזי, לארגזי חול שלב אחר שלב, לסביבת סדנת העבודה ולאפליקציית הייצור:
vibe-studio-lab/
├── agent/ # Core ADK workflow, graph definition, and platform services
│ ├── graph.py # Workflow graph definition, node functions, and routers
│ ├── desk.py # Video render desk using LongRunningFunctionTool
│ ├── schemas.py # Pydantic schemas for directions, gates, and scripts
│ ├── trends.py # Trend generation and sampling utilities
│ ├── backlog.txt # Creator video ideas backlog
│ ├── comments.md # Audience comments for RAG Engine corpus seeding
│ ├── policy_words.txt # Blocked subject words for deterministic policy checks
│ └── platform/ # Google Cloud service clients (Memory Bank, RAG, Veo)
│ ├── config.py # Environment variables, locations, and model configurations
│ ├── memory.py # GEAP Memory Bank callbacks and context injection
│ ├── rag.py # GEAP RAG Engine corpus creation and semantic retrieval
│ └── videogen.py # Veo video generation and operation polling
├── stage0_prompt/ # Step sandboxes: isolated agent.py files runnable in adk web
│ └── ... # stage1_fanout through stage6_video for incremental steps
├── server/ & web/ # VibeStudio Workbench (FastAPI backend and React frontend)
├── vibestudio/ # Complete production application deployed to Cloud Run
│ ├── server/ # FastAPI production server and event runner
│ ├── web/ # End-user React web application
-
agent/: מכיל את הגרף המרכזי של תהליך העבודה. תערכו קבצים בספרייה הזו כדי להטמיע צמתים מקבילים של fan-out, ניתוב מדיניות דטרמיניסטי, קריאות חוזרות לזיכרון וכלי ליצירת סרטונים. -
agent/platform/: ממשקי משתמש עם שירותי Google Cloud, כולל מודלים של Gemini, GEAP Memory Bank, GEAP RAG Engine וסינתזת וידאו של Veo. -
stage0_prompt/עדstage6_video/: סביבות ארגז חול עצמאיות. כל תיקייה מייצאתroot_agentעצמאי, כך שאפשר להריץ ולבדוק כל שלב בנפרד באמצעות ממשק הפיתוח המוטמע של ADK. -
server/ו-web/: אפליקציית VibeStudio Workbench שפועלת באופן מקומי ביציאה 4600. הוא כולל את התיעוד של השלב, עורך קוד שמוטמע בדף, מאמתים של ראיות בזמן ריצה ותצוגה חזותית של הגרף. -
vibestudio/: האפליקציה המלאה לייצור, שנארזת ונפרסת ב-Cloud Run בשלב האחרון. הוא מכיל עותק עצמאי משלו של תרשים זרימת העבודה שהושלם.
3. סוכן מונוליתי
לפני שיוצרים גרף של תהליך עבודה עם כמה צמתים, צריך ליצור בסיס לארכיטקטורה עם סוכן יחיד ב-stage0_prompt/agent.py. הסוכן הזה מסתמך על הנחיית מערכת מונוליטית שמתארת את צינור הייצור בפרוזה, והוא נתמך על ידי שני כלי פונקציות של Python.
הערכה של נקודת הבסיס הזו מדגימה את הגבולות התפעוליים של תיאום מבוסס-הנחיות, ומסבירה למה מערכות ייצור דורשות תזמור גרפים.
ארכיטקטורה של סוכן ADK (3A)
ב-VibeStudio Workbench, עוברים אל Step 3 · Monolithic agent ופותחים את ADK agent architecture (3A). בתצוגה הזו מוצגות שכבות הליבה של סוכן ADK (LlmAgent):

from google.adk.agents import LlmAgent
from google.adk.tools import mcp_toolset
root_agent = LlmAgent(
model="gemini-3.5-flash", # model
instruction=BRAND_INSTRUCTION, # instruction
skills=[load_skill("brand-audit")], # skills
tools=[mcp_toolset("mcp_brand_style")], # tools
output_schema=BrandStyleReport, # structured output
before_agent_callback=setup_ctx, # interceptor
before_model_callback=require_image, # interceptor
after_model_callback=schema_guard, # interceptor
)
בתרשים האינטראקטיבי, רכיבי הסוכן מחולקים לחמישה תחומים תפעוליים:
- שכבת ההסקה (מודל): מודל השפה הבסיסי (כמו Gemini 3 Flash) שמבצע משימות קוגניטיביות, חשיבה רציונלית של פרומפטים ובחירה של כלים. כל שאר הרכיבים בארכיטקטורה מספקים מידע למודל הזה או מגבילים אותו.
- שכבת ההקשר (הוראות ומיומנויות): הנחיות שמעצבות את ההיגיון של המודל.
instructionמגדיר את ההנחיה הקבועה למערכת, את הדמות ואת כללי התפעול.skillsמספקת הנחיות מפורטות עם מספור גרסאות (SKILL.md) לתהליכי עבודה שניתן לחזור עליהם. - שכבת שיתוף הפעולה והפעולה (כלים, סוכני משנה, תהליך עבודה, סכימת פלט): ממשקים שמאפשרים לסוכן לפעול במערכות חיצוניות ולפלוט נתונים מוקלדים.
toolsלספק פונקציות Python שניתן להפעיל או נקודות קצה של Model Context Protocol (MCP).subagentsלבצע משימות שהוקצו לבעלי הרשאה משנית.workflowקואורדינטות של גרפים של כמה סוכנים. output_schemaמשתמש במודלים של Pydantic כדי להבטיח שצרכנים במורד הזרם יקבלו JSON מאומת במקום טקסט לא מובנה. - שכבת חסימה (Lifecycle Callbacks): אמצעי הגנה דטרמיניסטיים שמבצעים קוד מותאם אישית לפני ואחרי הפעלה של סוכן (
before_agent/after_agent), תורות של מודלים ספציפיים (before_model/after_model) וקריאות לכלים (before_tool/after_tool). אמצעי החסימה אוכפים כללי מדיניות בלי להסתמך על התאמה של המודל. - מצב חיצוני (סשן וזיכרון): שמירה של מצב נפרד מהלוגיקה של הסוכן.
Sessionשומר את הזיכרון הזמני של המשימה ואת נתוני המעקב אחר האירועים של השרשור הנוכחי. Memoryשומר על עובדות והעדפות עמידות בין סשנים באמצעות שירותים מנוהלים כמו GEAP Memory Bank.
הסוכן המונוליטי בשלב הזה מיישם רק שלושה מהפרימיטיבים האלה: model, instruction ו-tools. בשלבים הבאים נסביר על תהליכי עבודה של גרפים, סכימות מובנות, interceptors ושירותי זיכרון קבוע.
מפרט של סוכן מונוליטי (3B)
בסביבת העבודה, עוברים אל Monolithic agent specification (3B). פותחים את stage0_prompt/agent.py כדי לבדוק את ההגדרה של הסוכן הראשוני:
- הנחיה אחת: הנחיית המערכת מתמצתת חמש משימות הפקה שונות לטקסט רציף: גילוי מגמות בפלטפורמה, בדיקת רעיונות לתוכן, הצעת קונספטים יצירתיים, אכיפת מדיניות בנושאים אסורים וטיוטת רשימת שוטים.
- מקורות נתונים בסיסיים: הסוכן מתייחס לשני מקורות שמוגדרים לצד הגרף:
-
agent/trends.py: המערכת בוחרת מדגם של עשר מגמות פעילות של פורמטים וסגנונות מתוך מאגר של 250 מגמות עם ציוני חום דינמיים. -
agent/backlog.txt: קורא את הערות הרעיון הגולמיות של היוצר שורה אחר שורה.
-
כלים בסוכן (3C)
בסביבת העבודה, עוברים אל Tools in Agent (3C) (כלים בסוכן (3C)).
מה זה כלי לסוכן?
מודל שפה הוא מנוע הסקה בעולם סגור: הוא פועל רק על משקלים שאומנו מראש ועל הטוקנים שמופיעים בחלון ההקשר המיידי שלו. הוא לא יכול לשלוח שאילתות למסד נתונים, לגשת לממשקי API בזמן אמת או להריץ קוד באופן מקורי.
כלי יכול לגשר על הפער הזה. היא מעניקה למודל סוכנות חיצונית, ומאפשרת לו לאחזר מידע מהשטח ולבצע פעולות דטרמיניסטיות במערכות חיצוניות.

הפעלת כלים מתבצעת לפי פרוטוקול מפורש בן חמישה שלבים בין המודל לבין זמן הריצה של ADK:
- הצהרת סכימה: המפתח מספק פונקציות Python לסוכן. ה-ADK בודק את השם, הערות הסוג והמחרוזות של כל פונקציה כדי ליצור הצהרת סכימת JSON שתואמת ל-OpenAPI ומתארת את הפרמטרים והמטרה שלה.
- חשיבה רציונלית של המודל: במהלך היקש, המודל מעריך אם הפרומפט של המשתמש דורש נתונים חיצוניים. במקרה הצורך, המודל פולט אירוע מובנה
function_callשמכיל את שם פונקציית היעד ומילון הארגומנטים שתואם לסכימה. - הרצת זמן ריצה: המודל עצמו לא מריץ קוד. זמן הריצה של ADK מיירט את
function_call, מפעיל את פונקציית ה-Python המקומית בפועל באמצעות הארגומנטים שסופקו ומתעד את הערך המוחזר. - החדרה מחדש של ההקשר: חבילות ה-ADK בזמן הריצה אורזות את הערך שמוחזר מהפונקציה לאירוע
function_responseומצרפות אותו להיסטוריית הסשן הפעיל. - סינתזה סופית: המודל מעבד את הפלט של הכלי שמופיע עכשיו בחלון ההקשר שלו ומשלים את התשובה.
ב-stage0_prompt/agent.py, שני כלי המחקר מוגדרים כפונקציות Python רגילות:
def check_trends() -> dict:
"""Ten formats trending on the platform right now, with a heat score each."""
from agent.trends import sample_trends
return {"trends": sample_trends()}
def read_backlog() -> dict:
"""The creator's backlog: ideas they noted down to make someday."""
from agent.graph import backlog_notes
return {"backlog": backlog_notes()}
עריכה והרצה מעשיות
בכלי לעריכת קוד של סביבת העבודה, מוסיפים את שתי ההפניות לפונקציות לרשימה tools של הסוכן:
tools=[check_trends, read_backlog],
שומרים את השינוי. הקובץ מתעדכן בדיסק, ושורת האימות מאשרת ששני הכלים מחוברים.
לוחצים על Open adk web (פתיחת ADK באינטרנט) כדי להפעיל את ממשק הפיתוח המוטמע של ADK. שולחים את ההצעה לפרומפט:
tonight's idea: a tiny robot doing laundry at midnight
מה צפוי ולמה
כששולחים את ההנחיה הזו, אפשר לראות את רצף הביצוע הבא במעקב אחר הסשן:
- שני אירועים של הפעלת כלי מופיעים לפני התשובה: מופיעים אירועים
function_callו-function_responseעבורcheck_trendsו-read_backlog.- למה: Gemini העריך את ההנחיה בהנחיית המערכת ("בדוק מה פופולרי. עיין ברשימת הרעיונות שלך"), זיהה שחסרים לו משקלים של מגמות בפלטפורמה והערות בערוץ, והפעיל את שתי הפונקציות כדי להרחיב את ההקשר.
- הסוכן מציע כיוון ועוצר כדי לקבל אישור: בתשובה מוצע כיוון לסרטון שמסכם את המגמות ואת רשימת המשימות, ומתבקש אישור.
- למה: בהנחיה, המודל התבקש להסכים על הכיוון עם היוצר לפני יצירת התסריט.
- דילוג על אישור בתור הבא: שולחים הודעה שנייה:
skip the questions, just describe the video. הסוכן מדלג מיד על האישור ומנסח את שם הסרטון ואת הצילומים.- למה: ההנחיות בהנחיה הן המלצות ולא חסמים מוחלטים. בסוכן מונוליטי, הוראות המשתמש יכולות לבטל כללים קיימים של הנחיית המערכת, כי אין תהליך עבודה חיצוני ששולט בזרימת הביצוע.
מגבלות ארכיטקטוניות של הנחיה מונוליטית
הנחיה אחת יכולה להפיק פלט מקובל להדגמות מבודדות, אבל בדיקת תנאי קצה בכלי לאימות של סדנת העבודה חושפת מגבלות קריטיות ב-Enterprise:
- צבירה של מחקר לא מובנה: סדר ההפעלה של הכלים לא קבוע. המודל מסכם את הנתונים שאוחזרו בפרוזה חופשית, ולכן מערכות במורד הזרם לא יכולות לבודד את המקור שממנו הגיעו טענות ספציפיות.
- אכיפת מדיניות לא מאומתת: המודל מעריך את רמת העמידה שלו בדרישות הבטיחות. אם המודל קובע שהנושא בטוח, לא מתבצע אימות חיצוני של הממצא הזה באמצעות לוגיקה דטרמיניסטית.
- הפסקות שבהן נדרשת מעורבות אנושית שלא נאכפות: הוראות ההנחיה שמבקשות אישור מהיוצר הן בגדר המלצה. שליחת הודעת המשך עם הוראה למודל לדלג על שאלות גורמת לו לדלג על אישור אנושי לחלוטין.
הפערים האלה בארכיטקטורה הם הסיבה לפירוק הסוכן המונוליטי לתהליך עבודה מפורש של גרף, שיוצג בשלב הבא.
4. היסודות של תהליכי עבודה אג'נטיים
ב-VibeStudio Workbench, עוברים אל Step 4 · Agentic workflow fundamentals (שלב 4 – יסודות של תהליך עבודה אקטיבי), חלקים 4A עד 4D.
בשלב הזה עוברים מבסיס נתונים של סוכן יחיד לתיאום גרפים דטרמיניסטי באמצעות ADK Workflow. תבנו fan-out של מחקר מקביל, תסנכרנו ענפים עם צומת איחוד, תיצרו מועמדים לנכסי קריאייטיב שעברו אימות סכמה ותציגו שער אישור דטרמיניסטי של האדם שבתהליך.
ארכיטקטורת גרף ושרשראות ביצוע (4A)
בסביבת העבודה, פותחים את Graph architecture and execution chains (4A).
ב-ADK Workflow, הרצת הסוכן בנויה כגרף מכוון שמוגדר על ידי רשימת קשתות:
- שרשראות: טפלים עוקבים מגדירים ביצוע לינארי של צמתים (
(node_a, node_b, node_c)). - ענפים מקבילים: שרשראות עצמאיות שחולקות צומת מקור מופעלות במקביל.
- סנכרון: שרשרות שמתכנסות בנקודת
JoinNodeממתינות עד שכל הענפים הנכנסים מדווחים לפני שהן משתחררות. - שליטה דטרמיניסטית: זרימת הביצוע נשלטת על ידי מבני קוד מוצהרים, במקום להסיק אותה מטקסט ההנחיה.

סוגי צמתים ב-ADK
תהליכי העבודה ב-ADK מורכבים מכמה סוגים של צמתים מיוחדים. כל ארכיטיפ ממלא תפקיד תפעולי ספציפי בתרשים, ומפריד בין הרצת קוד דטרמיניסטי לבין חשיבה רציונלית של מודל גנרטיבי:
אב-טיפוס של צומת | הטמעה | תפקיד בפייפליין |
צומת פונקציה | פונקציית Python שמחזירה | מבצע לוגיקה דטרמיניסטית, אחזור נתונים ושינויים במצב. |
צומת של הצטרפות | מופע מובנה של | מסנכרנת ענפים מקבילים למילון מצטבר. |
צומת של סוכן | | הוא בודק את ההוראות ביחס לקלט במעלה הזרם ומפיק נתונים מאומתים. |
צומת נתב | פונקציה שמחזירה | הצומת מעריך לוגיקה מותנית כדי לבחור ענפי ביצוע במורד הזרם. |
צומת קלט אנושי | פונקציה שמחזירה ערך | הפעולה מושהית עד שתגיע תגובה ממשתמש חיצוני. |
root_agent = Workflow(
name="stage1_fanout",
description="2 real readers -> join -> one research dict",
edges=[...])
במקרה הזה, root_agent הוא מופע של Workflow ולא Agent עצמאי. ב-ADK, תהליכי עבודה נחשבים לסוכנים ברמה גבוהה, ולכן אפשר לטעון, להציג ולבדוק גרף שלם כאפליקציה מאוחדת. name רושם את האפליקציה ב-ADK Web, ואילו רשימת edges מגדירה את טופולוגיית הביצוע שלה.
הסתעפות מחקר מקבילית (4B)
ב-Workbench, עוברים אל Parallel research fan-out (4B). פותחים את stage1_fanout/agent.py.

צמתים של פונקציות ומחסומי סנכרון
בשלב המחקר נעשה שימוש בשני צמתי פונקציות שיובאו מ-agent/graph.py:
-
scan_trends: מחזירה אתEvent(output={"trends": [...]})שמכיל עשר מגמות בפלטפורמה עם ניקוד. -
read_backlog: מחזירהEvent(output={"backlog": [...], "idea": "..."})שמכילה חמישה עשר רעיונות לתוכן בערוץ, לצד ההנחיה הראשונית.
כל פונקציה מקבלת node_input (הפלט של הצומת הקודם) ומחזירה Event.
צומת JoinNode משמש כמחסום סנכרון: הוא מושהה עד שכל שרשרת נכנסת מעבירה אירוע, ואז הוא מצבר את כל התוצאות של הענפים למילון עם מפתחות לפי שם הצומת ({"scan_trends": {...}, "read_backlog": {...}}).
עריכה מעשית: הגדרת הצומת והקצוות המקבילים
ב-stage1_fanout/agent.py, יוצרים מופע של JoinNode ומקשרים את שני השרשורים המקבילים שמתחילים ב-START:
join_research = JoinNode(name="join_research")
edges=[(START, scan_trends, join_research),
(START, read_backlog, join_research)])
שומרים את השינויים. המאמת של סביבת העבודה מוודא שהצמתים והקצוות מחוברים. מריצים את השלב באמצעות Run Stage 1 (הרצת שלב 1) או דרך ממשק האינטרנט המוטמע של ADK.
מה צפוי ולמה
- הפעלה בו-זמנית של קוראים: בתרשים ההפעלה, הצמתים
scan_trendsו-read_backlogמופעלים בו-זמנית.- למה: שתי השרשראות מתחילות ב-
START. מנוע ה-ADK מתזמן ענפים עצמאיים במקביל.
- למה: שתי השרשראות מתחילות ב-
- פלט מילון מצטבר: תהליך העבודה מסתיים ב-
join_research, ומופק מילון עם ערכים לשני הקוראים.- למה: הצומת
JoinNodeמבטיח שכל הנתונים יתועדו לפני שמאפשרים לצמתים הבאים לפעול.
- למה: הצומת
צמתים של סוכנים (4C)
ב-Workbench, עוברים אל Agent nodes (4C) (צמתי סוכן (4C)). פותחים את stage2_direction/agent.py.

מצבי הפעלה וסכימות מובנות
כשמטמיעים Agent בתוך Workflow, הוא פועל במצב single_turn כברירת מחדל:
- הוא מקבל את הפלט של הצומת הקודם כקלט ההקשר שלו.
- היא מבצעת שיחת הסקה אחת ללא שיחה הלוך ושוב.
- הוא יוצר נתונים מובְנים ומעביר אותם לצומת הבא.
ההקצאה של output_schema=Directions גורמת לסוכן לאכוף אימות Pydantic על פלט המודל. התרשים במורד הזרם מקבל אובייקטים מוקלדים במקום פרוזה לא מובנית:
class Direction(BaseModel):
title: str # <=60 chars, filmable, characterful
angle: str # the twist, one line
hook: str = "" # 2-4 words, the video's sticker line
evidence: list[Evidence]
class Directions(BaseModel):
candidates: list[Direction] # exactly 4
PROPOSE_INSTRUCTION מכוון את המודל להציע ארבעה מועמדים תוך ציטוט ראיות גם מהמגמות וגם מהמשימות שנותרו לביצוע. המועמדים 1 עד 3 מציעים רעיונות טובים לערוצים. מועמד 4 מכניס בכוונה מושג שמפר את המדיניות כדי לבדוק את שער הבטיחות בשלב הבא.
עריכה מעשית: הגדרת צומת הסוכן ושרשור ההצטרפות
ב-stage2_direction/agent.py, מגדירים את propose_directions ומרחיבים את קצוות תהליך העבודה:
propose_directions = Agent(
name="propose_directions",
model=config.MODEL,
instruction=PROPOSE_INSTRUCTION,
output_schema=Directions)
edges=[(START, scan_trends, join_research),
(START, read_backlog, join_research),
(join_research, propose_directions, direction_gate)])
מה צפוי ולמה
- צריכה ישירה של מילון:
propose_directionsצורך את מטען ה-JSON הייעודי שמופק על ידיjoin_researchללא עיצוב ידני. - פלט מועמד עם סוג: הסוכן פולט אובייקט מאומת
Directionsשמכיל ארבעה מועמדים נפרדים. צמתים במורד הזרם קוראים שדות לפי שם המאפיין (candidate.title) בלי ניתוח מחרוזות.
האדם שבתהליך (4D)
ב-Workbench, עוברים אל Human-in-the-loop (האדם שבתהליך) (4D). פותחים את agent/graph.py.

הוראות בפרומפט לעומת השעיה דטרמיניסטית
תהליכי עבודה של הפקה שכוללים עלויות כספיות או פרסום תוכן דורשים פיקוח אנושי בנקודות קריטיות של קבלת החלטות. בפרומפט יחיד, בקשות אישור הן הוראות מייעצות שמשתמש יכול בקלות להנחות את המודל לעקוף. בתהליך עבודה של ADK, מנוע ההפעלה אוכף אישור אנושי: הגרף נעצר בצומת ייעודי ולא יכול להתקדם עד שהוא מקבל קלט חיצוני שתוקף לפי הסכימה:
- הפקודה Yielding
RequestInputמשעה את הביצוע של תהליך העבודה באופן מיידי. - ה-ADK מתעד קריאה פתוחה להפרעה בחנות הסשנים ומנפיק
interrupt_idייחודי. - תהליך ההפעלה נעצר בלי לצרוך אסימונים או שרשורים של השרת.
- הביצוע של הגרף יתחדש רק כשיישלח ערך תקין של
function_responseשתואם לסכימה ולמזהה ההפרעה.
עריכה מעשית: השהיית הביצוע באמצעות RequestInput
ב-agent/graph.py, מטמיעים את קריאת ההשעיה בתוך direction_gate:
yield RequestInput(
message="Pick tonight's direction: 1, 2, 3 or 4.",
response_schema={
"type": "object",
"properties": {
"pick": {"type": "string", "enum": ["1", "2", "3", "4"]}}},
payload={"candidates": cands})
RequestInput מגדיר שלושה מאפיינים:
-
message: ההנחיה לכתיבת ביקורת שמוצגת למשתמש. -
response_schema: סכימת JSON שהקצה הקדמי מעבד כטופס קלט, שמאומת על ידי ADK לאחר השליחה. -
payload: מטא-נתונים שצורפו לבקשה (ארבעת המועמדים), שמאפשרים לממשקי לקוח לעבד כרטיסי ביקורת בלי לשלוח שאילתה לגבי מצב הסשן.
מה צפוי ולמה
- תהליך העבודה נעצר ב-direction_gate: ב-ADK Web או בממשק של סביבת העבודה, ההרצה מושהית ומוצג טופס אינטראקטיבי לבחירת מועמדים.
- הסיבה: המנוע נתקל ב-
RequestInputשהוחזר והמשיך את מצב הביצוע ל-runs/sessions.db.
- הסיבה: המנוע נתקל ב-
- המשך השיחה דורש קלט מובנה: שליחת טקסט שרירותי בצ'אט לא מקדם את הגרף. בחירה באחת מהאפשרויות (1, 2, 3 או 4) שולחת את הערך המוקלד
function_responseשעומד בתנאיresponse_schemaוממשיכה את ההרצה.
5. מדינה ונתב
ב-VibeStudio Workbench, עוברים אל Step 5 · State and Router, חלקים (5A) עד (5C).
תשמרו את בחירות המשתמש במצב הסשן, תאכפו את מדיניות הבטיחות של הערוץ באמצעות צמתי נתב דטרמיניסטיים ותבנו סוכן משימות איטרטיבי כדי לתקן באופן אוטומטי הפרות של מדיניות לפני יצירת תסריטים לסרטונים.
מצב תהליך העבודה (5A)
ב-Workbench, עוברים אל Workflow State (5A) (סטטוס תהליך העבודה (5A)).

מצב הסשן לעומת פלט הצומת
בתהליך עבודה של ADK, הנתונים עוברים בגרף באמצעות שני מנגנונים שונים:
- פלט של הצומת (
Event(output=...)): נתונים שמופנים אך ורק לצרכני נתונים במורד הזרם המיידי, שמוגדרים ברשימת הקצה. - מצב הסשן (
Event(state=...)): מילון משותף של זוגות מפתח/ערך שנגיש לכל צומת עוקב במחזור החיים של הביצוע.

כשמשתמש בוחר מועמד ב-direction_gate, הבחירה מגיעה כמדד מספרי ({"pick": "2"}). הצמתים הבאים בשרשרת צריכים את אובייקט ההנחיות המלא: שם, זווית הסיפור ושורת הפתיחה. במקום להעביר מטא-נתונים מפורטים דרך כל מטען ייעודי ביניים של צומת, persist_direction כותב את המועמד שנבחר למצב סשן משותף.
הצמתים לא צריכים להעביר את כל מילון מצב הסשן. כשצומת מחזיר Event(state=...), הוא מספק רק את צמדי המפתח/ערך החדשים או המעודכנים. ה-ADK ממזג אוטומטית את העדכונים האלה במאגר הסשנים:
yield Event(state={"direction": chosen["title"], "angle": chosen.get("angle", ""),
"hook": hook, "user:prefs": {"last_direction": chosen["title"]}})
הפונקציה מחזירה את הערך Event ומעבירה את השליטה לזמן הריצה Workflow, ששומר את הערכים החדשים ביומן הסשן ב-runs/sessions.db.
קישור פרמטרים
צמתי פונקציות של ADK קוראים את מצב הסשן באופן אוטומטי באמצעות בדיקת פרמטרים. אם חתימת פונקציה מכריזה על שם פרמטר שתואם למפתח מצב קיים, ה-ADK מחלץ את המפתח הזה מהמצב ומעביר אותו ישירות:
def persist_direction(node_input, candidates: list = []):
ni = node_input if isinstance(node_input, dict) else {}
raw = ni.get("pick")
pick = str(raw).strip() if raw is not None else ""
if candidates:
i = int(pick) - 1 if pick.isdigit() else 0
chosen = candidates[max(0, min(len(candidates) - 1, i))]
else:
chosen = {"title": "untitled", "angle": "", "evidence": []}
hook = chosen.get("hook") or " ".join(chosen["title"].split()[:4])
במקרה הזה, הערך candidates נכתב למצב הסשן על ידי direction_gate. ה-ADK מאגד אותו ישירות ל-persist_direction(node_input, candidates: list = []) בלי לדרוש חיפושים מפורשים במילון.
מפתחות עם הקידומת user: נשמרים בין סשנים באחסון ברמת המשתמש, וכך מאפשרים להפעלות הבאות של תהליך העבודה לגשת להעדפות היוצר.
עריכה מעשית: שמירת המצב וחיבור הצומת
- ב-
agent/graph.py, בתוךpersist_direction, מחליפים את השורהTODO: PERSIST_STATEבתפוקת אירוע המצב:
yield Event(state={"direction": chosen["title"], "angle": chosen.get("angle", ""),
"hook": hook, "user:prefs": {"last_direction": chosen["title"]}})
- ב-
stage3_router/agent.py, מוסיפים אתpersist_directionלשרשרת השלישית ברשימהedges:
(join_research, propose_directions, direction_gate,
persist_direction)
שומרים את הקבצים. בסביבת העבודה, מוודאים שגם state write in place וגם persist_direction in the chain מציגים סימני וי ירוקים.
צומת הנתב (5B)
ב-Workbench, עוברים אל צומת הנתב (5B).

ניתוב דטרמיניסטי על סמך מדיניות
נתב הוא צומת פונקציה מיוחד שמעריך את הפלט במעלה הזרם ומכוון את הביצוע לאורך ענפי תרשים מותנים. בניגוד לסוכנים גנרטיביים, נתב מבצע לוגיקה דטרמיניסטית בלי לבצע קריאות ל-LLM.
נתב מחזיר Event שמציין תג route:
def length_check(node_input):
too_long = len(node_input.get("title", "")) > 60
return Event(output=node_input, route="TRIM" if too_long else "PASS")
בהגדרת תהליך העבודה, יעד קצה שמוגדר כמילון ממפה שמות של מסלולים לצמתי יעד:
(length_check, {"TRIM": shorten, "PASS": scripter}),
הנתב של תהליך העבודה policy_check קורא את הביטויים האסורים מ-agent/policy_words.txt ומבצע התאמה של מילים שלמות לשם ולזווית של הכיוון שנבחר:
return Event(output=node_input, route="BLOCK" if bad else "OK")
שמירת המדיניות כנתונים במקום כהוראות שמוטמעות בקוד מאפשרת לבצע עדכונים בלי לשנות את גרף תהליך העבודה: עדכון קובץ הטקסט חל באופן מיידי על הרצות הבאות. ההערכה היא התאמה דטרמיניסטית של ביטויים רגולריים, ולכן היא מתבצעת במילישניות ללא עלות של טוקנים, לפני שמתחיל התסריט הגנרטיבי.
יעדים: Scripter ו-Quarantine
הנתב מפנה את התנועה לאחד משני צמתים במורד הזרם:
-
scripter: צומת של סוכןsingle_turnשממיר את ההנחיות שאושרו לסקריפט הפקה מובנה בהתאם לסכימתScriptPydantic:
scripter = Agent(
name="scripter",
model=config.MODEL,
instruction=SCRIPT_INSTRUCTION,
output_schema=Script)
-
quarantine: בתחילה, פונקציית placeholder שמשהה הוראות שסומנו. בחלק הבא היא מוחלפת בסוכן תיקון אוטונומי.
עריכה מעשית: ניתוב של בדיקת המדיניות
- בקטע
agent/graph.py, בתוךpolicy_check, משלימים את פקודת החזרה:
return Event(output=node_input, route="BLOCK" if bad else "OK")
- ב-
stage3_router/agent.py, מעדכנים אתedgesכדי להפנות ל-policy_checkומצטרפים מחדש לענף ההסגר ב-scripter:
(join_research, propose_directions, direction_gate,
persist_direction, policy_check),
(policy_check, {"OK": scripter, "BLOCK": quarantine}),
(quarantine, scripter)])
שומרים את הקבצים. בסביבת העבודה, מוודאים שמיפויי הנתבים של Edge אומתו.
מצבי סוכן וצומת המשימה (5C)
ב-Workbench, עוברים אל Agent modes and the task node (5C) (מצבי סוכן וצומת המשימה (5C)).

מצבי הרצה של סוכנים
מופעים של ADK Agent תומכים בשלושה מצבי הפעלה שמותאמים לדרישות ספציפיות של צינורות עיבוד נתונים:
מצב | מחזור החיים של הביצוע | תפקיד בפייפליין |
| לולאת שיחה רב-שלבית. המודל קובע מתי להפעיל כלים, לבקש קלט או לסיים את התור. | סוכני הבסיס שמתמודדים עם משתמש אנושי אינטראקטיבי. |
| קריאה להסקה של מודל יחיד. מקבל קלט מהצומת הקודם ופולט אובייקט סכמה מובנה. | טרנספורמציות רציפות של גרפים ( |
| Autonomous loop with tool execution. הנציג חוזר על הפעולה עד שהוא מתקשר לכלי המובנה | תיקון ובדיקה רב-שלביים ( |
תיקון אוטונומי של מדיניות
כדי לשכתב הוראה שסומנה, צריך להשתמש במצב task כי מספר האיטרציות של התיקון משתנה. הסוכן מקבל את ההנחיה שסומנה, מפעיל את find_policy_hits כדי לזהות הפרות, מבקש חלופות מאושרות באמצעות suggest_replacement, משכתב את ההנחיה ומאמת שהיא נקייה לפני שהוא ממשיך.
שני הכלים מוגדרים ב-agent/cleanup_tools.py עם חתימות מוקלדות ומחרוזות תיעוד:
def find_policy_hits(text: str) -> dict:
"""Which refused words appear in `text`. Matches whole words and phrases
from agent/policy_words.txt, case-insensitive.
Returns {"hits": [...], "clean": bool}. clean is true when hits is empty.
"""
def suggest_replacement(word: str) -> dict:
"""The channel's approved stand-in for a refused word, read from
agent/policy_replacements.txt.
Returns {"word", "replacement", "listed"}. When the word has no entry,
listed is false and replacement is a hint to pick a gentle synonym.
"""
עריכה מעשית: הרכבת סוכן המשימות של ההסגר
ב-stage3_router/agent.py, מחליפים את פונקציית ה-placeholder quarantine בהגדרה של סוכן המשימות:
quarantine = Agent(
name="quarantine",
model=config.MODEL,
instruction=QUARANTINE_INSTRUCTION,
mode="task",
tools=[find_policy_hits, suggest_replacement],
output_schema=CleanedDirection,
)
במצב משימה, הסוכן מצויד בכלים וההרצה מסתיימת על ידי קריאה ל-finish_task. כשמגדירים את mode="task", ADK מספק אוטומטית את finish_task וגוזר את הפרמטרים שלו מ-output_schema, וכך מוודא שהצומת יפיק אובייקט מוקלד CleanedDirection שתואם לסכימת הקלט של צומת הסקריפט.

מה צפוי ולמה
בודקים את שני נתיבי הביצוע ב-ADK Web או ב-VibeStudio Workbench:
- מסלול מאושר (מועמד 1, 2 או 3):
- בחירת מועמד שאושר מעבירה את המסלול מ
policy_checkישירות אלscripter(route="OK"). - התסריטאי יוצר תסריט הפקה של 3 שוטים בהתאם לסכימה
Script.
- בחירת מועמד שאושר מעבירה את המסלול מ
- Quarantine remediation route (Candidate 4):
- אלמנט החיפוש מספר 4 מכיל אוצר מילים מסומן ("קליקבייט", "פריצה ויראלית").
policy_checkמסלולים אלquarantine(route="BLOCK").- במעקב אחר הסשן, אפשר לראות את
quarantineקורא ל-find_policy_hits, קורא ל-suggest_replacementלכל הפרה, משכתב את הכותרת וקורא ל-finish_task. - ההרצה חוזרת ל-
scripter, ויוצרת תסריט מההנחיה שעברה ניקוי.
6. Memory Bank
בסביבת העבודה של VibeStudio, עוברים אל שלב 6 – מאגר זיכרון, חלקים (6א) ו-(6ב).
כרגע, תהליך העבודה פועל ללא זיכרון בין הפעלות. כל הפעלה מתחילה מאפס, בלי לדעת מה היוצר בחר קודם או אילו ז'אנרים הוא מעדיף. בשלב הזה, מחברים את Vertex AI Agent Engine Memory Bank כדי לאחסן את ההעדפות של היוצרים ולאחזר אותן בין הפעלות.
חשוב לציין שהזיכרון משולב באמצעות קריאות חוזרות (callbacks) של מחזור החיים של הסוכן, ולא באמצעות צמתי צינור. מכיוון שחילוץ ואחזור של זיכרון משרתים סוכנים בודדים במקום שלבי נתונים ביניים, צירוף קריאות חוזרות שומר על טופולוגיית גרף נקייה ומנותקת.
Memory Bank (6A)
בסביבת העבודה, עוברים אל Memory Bank (6A) (מאגר הזיכרון).

זיכרון נפרד לכל משתמש מנוהל
Memory Bank הוא שירות מנוהל לזיכרון משתמש לטווח ארוך. הוא מארגן עובדות על אדם מסוים בהיקף מוגדר, שמזוהה כאן לפי שם האפליקציה ומזהה המשתמש:
SCOPE = {"app_name": config.APP, "user_id": config.USER}
TOPICS = {
"CREATOR_TASTE": "Which video directions this creator picks and passes on, "
"and how that preference changes over time.",
"CHANNEL_RULES": "Standing instructions the creator states for every video "
"(style, subjects to avoid, format rules).",
}
נושאי זיכרון מותאמים אישית מגדירים את הגבולות של מה שהבנק מתעד:
- חילוץ נושאים: כששולחים טקסט חדש לשיחה באמצעות
memories.generate, השירות מפעיל מודל חילוץ על כל תיאור של נושא. אם הטקסט לא תואם לנושא, לא נוצרים זיכרונות. - איחוד והסרת כפילויות: השירות ממיר עובדות חדשות שחולצו להטבעות ומשווה אותן לזיכרונות קיימים בהיקף. כשתצפית תואמת לזיכרון קיים, השירות מעדכן את הזיכרון הזה. אם המידע חדש, השירות יוצר רשומה חדשה. תהליך האיחוד הזה מבטיח שמידע מכמה סשנים בנושא מסוים יאוחד לסיכום קוהרנטי, במקום ליצור רשומות מיותרות.
- אחזור: קריאה ל-
memories.retrieveעם היקף המשתמש מחזירה עובדות מאוחסנות, בסדר מהישן לחדש.
שתי הפעולות מיושמות ב-agent/platform/memory.py. שם משאב הבנק שהוקצה נשמר במטמון באופן מקומי ב-runs/memorybank.json.
הגדרת בנק הזיכרונות
משתמשים באמצעי הבקרה של סביבת העבודה או מריצים את פקודות ה-CLI בטרמינל:
- חיבור הבנק והקצאת הרשאות:
יצירת מופע של Agent Engine והגדרת הנושאיםpython -m agent.platform.bankCREATOR_TASTEו-CHANNEL_RULES. - הוספת נתונים היסטוריים של סשנים:
טוען ארבעה סשנים היסטוריים של יוצרים (שני עיצובים של בעלי חיים עם מגבלות סגנון, עיצוב אחד של גאדג'ט ועיצוב פנטזיה אחד מהזמן האחרון).python -m agent.platform.bank load - בדיקת עובדות מאוחדות:
בודקים את הפלט. שימו לב איך תמלילים נרטיביים הומרו להצהרות עובדתיות מובנות ומאוחדות.python -m agent.platform.bank list
קריאות חוזרות (6B)
ב-Workbench, עוברים אל Callbacks (6B). פותחים את stage4_memory/agent.py.

קריאות חוזרות במחזור החיים של סוכן ADK
פונקציית קריאה חוזרת היא פונקציה שמועברת כארגומנט לפונקציה Agent. ערכת ה-ADK מפעילה קריאות חוזרות (callbacks) ברגעים מוגדרים מראש במחזור החיים, ומעבירה את ההקשר הפעיל. החזרת None ממשיכה את הביצוע הרגיל, והחזרת אובייקט חלופי מבטלת את הפעולה או מיירטת אותה.

ערכת ה-ADK מספקת שלושה זוגות של פונקציות קריאה חוזרת:
זוג של קריאה חוזרת | נקודת הפעלה | פרמטרים שהתקבלו | התנהגות הערך המוחזר |
| מסביב לכל תור הסוכן | | הקשה על מקש |
| מסביב לכל קריאה להסקת מסקנות של מודל שפה גדול |
| החזרת |
| מסביב לכל הרצה של כלי | הגדרת הכלי, הארגומנטים והתוצאה | החזרת מילון מבטלת את פלט הכלי, |
התכונה 'התקשרות חוזרת' מספקת מיקום נקי להוספת הקשר, אמצעי הגנה, טלמטריה וחיפושים במטמון, בלי להוסיף צמתים מיותרים לגרף של תהליך העבודה.
עריכה מעשית: החזרת שיחות חוזרות וזכירת שיחות חוזרות
- ב-
stage4_memory/agent.py, מעדכנים אתpropose_directionsכדי לצרף אתbefore_model_callback=recall_taste:
output_schema=Directions,
before_model_callback=recall_taste)
recall_taste מופעל מיד לפני ש-Gemini יוצר הצעות לניסוח. הכלי מאחזר את ההיסטוריה של היוצר מ-Memory Bank, מעצב את הזיכרונות מהישן לחדש ומצרף אותם לLlmRequest היוצא. ההנחיה מכוונת את המודל להטות את המועמדים 1 עד 3 לכיוון הטעם הנוכחי של היוצר, תוך התייחסות לכללי הערוץ כמגבלות מחמירות.
- ב-
stage4_memory/agent.py, מעדכנים אתscripterכדי לצרף אתafter_agent_callback=remember_pick:
output_schema=Script,
after_agent_callback=remember_pick)
הפעולה remember_pick מתבצעת אחרי ש-scripter משלים את התור שלו. הוא קורא את הכיוון שנבחר ממצב הסשן, מסנתז הצהרה תמציתית שמסכמת את ההחלטה של היוצר ומפעיל את memories.generate כדי לעדכן את Memory Bank.
מה צפוי ולמה
בודקים את תהליך העבודה המשופר באמצעות קריאה חוזרת (callback) בכלי הפיתוח או ב-ADK Web:
- מריצים פרומפט ריק:
- במעקב אחר הסשן, בודקים את
LlmRequestעבורpropose_directions. שימו לב להקשר הזיכרון שנוסף, שבו מפורטת ההעדפה של היוצר לנושאי פנטזיה ולקצב תמציתי. - שימו לב להצעות: מועמדים 1 עד 3 תואמים להעדפות ההיסטוריות של היוצר, גם כשהמגמות מדגישות נושאים אחרים.
- במעקב אחר הסשן, בודקים את
- בוחרים מועמד בכתובת
direction_gate. - אחרי ש
scripterמסתיים, בודקים את הרשומות ב-Memory Bank: המערכת תעדכן את הבחירה האחרונה בנתוני הבנק ותאחד אותה עם רשומות הטעם הקודמות.python -m agent.platform.bank list
7. RAG Engine
ב-VibeStudio Workbench, עוברים אל Step 7 · RAG Engine, חלקים (7A) ו-(7B).

סרטונים שפורסמו צוברים משוב מתמשך מהצופים. מערכת AI אוספת 30 תגובות מייצגות ב-agent/comments.md, שכוללות שבחים מהצופים, ביקורת על קצב הצגת התוכן הממומן והעדפות לגבי אודיו. בשלב הזה, יוצרים אינדקס לתגובות האלה באמצעות Vertex AI RAG Engine ומחברים את השליפה הסמנטית ל-fan-out של המחקר.
אחזור מידע ממסמכים (7A)
ב-Workbench, עוברים אל RAG Engine (7A).
Memory Bank לעומת RAG Engine
שני הכלים מבוססים על נתונים חיצוניים, אבל הם משמשים למטרות ארכיטקטוניות שונות:
מאפיין | Memory Bank | RAG Engine |
תרחיש שימוש ראשי | העדפות משתמשים לטווח ארוך וכללים תפעוליים | אחזור סמנטי של אוספים גדולים של מסמכים |
היקף | ההיקף מוגבל למזהי משתמשים ספציפיים ולשמות אפליקציות | ההיקף מוגבל למשאבי מאגר מידע משותפים לכל המשתמשים |
עיבוד נתונים | חילוץ, הטמעה ואיחוד סמנטי בזמן אמת | חלוקת מסמכים לחלקים, הטמעת וקטורים וחיפוש השכן הקרוב ביותר |
שילוב של גרפים | קריאות חוזרות במחזור החיים של הסוכן ( | צומת פונקציה ייעודית ב-fan-out של מחקר ( |

חלוקה לקטעים והטמעה של מסמכים
מנוע RAG מוסיף מסמכים לאינדקס על ידי חלוקת הטקסט לקטעים סמנטיים ושמירת הווקטורים שלהם במסד נתונים מנוהל:
corpus = rag.create_corpus(
display_name="vibestudio-feedback",
description="Vibe Studio: what the audience wrote under the channel's past videos.",
backend_config=rag.RagVectorDbConfig(
rag_embedding_model_config=rag.RagEmbeddingModelConfig(
vertex_prediction_endpoint=rag.VertexPredictionEndpoint(
publisher_model="publishers/google/models/text-embedding-005"))))
rag.upload_file(
corpus_name=corpus.name, path="agent/comments.md", display_name="comments.md",
transformation_config=rag.TransformationConfig(
chunking_config=rag.ChunkingConfig(chunk_size=120, chunk_overlap=20)))
- גודל המקטע: מוגדר ל-120 טוקנים עם 20 טוקנים של חפיפה. כך נאספות שתיים או שלוש תגובות לכל פסקה, כדי להבטיח שכל וקטור ייצג סנטימנט מגובש בלי לפגוע במשמעות של משוב לא קשור.
- מודל הטמעה:
text-embedding-005ממיר טקסט לווקטורים עם הרבה ממדים. כששולחים שאילתה, המודל ממיר את השאילתה לווקטור ומוצא את ההתאמות הקרובות ביותר על סמך מרחק סמנטי. תגובה על דרקון קטן ששומר על גרביים תואמת להנחיה על יצורים קסומים, בלי שנדרש חפיפה מדויקת של מילות מפתח.
הגדרת מאגר המידע של RAG
מאותחלים את הקורפוס באמצעות הלחצנים של סביבת העבודה או פקודות במסוף:
- יוצרים את מאגר הטקסטים:
מבצע הקצאה של מסד נתונים וקטורי מנוהל ומתעד את מזהה המשאב ב-python -m agent.platform.ragruns/ragcorpus.json. - העלאה והוספה לאינדקס של תגובות: מעלה את
agent/comments.mdעם הגדרת חלוקה לחלקים וממתין לסיום ההוספה לאינדקס. - שאילתות על הקורפוס: בודקים את אחזור הדמיון באמצעות שאילתות שלא כוללות מילים זהות לתגובות (לדוגמה, שאילתה 'יצורים קסומים קטנים' כדי לאחזר תגובות על דרקונים).
צומת האחזור (7B)
ב-Workbench, מנווטים אל The third reader (7B). פותחים את stage5_rag/agent.py.

אחזור כצומת בתרשים
המשוב מהקהל מייצג נתוני מחקר שמשותפים בתהליך העבודה. בניגוד לזיכרון האישי של היוצר, הסנטימנט של הצופים מוזן ישירות ל-join_research לצד נתוני מגמות ונתוני עומס עבודה. לכן, היא מיושמת כצומת פונקציה:

def read_feedback(node_input):
"""The third reader (step 7): what the audience wrote under past videos,
the passages nearest to tonight's idea. Retrieval, not a model call."""
from .platform import rag
idea = idea_text(node_input)
query = idea or "what viewers liked and what they complained about"
try:
hits = rag.retrieve(query)
except Exception as e:
print(f" [rag] feedback unavailable ({str(e)[:80]})")
return Event(output={"query": query, "feedback": [],
"note": "no corpus connected - run: python -m agent.platform.rag"})
return Event(output={"query": query, "feedback": [h["text"] for h in hits]})
read_feedback מחלץ את הרעיון הראשוני של המשתמש ומריץ שאילתת וקטורים מול מאגר המידע של מנוע ה-RAG. היא מחזירה את התגובות שאוחזרו במטען ייעודי (payload) מסוג Event(output=...).
עריכה מעשית: חיבור הקורא השלישי ל-fan-out
ב-stage5_rag/agent.py, מעדכנים את edges כדי להוסיף את read_feedback כענף מקביל שלישי שנכנס ל-join_research:
(START, read_backlog, join_research),
(START, read_feedback, join_research),
מכיוון ש-join_research הוא JoinNode, הוא מסנכרן את כל הענפים הנכנסים וממתין עד ש-scan_trends, read_backlog ו-read_feedback ישדרו את כל האירועים לפני שהוא מעביר את חבילת האירועים המצטברת במורד הזרם.
מה צפוי ולמה
מריצים את תהליך העבודה ב-Workbench:
- שולחים הנחיית רעיון (לדוגמה, "דרקון מיניאטורי ששומר על משטח במטבח").
- במעקב הביצוע, מוודאים שכל שלושת צמתי הקריאה מופעלים בו-זמנית.
- שימו לב ל-
join_research: מילון הפלט שלו מכיל עכשיו אתtrends,backlogו-feedback. - בודקים את המועמדים שנוצרו מ-
propose_directions: המודל משלב את התגובות של הצופים בהצעות שלו, ומפנה לרגשות של הקהל בשדות הראיות. - שימו לב שאחזור RAG הוא דטרמיניסטי (שאילתות זהות מחזירות קטעי תגובות זהים), בעוד שצומת ההצעה הגנרטיבית יוצר וריאציות קריאייטיביות.
8. יצירת סרטונים אסינכרונית באמצעות Veo
ב-VibeStudio Workbench, עוברים אל Step 8 · The video, חלקים (8A) ו-(8B).
יצירת סרטון בהגדרה גבוהה באמצעות Google Veo דורשת כמה דקות לכל רינדור. חסימת הביצוע של הגרף במהלך התקופה הזו מבזבזת משאבי מחשוב, נועלת מאגרי שרשורים וחושפת את ההרצה לנטישות של חיבורי HTTP. בשלב הזה, מבצעים עיבוד אסינכרוני של הווידאו באמצעות LongRunningFunctionTool של ADK.
כלים לטווח ארוך (8A)
בסביבת העבודה, עוברים אל כלי שפועל לאורך זמן (8A). פותחים את stage6_video/agent.py ואת agent/deliver.py.

כלים סינכרוניים לעומת כלים שפועלים לאורך זמן
הכלים הרגילים של פונקציות ADK פועלים באופן סינכרוני במהלך תור של סוכן: המודל קורא לכלי, מחכה למטען הייעודי (payload) שמוחזר ומשלב את התוצאה בתור הנוכחי.
אי אפשר להשלים את עיבוד הסרטון במהלך תור אחד. במקום זאת, render_submit מתחיל את משימת היצירה ומחזיר מיד קבלה תפעולית עם הסטטוס "pending":
def render_submit(prompt: str) -> dict:
"""Submit one Veo render of `prompt`. Returns at once with a pending
receipt; the clip is delivered later, to this call, by id."""
receipt = videogen.start(f"{prompt} {videogen.NO_TEXT}")
return {"status": "pending", "operation": receipt["operation"], "prompt": receipt["prompt"]}
כשעוטפים את הסטטוס "pending" ב-ADK, הוא מיירט את הסטטוס "pending".LongRunningFunctionTool תור הסוכן מסתיים, תהליך העבודה מושהה בצומת, ומטא-הנתונים של השיחה בהמתנה (כולל מזהה השיחה והקבלה) נרשמים ב-runs/sessions.db. תהליך ההפעלה מסתיים בצורה נקייה בלי לשמור על חיבורי רשת פעילים או על שרשורי עובדים.
עריכה מעשית: עטיפת כלי העיבוד
ב-stage6_video/agent.py, מעדכנים את render_desk כך שיכלול את render_submit ב-LongRunningFunctionTool:
tools=[LongRunningFunctionTool(render_submit)])
חידוש השיחה באמצעות מזהה השיחה
דפוס ההמשך האוניברסלי
ADK משתמש במנגנון זהה להשהיה ולחידוש של תהליכי עבודה, גם עבור בני אדם וגם עבור כלים חיצוניים:
טריגר השעיה | הפעלת Construct | מצב השעיה מאוחסן | אירוע המשך |
החלטה אנושית |
| פתיחת פרומפט קלט בחנות הסשנים |
|
כלי ממושך |
| פתיחת קריאה לכלי בחנות הסשנים |
|
בשני התרחישים, תהליך העבודה נעצר לחלוטין ומתחדש רק כשאירוע עם FunctionResponse תואם מגיע ממקור חיצוני: ממשק משתמש, webhook או תהליך ברקע.
עריכה מעשית: השלמת תשובת המשלוח
ב-agent/deliver.py, יוצרים את החלק של ההמשך FunctionResponse:
part = Part(function_response=FunctionResponse(
id=row["call_id"], name=row["name"], response=response))
הדמון של ההעברה שולח שאילתות ל-Veo עד שקובץ הווידאו נוצר, ואז הוא שולח את FunctionResponse לסשן. ADK מתאים למזהה השיחה וממשיך את תהליך העבודה ישירות בצומת הבא. צמתים שהושלמו לא מופעלים מחדש, והסוכן לא מבצע עוד תור גנרטיבי.
הגדרה של STUDIO_REAL_VIDEO=0 ב-.env מאפשרת עיבוד מדומה: הפונקציה start מחזירה קבלה מיידית של בדיקה, והפונקציה check מדמה השלמה תוך חמש שניות בלי לבצע קריאות ל-Veo API שניתנות לחיוב.
שילוב צינורות עיבוד נתונים (8B)
בסביבת העבודה, עוברים אל render_desk בתרשים (8B). פותחים את stage6_video/agent.py.
צומת הטרמינל בצינור הוא store_video. הוא קורא את פרטי הרינדור שהושלם מ-runs/state.json (המקום שבו תהליך ההעברה תועד) ומבצע קומיט של כתובת ה-URL של הסרטון וסטטוס היצירה למצב סשן משותף.

עריכה מעשית: חיבור צינור העברת הנתונים המלא של הסרטון
ב-stage6_video/agent.py, מעדכנים את edges כדי לצרף את render_desk ואת store_video:
(quarantine, scripter),
(scripter, render_desk, store_video)])
מה צפוי ולמה
בדיקת תהליך היצירה האסינכרוני בסביבת העבודה:
- מריצים את תהליך העבודה באמצעות בחירת מועמד ויצירת תסריט.
- ב-
render_desk, מתבוננים בהפעלת הסוכןrender_submit. - תהליך העבודה מושהה באופן מיידי. בסביבת העבודה או ב-ADK Web, בודקים את הסטטוס 'בהמתנה': הסשן מכיל את מזהה השיחה הפתוחה, ולא מתבצעים תהליכים ברקע שצורכים משאבים.
- מריצים את דמון המסירה באמצעות מסוף סביבת העבודה או במסוף:
תהליך המסירה עוקב אחרי Veo עד שהסרטון מוכן, ואז שולח את אירוע ההמשך.python -m agent.deliver - ב-ADK Web, מרעננים את הסשן: ההרצה ממשיכה ב-
store_video, כתובת ה-URL של הסרטון נשמרת במצב הסשן, ותהליך העבודה מסתיים.
9. פריסה ב-Cloud Run
ב-VibeStudio Workbench, עוברים אל Step 9 · Deploy (שלב 9 – פריסה).
פיתחתם ואימתתם כל רכיב בצינור עיבוד הנתונים בארגזי חול ייעודיים. בשלב הזה מרכיבים את צינור הייצור המלא ומפרסים אותו ב-Google Cloud Run.

ה-ADK Runner
בפיתוח, adk web תזמן את הגרף. בסביבת הייצור, האפליקציה מארחת את תהליך העבודה באמצעות המחלקה Runner של ADK:
self._svc = DatabaseSessionService(db_url=config.DB_URL)
self._runner = Runner(app_name=config.APP, agent=wf, session_service=self._svc)
async for ev in self._runner.run_async(user_id=config.USER, session_id=run_id, new_message=message):
self._absorb(ev) # fold the ADK event into the run state, publish one app event
# the gate's answer and the render's delivery are the same call, with a function_response part
part = Part(function_response=FunctionResponse(id=call_id, name=name, response=response))
-
run_async: מפעיל את תהליך העבודה, מפיק אירועים ברצף בזמן שהצמתים מופעלים ושומר את העדכונים בשירות הסשן. - המשך פעולה מאוחד: גם החלטות המשתמש ב-
direction_gateוגם מסירות הווידאו שהושלמו מ-Veo ממשיכות את הביצוע באמצעות אובייקטים זהים שלFunctionResponseשנשלחים אלrun_async.
ארכיטקטורת האפליקציה בסביבת הייצור
אפליקציית הייצור ב-vibestudio/ משלבת את צינור הנתונים המלא:
vibestudio/
server/
main.py FastAPI: application server, REST routes, static assets
api.py REST API endpoints: run, pick, publish, backlog, profile, history
runner.py Runner orchestration over the workflow, background render poller
platform/ Event bus (SSE stream), file storage, publishing, telemetry
agent/ Production agent package, verified by checks/verify_app.py
graph.py The complete workflow graph and node definitions
desk.py render_desk and render_submit wrapped with LongRunningFunctionTool
schemas.py Pydantic schemas: Directions, CleanedDirection, Script
cleanup_tools.py Deterministic policy tools: find_policy_hits, suggest_replacement
platform/ Memory Bank, RAG Engine, and Veo integrations
web/ Production React user interface
Dockerfile · deploy.py · run.sh
- זרם אירועים יחיד: קצה העורף של FastAPI מפרסם אירועים בזרם יחיד של אירועים שנשלחים מהשרת (SSE). ממשק הקצה של React מציג את התקדמות הגרף בזמן אמת ומטפל בחיבורים מאוחרים בלי לאבד את המצב.
- ביצוע מנותק: האפליקציה מנהלת את לולאת האירועים. תרשים זרימת העבודה מתמקד אך ורק בלוגיקת הביצוע, בלי להתייחס לממשק הקצה.
רשימת הקצוות המלאה של זרימת העבודה ב-agent/graph.py משלבת כל תבנית ארכיטקטונית שנבנתה במהלך ה-codelab הזה:
(START, scan_trends, join_research),
(START, read_backlog, join_research),
(START, read_feedback, join_research),
(join_research, propose_directions, direction_gate,
persist_direction, policy_check),
(policy_check, {"OK": scripter, "BLOCK": quarantine}),
(quarantine, scripter),
(scripter, render_desk, store_video),
פריסה ב-Cloud Run
Google Cloud Run מספק אירוח ללא שרת עם התאמה אוטומטית לעומס, ניתוב בקשות וגרסאות build משולבות של קונטיינרים:
gcloud run deploy vibestudio --source vibestudio \
--project $GOOGLE_CLOUD_PROJECT --region us-central1 \
--labels dev-tutorial-codelab=vibetube --allow-unauthenticated \
--memory 2Gi --cpu 2 --timeout 3600 --concurrency 40 \
--max-instances 1 --min-instances 1 --session-affinity \
--set-env-vars GOOGLE_CLOUD_PROJECT=...,STUDIO_VERTEX=1,STUDIO_MEMORY_BANK=...,STUDIO_RAG_CORPUS=...,VIBETUBE_URL=...,VIBETUBE_EVENT=...,VIBETUBE_NAME=...,VIBETUBE_PROJECT=...
- יצירת קונטיינר: הפקודה
gcloud run deploy --sourceאורזת את הספרייהvibestudio/, יוצרת את קובץ האימג' של הקונטיינר באמצעות Cloud Build ומפריסה את השירות בפעולה אחת. - זיקה לסשן (session affinity): מפנה בקשות מאותו משתמש לאותו מופע של קונטיינר, ושומר על מצב הסשן המקומי לאורך שלבים חוזרים.
- יכולת צפייה (Observability): שילוב של Cloud Trace מתעד טווחים מבוזרים לכל צומת, קריאה ל-LLM והפעלה של כלי, שאפשר לגשת אליהם ב-Trace Explorer במסוף Google Cloud.
לוחצים על הלחצן פריסה בסביבת העבודה כדי להפעיל את סקריפט הפריסה. בסיום ה-build, כתובת ה-URL של השירות בשידור חי מוצגת בטרמינל.

10. סיכום
ב-VibeStudio Workbench, עוברים אל שלב 10 · סיכום כדי לבדוק את הארכיטקטורה שהושלמה.

שלב | ארכיטקטורה ומושגים | תבנית הטמעה |
פרומפט אחד | פרומפט יחיד, כלים לפונקציות, לולאת צ'אט רציפה |
|
היסודות של תהליכי עבודה אג'נטיים | גרף תהליך העבודה, מחקר מקביל, פלט סכימה, שער אנושי |
|
מדינה ונתב | מצב סשן משותף, קישור פרמטרים, ניתוב דטרמיניסטי, סוכן משימות |
|
Memory Bank | זיכרון לטווח ארוך ברמת המשתמש, איחוד סמנטי, נקודות חיבור למחזור החיים |
|
RAG Engine | אחזור מסמכים על סמך תגובות של קהלים, הטמעות סמנטיות |
|
יצירת סרטונים אסינכרונית באמצעות Veo | כלים שפועלים לאורך זמן, קבלות בהמתנה, שד חיצוני למסירה | |
פריסה ב-Cloud Run | תזמור תוכנתי, אירועים שנשלחים מהשרת, מאגר תגים בצד השרת | |
עקרונות ארכיטקטוניים מרכזיים
- השעיה במקום המתנה: תהליכי העבודה מושהים בצורה נקייה כדי לאפשר קלט אנושי (
RequestInput) או פעולות ממושכות (LongRunningFunctionTool). התהליכים לא ממתינים בלי פעילות ב-Threads או בשקעי רשת. - הפעלה מחדש אוניברסלית: כל ההשעיות מופעלות מחדש באמצעות מנגנון זהה: הודעת
function_responseיחידה שכוללת את מזהה השיחה של הצומת שהושעה. - ניהול מצב מנותק: הצמתים משתפים נתונים באמצעות מפתחות בעלי שם של מצב הסשן וקישור פרמטרים, במקום מטען ייעודי (payload) מפורט ומקושר באופן הדוק.
- ניתוב דטרמיניסטי לפני עלות גנרטיבית: מסנני ביטויים רגולריים ונתבים מבוססי-כללים בודקים את המדיניות ללא עלות של טוקנים לפני הפעלת מודלים גנרטיביים.
- הפרדה בין נושאים: הקשר שספציפי לסוכן מסוים שייך לקריאות חוזרות (callback) של מחזור החיים, בעוד שתלות בנתונים משותפים שייכת
