1. Giriş

Ham bir konu özetini alıp son derece ilgi çekici sosyal medya öğelerinin oluşturulmasını düzenleyen çok formatlı ve çok agent'lı bir motor oluşturmayı öğrenin. Google'ın Agent Development Kit (ADK) ve Agent2Agent (A2A) protokolünü kullanarak bağımsız mikro ajanlar oluşturacak, marka kurallarını yeniden kullanılabilir bir ajan becerisi olarak paketleyecek, Cloud Run'a bir ajan hizmeti dağıtacak ve BigQuery AI işlevleriyle marka uyumluluğu için oluşturulan temel görsellere puan vereceksiniz.
Yapacaklarınız
Bu codelab'de aşağıdaki görevleri nasıl gerçekleştireceğinizi öğreneceksiniz:
- Belirleyici bir grafik iş akışıyla birden fazla ADK aracısını düzenleyin.
- Marka kurallarını yalnızca gerektiğinde yüklenen bir aracı becerisi olarak paketleyin.
- Bir ajana, çıktısını eser olarak kaydeden bir görüntü üretme aracıyla donatın.
- Bir aracı A2A hizmeti olarak kullanıma sunma ve başka bir aracıdan uzaktan düğüm olarak çağırma
- Görsel Yönetmen'i Cloud Run'a dağıtın ve iş akışını A2A üzerinden çağırın.
- BigQuery'de yapay zeka işlevlerini kullanarak oluşturulan temel görselleri marka uyumluluğu açısından puanlayın.
İhtiyacınız olanlar
- Web tarayıcısı (ör. Chrome)
- Faturalandırmanın etkin olduğu bir Google Cloud hesabı ve Google Cloud projesi.
2. Başlamadan önce
Google Cloud projesi oluşturma
- Google Cloud Console'daki proje seçici sayfasında bir Google Cloud projesi seçin veya oluşturun.
- Cloud projeniz için faturalandırmanın etkinleştirildiğinden emin olun. Bir projede faturalandırmanın etkin olup olmadığını nasıl kontrol edeceğinizi öğrenin.
Cloud Shell'i Başlatma
Kodu indirmek, kurulum komut dosyalarını çalıştırmak ve uygulamayı dağıtmak için Google Cloud Shell'i kullanacaksınız.
- Tarayıcınızda Google Cloud Shell'i açın (veya Google Cloud Console'un üst kısmındaki Cloud Shell'i etkinleştir'i tıklayın):
Ek bildirimler verilirse Devam'ı tıklayın.Hem terminalin hem de düzenleyicinin tamamen yüklenmesini bekleyin. Bu işlem bir iki dakika sürebilir.https://shell.cloud.google.com/ - Bu kodu terminale yapıştırarak ortamınızda Google Cloud proje kimliğinizi ve bölgenizi (örneğin,
us-central1) yapılandırın (vedeğerlerini kendi değerlerinizle değiştirin):export PROJECT_ID="<YOUR_PROJECT_ID>" export REGION="<YOUR_REGION>" gcloud config set project $PROJECT_ID
Aşağıdakine benzer bir mesaj görürsünüz:Your active configuration is: [cloudshell-####] Updated property [core/project] - Projeniz için gerekli Google Cloud API'lerini etkinleştirin:
gcloud services enable \ compute.googleapis.com \ cloudresourcemanager.googleapis.com \ aiplatform.googleapis.com \ storage.googleapis.com \ storage-component.googleapis.com \ bigqueryconnection.googleapis.com \ bigquery.googleapis.com \ run.googleapis.com \ secretmanager.googleapis.com \ cloudbuild.googleapis.com \ artifactregistry.googleapis.com \ iap.googleapis.com \ iam.googleapis.com
Depoyu Klonlama
Codelab'e başlamanıza yardımcı olacak bir kod şablonumuz var. Bu dosya nispeten küçüktür ancak bulunduğu GitHub deposu oldukça büyüktür. Klonlama işlemini hızlandırmak ve disk alanından tasarruf etmek için normalde git clone komutunu --filter=blob:none seçeneği, git sparse-checkout ve başka bazı komutlarla birlikte kullanırız.
Bu çok karmaşık görünüyor ancak Antigravity tüm bunları bizim için yapabilir.
Öncelikle Antigravity CLI'yı yapılandırarak doğrudan sorunumuzu çözmesini sağlayalım ve başlatalım.
Cloud Shell'de şu komutu çalıştırın:
source <(curl -fsSL https://github.com/GoogleCloudPlatform/devrel-demos/raw/refs/heads/vladkol/cloud-shell-configure-agy/codelabs/labs-scripts/bwg-multi-agent-pitch-generator/cloud_shell_configure_agy.sh)
Bu komut, Antigravity CLI'yı yapılandırır ve aynı terminalde başlatır. Antigravity CLI'dan çıktığınızda Cloud Shell isteminize geri dönersiniz.

Depoda yalnızca codelabs/bwg-multi-agent-pitch-generator klasörüne ihtiyacımız var. Antigravity'den yalnızca bu klasörü indirmesini ve ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/ konumunda yerel olarak saklamasını isteyelim.
Antigravity CLI'ya şu görevi verin:
Download files from under `https://github.com/GoogleCloudPlatform/devrel-demos/tree/main/codelabs/bwg-multi-agent-pitch-generator`
to folder `~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/`.
If `devrel-demos` folder already exists, rename it with a `.backup` suffix.

Antigravity görevi yerine getirir. Birkaç komut çalıştırmak için sizden izin isteyecektir. Kod indirildikten sonra /exit komutunu çalıştırarak Antigravity CLI'dan çıkın:
/exit

Depo çalışma alanını açın.
Şimdi Cloud Shell'de kod çalışma alanını açalım. Cloud Shell terminalinde şu komutu çalıştırın:
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/
cloudshell workspace .
Kurulum komut dosyasını çalıştırın
Bu deneyimi daha sorunsuz hale getirmek için kurulum komut dosyasını depodan çalıştırın. Ortam değişkenlerini yapılandırır, agents-cli'ı yükler, yapılar için Cloud Storage paketi oluşturur, BigQuery Cloud Resource bağlantısını oluşturur ve otomatik yeniden deneme ile hizmet hesabına gerekli IAM izinlerini verir.
Kurulum komut dosyası, yukarıda dışa aktardığınız PROJECT_ID ve REGION'den her iki aracının da ihtiyaç duyduğu değişkenleri (GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_REGION, GOOGLE_CLOUD_LOCATION ve GOOGLE_GENAI_USE_VERTEXAI) türeten küçük bir yardımcı olan setenv.sh'yı da çağırır. Ayrıca bu iki değeri ana dizininizdeki bir .env dosyasına kaydederek daha sonra kurtarmanızı sağlar.
- Cloud Shell'de kurulum komut dosyasını yürütülebilir hale getirin ve çalıştırın:
chmod +x codelab-setup.sh setenv.sh ./codelab-setup.sh - Bu işlemin çalışması yaklaşık bir dakika sürer. Başarıyı belirten şu mesajı görmelisiniz: "🎉 🦄 Komut dosyası yürütme tamamlandı."

- Kurulum komut dosyası kendi kabuğunda çalıştığı için değişkenleri terminalinize ulaşmadı. Bu dosyaları oturumunuza yükleyin:
Projenizin, bölgenizin ve konumunuzun tekrarlandığını görürsünüz.source ./setenv.sh
3. Grafik iş akışıyla aracıları düzenleme
Bu görevde, şarkı önerisi oluşturucu projesini oluşturacak ve iki aracı çalıştırıp çıkışlarını birleştiren bir grafik iş akışı oluşturacaksınız.
Bir şarkı önerisi için konsept gerekir. Konsept, fikri ve bu fikri destekleyen öğeleri ifade eder. Bu kullanım alanında, iş kapsamı içinde farklı sorumluluklara sahip olan aracıları tasarlayacağız. Böylece, karmaşık görevleri nasıl ayırıp farklı sorumluluklara sahip farklı aracılara atayabileceğinizi ve bu görevleri nasıl daha kolay yönetebileceğinizi göstereceğiz.
Bu tür işlerin uzmanlar arasında paylaştırılması, her temsilcinin ne zaman çalışacağını koordine etmeyi gerektirir. Ajanınızın her alt ajanı ne zaman arayacağına karar vermesine izin verebilir veya daha deterministik bir yaklaşım uygulayabilirsiniz. Bu codelab'de, grafik iş akışıyla deterministik bir yaklaşım kullanacaksınız.
İlk ajan projesini oluşturma
- Cloud Shell'de, bu kodu terminale yapıştırarak projeyi oluşturun:
Bu işlem, çalıştırılabilir eksiksiz bir proje oluşturur: bir aracı, bircd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator agents-cli create pitch-generator \ --agent adk \ --agent-directory pitch_generator \ --deployment-target cloud_run \ --session-type in_memory \ --cicd-runner skip \ --region <YOUR_REGION> \ --auto-approveDockerfile, testler, daha sonra kullanılmak üzere Terraform ve.env.exampleşablonuyla birlikte bir.envdosyası. Bu codelab için iki bölüm önemlidir:pitch_generator/agent.py, ajanı ve yeniden yazdığınız dosyayı ifade eder.pitch_generator/,--agent-directorytarafından ayarlanan paket adıdır.
setenv.shile dışa aktardığınız ortamdan okur. Bu nedenle, burada yapılandırılacak bir şey yoktur. - Bağımlılıkları yükleyin:
Not: İskele, projeyi bu codelab'de daha sonra kullanılan protokol olan A2A'yı sunacak şekilde de bağlar. Şimdilik bu dosyaları olduğu gibi bırakın.cd pitch-generator agents-cli update -y && agents-cli install && uv sync --upgrade-package google-adk
Grafiği anlama
ADK v2.x, grafik iş akışlarını destekler. Grafikler, iş birimleri olan düğümlerden ve bunları birbirine bağlayan kenarlardan oluşur. Bir düğüm genellikle bir aracıdır ancak düz bir Python işlevi de kullanılabilir. Bir kenar, bir düğüm tamamlandığında bir sonrakinin çalışacağını belirtir.
Kenarlar liste olarak yazılır ve ADK sırayı belirler:
edges=[
("START", creative_director), ## the graph begins here
(creative_director, copywriter), ## then this
]
İç içe yerleştirme, kenara anlamını verir:
Edge | Anlamı |
| Zincir. Önce a, sonra b, sonra c, birbiri ardına |
| Ayrıntılı bir şekilde. Önce a, sonra aynı anda b ve c |
| Fan-in. c, hem a hem de b'yi bekler. |
Fan-in için JoinNode kullanırsınız. Bu görev, tüm öncüllerin tamamlanmasını bekler ve çıkışlarını birlikte iletir.
Bu görevde aşağıdaki iş akışını oluşturacağız:

Ardışık düzeni oluşturma
- Bu kodu terminale yapıştırarak aracı dosyasını açın:
Cloud Shell düzenleyicisinde iskelelicd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/pitch-generator cloudshell edit pitch_generator/agent.pyagent.pyöğesini görürsünüz.💡 İpucu: İstediğiniz zaman kodu seçip ampul simgesini kullanarak Gemini'dan kodu açıklamasını isteyebilirsiniz. Antigravity CLI'ya da sorabilirsiniz.
pitch_generator/agent.pydüzenleyicisindeki dosyanın tamamını aşağıdakiyle değiştirin:import mimetypes import os from dotenv import load_dotenv from google.adk.agents import Agent from google.adk.agents.context import Context from google.adk.agents.remote_a2a_agent import ( AGENT_CARD_WELL_KNOWN_PATH, RemoteA2aAgent, ) from google.adk.apps import App from google.adk.events.event import Event from google.adk.models import Gemini from google.adk.workflow import JoinNode, Workflow from google.genai import types load_dotenv() MODEL = "gemini-3.8-flash" def _model() -> Gemini: return Gemini( model=MODEL, client_kwargs={"location": "global"}, retry_options=types.HttpRetryOptions(attempts=3), ) """ ⬇️ Configure visual-director RemoteA2aAgent agent below this comment """ creative_director = Agent( name="creative_director", model=_model(), description="Turns a raw idea into a campaign concept.", instruction=( "You are the Creative Director. Turn the idea you are given into ONE " "punchy campaign concept line with the rationale explanation behind it." ), output_key="creative_director", ) copywriter = Agent( name="copywriter", model=Gemini(model=MODEL, retry_options=types.HttpRetryOptions(attempts=3)), description="Writes social copy for a campaign concept.", instruction=( "You are the Copywriter. Write ONE short social caption for the " "campaign concept you are given. Under 25 words." ), ) """ Waits for every node wired into it, then hands their outputs on together.""" assemble = JoinNode(name="assemble") def package(node_input: dict): """Render the joined branches as the finished pitch. """ pitch = "\n\n".join( [ f"CONCEPT\n{node_input['creative_director']}", f"COPY\n{node_input['copywriter']}", ] ) """ The first event is what the user sees. The second is the node's output, which any downstream node would receive.""" yield Event(content=types.Content(role="model", parts=[types.Part(text=pitch)])) yield Event(output=pitch) """ we put creative_director before `assemble` so that we can gather the `Concept` output at assemble""" root_agent = Workflow( name="pitch_generator", edges=[ ("START", creative_director), (creative_director, copywriter), ((creative_director, copywriter), assemble), (assemble, package), ], ) app = App( root_agent=root_agent, name="pitch_generator", )agents-cli, ADK'ya benzer şekilde inceleme içinplaygroundadlı yerleşik bir web geliştirme kullanıcı arayüzü içerir. Playground'u başlatmak için: Telemetriyi etkinleştirmek isteyip istemediğiniz sorulur.agents-cli playground --port 8080nyazıp Enter tuşuna basın.- Terminalin sağ üst kısmındaki göz simgesi olan Web önizlemesi'ni tıklayın ve 8080 bağlantı noktasında önizle'yi seçin.

- Temsilciyle sohbet etmek için aşağıdaki arayüzü görürsünüz. "Kediler için uçan kaykaylar" istemini göndermeyi deneyin. Aşağıdaki gibi bir yanıt görürsünüz. Burada iş akışı grafiğinin tamamını da inceleyebilirsiniz.
Bu yanıtın nasıl üretildiğini inceleyin. Deneme alanında, grafiğin sırasıyla creative_director,copywriter,assemblevepackageadımlarını nasıl attığı gösterilir. Bu sıra, kablolarını bağladığınız grafiktir. Bu şekilde, yeni oluşturduğunuz grafiği hızlıca onaylayabilirsiniz. - Terminale dönün ve Ctrl+C tuşlarına iki kez basarak çalışan
agents-cli playgroundişlemini durdurun.
4. Bir ajana beceri atama
Bu görevde ikinci bir aracı oluşturup ona beceri olarak paketlenmiş bir dizi marka yönergesi vereceksiniz.
Ardışık düzen, kelimeleri yazar. Bir resmin kendine özgü bir stili olmalıdır: palet, ışıklandırma şekli, kullandığınız ve asla kullanmadığınız kompozisyonlar. Bu bir kurallar sayfasıdır ve kurallar sayfasının yönetilmesi için daha iyi bir mekanizma gerekir. Bunu yapmanın bir yolu, "aracı becerisi" olarak paketlemektir.
Beceri, SKILL.md dosyası içeren bir klasördür. Beceri dizininin yapısı, aşağıdaki örnekte (visual_director kullanılarak, oluşturacağınız bir sonraki ajan) gösterildiği gibidir:
visual_director/
...
agent.py
skills/
brand-guidelines/
SKILL.md ## required: frontmatter + instructions
references/ ## optional: longer supporting documents
assets/ ## optional: templates, images, data
scripts/ ## optional: executable helpers
...
Ajan becerisinin giriş noktası, aşağıdaki gibi bir YAML ön bölümü içeren SKILL.md dosyasıdır:
---
name: brand-guidelines
description: The house brand rules for a key visual. Load this before writing art direction, so the visual looks like it came from this brand.
---
## Brand guidelines
Deep indigo and slate as the ground. One warm accent, amber or terracotta...
Frontmatter etikettir. Ajanın önceden gördüğü tek şey budur. Bu nedenle, becerinin ne zaman yüklenmeye değer olduğunu açıklamada belirtmeniz gerekir. Gövde, içeriktir ve aracı load_skill çağırana kadar bağlamın dışında kalır.
Buradaki amaç, bu ayrımı yapmaktır. İstem kısa kalır, ajan kuralları yalnızca gerektiğinde kullanır ve stil değişikliği, talimat dizesinde arama yapmak yerine tek bir dosyayı düzenlemek anlamına gelir.
Aşağıdaki şemada gösterildiği gibi, ajan becerilerini kullanarak ikinci ajanı (visual-director) oluşturmaya başlayacağız:

Görsel yönetmeni yönlendirme
Görsel bileşeni işlemek için uzman bir temsilci (visual-director) oluşturacaksınız. Bu proje, daha sonra A2A protokolünü kullanarak birden fazla aracının birbiriyle nasıl iletişim kurduğunu göstermek için kendi hizmetine dönüştüğünden ayrı bir projedir. Yan yana iki projeniz olur:
bwg-multi-agent-pitch-generator/
├── pitch-generator/ ## built in the last task
│ ├── pitch_generator/
│ │ ├── agent.py ## the graph you wrote
│ │ ├── app_utils/ ## generated, A2A wiring
│ │ └── fast_api_app.py ## generated, serves the agent
│ └── pyproject.toml
└── visual-director/ ## created below
└── ... ## the same shape again
- Bu kodu terminale yapıştırarak projeyi oluşturun ve bağımlılarını yükleyin:
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator agents-cli create visual-director \ --agent adk \ --agent-directory visual_director \ --deployment-target cloud_run \ --session-type in_memory \ --cicd-runner skip \ --region <YOUR_REGION> \ --auto-approve cd visual-director agents-cli update -y && agents-cli install && uv sync --upgrade-package google-adk
Markalama kurallarını yazma
- Beceri klasörünü oluşturun ve dosyayı açın:
mkdir -p visual_director/skills/brand-guidelines cloudshell edit visual_director/skills/brand-guidelines/SKILL.md - Aşağıdaki içeriği
SKILL.mddosyasına Düzenleyici'de yapıştırın ve kaydedin:
--- name: brand-guidelines description: The house brand rules for a key visual — palette, light, composition, subject treatment, and what never appears. Load this before writing art direction or rendering an image, so the visual looks like it came from this brand rather than from a generic image model. --- ## Brand guidelines House style for campaign key visuals. Every rule here beats a preference in the brief. If the brief asks for something forbidden below, follow the brief for the subject and the guidelines for the treatment. ## Palette Deep indigo and slate as the ground. One warm accent — amber or terracotta — carrying the eye to the subject. Nothing neon, nothing fluorescent. At most three colors with any weight. A fourth reads as clutter. ## Light One dominant source, low and raking. Long shadows are wanted. Golden hour or a single hard studio key, never flat overhead light and never a ring light. Rim light is allowed on the subject only, and only to separate it from the ground. ## Composition Subject off-center, roughly a third in. Generous negative space on the opposite side — copy lands there later, so leave it genuinely empty. Eye level or slightly below. No top-down flat lays. No fisheye, no Dutch tilt. ## Subject One subject. If the idea implies a crowd, pick the one that carries it. Photographic realism with a shallow depth of field. Not illustration, not 3D render, not clay, not pixel art. ## Never - Text, logos, watermarks, or signage anywhere in the frame - Collage or split-screen layouts - Chrome, lens flare, bokeh sparkle - Cool-toned neon cyan or magenta ## Rendering the prompt When you turn art direction into an image prompt, state the palette, the light, and the composition explicitly. An image model will not infer them from the subject alone. Put the "Never" items in as plain description of what the frame does contain, not as negatives — image models handle a positive description far better than a list of prohibitions.
visual_director/agent.py uygulamasını güncelleme
agent.py dosyasını güncelleyin ve daha önce tanımlanmış beceriyle donatılacak şekilde yapılandırın.
- Aracı dosyasını açın:
cloudshell edit ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/visual-director/visual_director/agent.py visual_director/agent.pydosyasının tüm içeriğini aşağıdaki kodla değiştirin:import mimetypes from pathlib import Path from google import genai from google.adk.agents import Agent from google.adk.apps import App from google.adk.models import Gemini from google.adk.skills import load_skill_from_dir from google.adk.tools import ToolContext from google.adk.tools.skill_toolset import SkillToolset from google.genai import types MODEL = "gemini-3.8-flash" ## Configure the `brand-guidelines` skill for the agent BRAND_SKILL = load_skill_from_dir(Path(__file__).parent / "skills" / "brand-guidelines") ## Add definition of `generate_key_visual` tool below this comment root_agent = Agent( name="visual_director", model=Gemini( model=MODEL, client_kwargs={"location": "global"}, retry_options=types.HttpRetryOptions(attempts=3), ), description="Turns a campaign concept into art direction and a key visual.", instruction="""You are the Visual Director on a campaign pitch team. Call `load_skill` for `brand-guidelines` before you write anything. The house style is not optional and it is not in this prompt. You are given a campaign concept. Then, in order: 1. Write art direction for ONE key visual that sells it, obeying the brand guidelines: subject, composition, lighting, color, mood. Three or four sentences. 2. Call `generate_key_visual` with exactly that art direction. Your final reply is the art direction itself and nothing else. No preamble, no alternatives, no questions back. Do not mention the skill, the tool, or the image file — the image travels on its own.""", tools=[ SkillToolset(skills=[BRAND_SKILL]), ## Supply the `generate_key_visual` tool below this comment ], ) app = App( root_agent=root_agent, name="visual_director", )visual-directoraracısı artık bir aracı becerisiyle düzgün şekilde yapılandırıldı. Test etmeden önce bu ajana, temel özelliklerinden biri olarak resim öğeleri oluşturma aracı ekleyeceksiniz.
5. Bir ajana görüntü üretme aracı ekleme
Bu görevde, görsel yönetmene sanat yönetimini görüntü olarak oluşturup yapay ürün olarak kaydeden bir araç veriyorsunuz. Yapay ürün, yapay zeka aracısının bir görev sırasında oluşturduğu, değiştirdiği veya kullandığı, adlandırılmış ve sürümü belirlenmiş bir ikili veri parçası ya da dosya içeriğidir.

Aracı uygulayın ve temsilciye ekleyin
- Aracı dosyasını açın:
cloudshell edit ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/visual-director/visual_director/agent.py - Aşağıdaki
generate_key_visualaracınıroot_agenttanımından önce kopyalayın:async def generate_key_visual(art_direction: str, tool_context: ToolContext) -> dict: """Render the art direction as the campaign's key visual. Args: art_direction: The art direction to render, in full. Returns: The saved artifact's filename, version, size and media type. """ IMAGE_MODEL = "gemini-3.1-flash-lite-image" response = await genai.Client(location="global").aio.models.generate_content( model=IMAGE_MODEL, contents=art_direction ) ## The image arrives as inline bytes on one of the response parts. image = next( ( part.inline_data for part in response.candidates[0].content.parts or [] if part.inline_data ), None, ) if image is None: raise ValueError(f"{IMAGE_MODEL} returned no image for: {art_direction[:120]}") filename = "key_visual" + ( mimetypes.guess_extension(image.mime_type or "") or ".bin" ) version = await tool_context.save_artifact(filename, types.Part(inline_data=image)) ## Return the artifact filename and version return { "filename": filename, "version": version, "bytes": len(image.data), "mime_type": image.mime_type, } - Ajana aracı eklemek için
generate_key_visualsimgesiniSkillToolsetsimgesinin altına ekleyin:tools=[ SkillToolset(skills=[BRAND_SKILL]), ## Supply the `generate_key_visual` tool below this comment generate_key_visual, ], agents-cli, ADK'ya benzer şekilde inceleme içinplaygroundadlı yerleşik bir web geliştirme kullanıcı arayüzü içerir. Playground'u başlatmak için:agents-cli playground --port 8080- Terminalin sağ üst kısmındaki göz simgesi olan Web önizlemesi'ni tıklayın ve 8080 bağlantı noktasında önizle'yi seçin.

- Temsilciyle sohbet etmek için aşağıdaki arayüzü görürsünüz. "Dokuz can. Sıfır yer çekimi."
Markalama kuralları becerisini okumak için visual_directoraracısının nasılload_skill("brand-guidelines")yürüttüğünü ve ardından görüntüyü oluşturmaya başlamak için nasılgenerate_key_visualyürüttüğünü etkileşimlerden inceleyebilirsiniz. Elde edilen resim, kullanıcı arayüzünde de gösterilen ve kolayca incelenebilen bir yapıt olarak saklanır. - Terminale dönün ve Ctrl+C tuşlarına iki kez basarak çalışan
agents-cli playgroundişlemini durdurun.
6. A2A protokolü ile çoklu ajan mimarisi
Bu görevde, Görsel Yönetici'yi diğer aracıların çağırabileceği bir hizmet olarak kullanıma sunacak ve oluşturulan resimle yanıt verecek şekilde yapılandıracaksınız.
Agent2Agent (A2A), bir ajanın ağ üzerinden başka bir ajanı çağırması için kullanılan açık bir protokoldür. Merkezi unsur, temsilcinin kendisi hakkında iyi bilinen bir URL aracılığıyla yayınladığı, adını, açıklamasını ve özelliklerini içeren bir JSON belgesi olan temsilci kartıdır. Arayan kişi kartı getirir ve kaynak kodu, bağımlılıklar veya dil paylaşımı olmadan kartın arkasındaki temsilciyle nasıl konuşacağını bilir.

agents-cli bu özelliği varsayılan olarak zaten bağlamıştır. Aracıdan kartı oluşturan ve rotaları bağlayan visual_director/app_utils/a2a.py ile bunları sunan visual_director/fast_api_app.py iskeleleri oluşturulur. Yapay nesneleri istemciye geri göndermesini sağlamak için küçük bir değişiklik yapmanız yeterlidir.
Mimari, aşağıda gösterildiği gibi görünecektir. Temsilcinin henüz ilk iş akışımıza entegre edilmediğini unutmayın:

agents-cli A2A sunucu iskelesi
visual-director aracısını agents-cli kullanarak başlattığımızda aşağıdaki kod ve modül zaten sağlanır. Aşağıdaki komutları terminale yapıştırarak bu dosyaları açın:
cloudshell edit visual_director/fast_api_app.py
cloudshell edit visual_director/app_utils/a2a.py
visual_director/fast_api_app.py, aracıyı başlatır ve A2A rotalarını uygulama adından oluşturulan bir yolun altına yerleştirir:
await attach_a2a_routes(
app,
agent=root_agent,
runner=runner,
rpc_path=f"/a2a/{adk_app.name}", ## becomes /a2a/visual_director
)
visual_director/app_utils/a2a.py, üç hamlede gerisini halleder.
İlk olarak, ajanın kendisinden ajan kartı oluşturur. Ad, açıklama ve her araç, arayan kişinin okuyabileceği girişler haline gelir:
agent_card = await AgentCardBuilder(
agent=agent,
rpc_url=f"{resolved_app_url}{rpc_path}",
).build()
İkincisi, protokol ile temsilciniz arasına bir yürütücü yerleştirir. Gelen A2A istekleri ADK çalıştırmalarına çevrilir ve sonuçlar tekrar çevrilir:
request_handler = DefaultRequestHandler(
agent_executor=A2aAgentExecutor(runner=runner, force_new_version=True),
task_store=task_store,
agent_card=agent_card,
)
Üçüncüsü, iki rota oluşturur: biri kartı sunar, diğeri aramaları kabul eder.
Rota | Amaç |
| Kart Arayan kişi, temsilcinin neler yapabileceğini öğrenmek için önce bunu okur. |
| JSON-RPC uç noktası. Gerçek isteklerin gittiği yer |
Çıktıların sınırı aşmasına izin verme
Varsayılan olarak, A2A yanıtı metin içerir. Resim bir yapay nesnedir ve dahil edilecek şekilde yapılandırmadığınız sürece yayın aracısının deposunda kalır.
- Oluşturulan A2A dosyasını açın:
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/visual-director cloudshell edit visual_director/app_utils/a2a.py AgentCardBuilderiçe aktarma işlemini bulun ve altınaA2aAgentExecutorConfigileinclude_artifacts_in_a2a_event_interceptoriçe aktarma işlemlerini ekleyin:## ... ## from google.adk.a2a.utils.agent_card_builder import AgentCardBuilder ## Add the following two below `AgentCardBuilder` import from google.adk.a2a.executor.config import A2aAgentExecutorConfig from google.adk.a2a.executor.interceptors.include_artifacts_in_a2a_event import ( include_artifacts_in_a2a_event_interceptor, )agent_executor=A2aAgentExecutor(runner=runner),satırını bulup aşağıdakiyle değiştirin (A2aAgentExecutorConfigekleyerek):agent_executor=A2aAgentExecutor( runner=runner, force_new_version=True, config=A2aAgentExecutorConfig( execute_interceptors=[include_artifacts_in_a2a_event_interceptor] ), ),
Hizmeti başlatın ve yayınlanan A2A kartını okuyun.
- Sunucuyu arka planda başlatın. Kartın kendi adresi olarak bildirdiği adres
APP_URLolduğundan bu adresi tanımlamanız gerekir. Bunu terminale yapıştırın:APP_URL=http://localhost:8801 nohup uv run uvicorn visual_director.fast_api_app:app --port 8801 > /tmp/visual-director.log 2>&1 & - Başlaması için birkaç saniye bekleyin, ardından yayınlandığını doğrulayın:
Şunları görmeniz gerekir:sleep 10 tail -2 /tmp/visual-director.logINFO: Application startup complete. INFO: Uvicorn running on http://127.0.0.1:8801 (Press CTRL+C to quit) - Ajanın yayınladığı kartı okuyun:
Kartta,curl -s http://localhost:8801/a2a/visual_director/.well-known/agent-card.json | python3 -m json.toolgenerate_key_visualdahil olmak üzere temsilcinin adı, açıklaması, URL'si ve becerileri listelenir. Doğrudan koddaki aracı tanımından oluşturulur.{ "name": "visual_director", "description": "Turns a campaign concept into art direction and a key visual.", "skills": [ { "id": "visual_director", "name": "model", "tags": [ "llm" ] }, { "id": "visual_director-generate_key_visual", "name": "generate_key_visual", "description": "Render the art direction as the campaign's key visual.\n\nArgs:\n art_direction: The art direction to render, in full.\n\nReturns:\n The saved artifact's filename, version, size and media type.", "tags": [ "llm", "tools" ] } ], "preferredTransport": "JSONRPC", "protocolVersion": "0.3", "url": "http://localhost:8801/a2a/visual_director" }visual-directoraracısını anapitch-generatoriş akışına yerleştirmeye hazırsınız.
7. A2A uzak aracısını iş akışına yerleştirme
Bu görevde, uzak aracıyı grafiğe üçüncü bir dal olarak ekleyeceksiniz.
Uzak aracı, RemoteA2aAgent içine alınır ve grafikte diğer düğümler gibi yerleştirilir. Kenarlar aynı şekli korur ve koordinatör, hangi düğümlerinin yerel olduğunu bilmez.
Koordinatörü hizmete yönlendirin ve grafik iş akışını güncelleyin
- Aracı dosyasını açın:
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/pitch-generator cloudshell edit pitch_generator/agent.py - Bu içe aktarma işlemlerini dosyanın en üstüne, mevcut olanların yanına ekleyin:
import asyncio import subprocess import google.auth.transport.requests import google.oauth2.id_token import httpx from google.adk.a2a.converters.part_converter import convert_genai_part_to_a2a_part creative_directorbildiriminin üzerine aşağıdakiRemoteA2aAgenttanımı ekleyin:VISUAL_DIRECTOR_URL = os.getenv("VISUAL_DIRECTOR_URL", "http://localhost:8801") ## For deployment on Cloud Run def _cloud_run_client() -> httpx.AsyncClient | None: """An httpx client that signs each request with a Cloud Run ID token. Cloud Run deploys private, so both the agent-card fetch and the A2A calls need one. """ if not VISUAL_DIRECTOR_URL.startswith("https://"): return None async def sign(request: httpx.Request) -> None: token = None try: token = await asyncio.to_thread( google.oauth2.id_token.fetch_id_token, google.auth.transport.requests.Request(), VISUAL_DIRECTOR_URL, ) except Exception: token = subprocess.check_output( ["gcloud", "auth", "print-identity-token", "-q"], stderr=subprocess.PIPE ).decode().strip() if not token: raise Exception("Failed to fetch ID token") request.headers["Authorization"] = f"Bearer {token}" return httpx.AsyncClient(event_hooks={"request": [sign]}, timeout=600) ## Keep the approval's tool traffic out of the A2A request def _pitch_parts_only(part: types.Part): """Sends the Visual Director text and media only. RemoteA2aAgent replays the session on every call, and the Visual Director runs downstream of the human approval, so the approval's function_response would travel alongside the concept text. An ADK server reads a function response as "resume the paused invocation" and rejects a message that also carries text, so drop the tool parts here. """ if part.function_call or part.function_response: return None return convert_genai_part_to_a2a_part(part) visual_director = RemoteA2aAgent( name="visual_director", description="Turns a campaign concept into art direction for one key visual.", agent_card=( f"{VISUAL_DIRECTOR_URL}/a2a/visual_director{AGENT_CARD_WELL_KNOWN_PATH}" ), httpx_client=_cloud_run_client(), genai_part_converter=_pitch_parts_only, )packagedüğümü Python işlevini aşağıdaki tanımla üzerine yazın veya değiştirin:async def package(ctx: Context, node_input: dict): """Render the joined branches as the finished pitch.""" empty = [name for name, value in node_input.items() if not value] if empty: raise ValueError(f"nothing reached the join from: {', '.join(empty)}") def _key_visual(ctx: Context) -> types.Blob | None: """The image the Visual Director sent back, or None if it sent none.""" for event in reversed(ctx.session.events): if event.author != "visual_director" or not event.content: continue for part in event.content.parts or []: if part.inline_data and part.inline_data.data: return part.inline_data return None image = _key_visual(ctx) if image is None: raise ValueError("the Visual Director returned art direction but no image") suffix = mimetypes.guess_extension(image.mime_type or "") or ".bin" filename = f"key_visual{suffix}" await ctx.save_artifact(filename, types.Part(inline_data=image)) pitch = "\n\n".join( [ f"CONCEPT\n{node_input['creative_director']}", f"COPY\n{node_input['copywriter']}", f"ART DIRECTION\n{node_input['visual_director']}", f"KEY VISUAL\n{filename}, {len(image.data)} bytes, {image.mime_type}", ] ) yield Event( content=types.Content( role="model", parts=[types.Part(text=pitch), types.Part(inline_data=image)], ) ) yield Event(output=pitch)- Aşağı akış oluşturma işlemi devam etmeden önce İnsan Onayı Aşaması ekleyin.
pitch_generator/agent.pybölümünde,root_agentüzerindeki onay düğümlerini tanımlayın:@node(rerun_on_resume=False) async def approve_concept(ctx: Context): yield RequestInput( message="Please approve the campaign concept (yes/no).", response_schema=str ) @node(rerun_on_resume=True) async def user_approval(ctx: Context): user_response = await ctx.run_node(approve_concept) if str(user_response).lower() in ("yes", "y"): approved_concept = f"## Approved Concept\n\n{ctx.session.state['creative_director']}" yield Event( content=types.Content( role="model", parts=[types.Part(text=approved_concept)] ) ) else: raise ValueError("User rejected the concept") - Son olarak, üst kısımdaki içe aktarma işlemlerini
google.adk.eventsvegoogle.adk.workflow'denRequestInputvenode'yi içerecek şekilde güncelleyin: vefrom google.adk.events import Event, RequestInput from google.adk.workflow import JoinNode, Workflow, noderoot_agentiş akışınıedgesuser_approvalüzerinden yönlendirecek şekilde değiştirin: Dikkat edilmesi gereken birkaç nokta:edges=[ ("START", creative_director), (creative_director, user_approval, (copywriter, visual_director)), ((creative_director, copywriter, visual_director), assemble), (assemble, package), ],- Kullanıcı müdahalesi (HITL) onayı:
approve_concept,RequestInputsonucunu verir. İş akışı bu düğüme ulaştığında yürütme duraklatılır ve arayana kesinti sinyali gönderilir. Kullanıcı onayı doğrulanana kadar aşağı akış dalları (copywritervevisual_director) çalışmaz. visual_director,copywriterile aynı şekilde kenarlarda görünür. Ancak biri işlev çağrısı, diğeri ise ağ üzerinden çalışır.- Şu anda yalnızca metin bir düğümün çıkışına yükseltildiğinden, döndürülen resim
node_inputyerine oturum etkinliklerinden okunur. Resim, A2A önleyici üzerinden sınırı aştı ancak uzak aracının etkinliklerine eklenmiş olarak geldi. Bu nedenle,_key_visualyardımcı işlevi resmi oradan alır.
- Kullanıcı müdahalesi (HITL) onayı:
Entegrasyonu test etme
Şimdi, Görsel Yönetmen (arka planda çalışır) ve Şarkı Önerisi Oluşturucu'nun A2A protokolü üzerinden iletişim kurabildiğini test edeceksiniz.
- Görsel Yönetmen'in arka planda çalıştığını onaylayın:
Buradacurl -s -o /dev/null -w "visual director: %{http_code}\n" http://localhost:8801/a2a/visual_director/.well-known/agent-card.jsonvisual director: 200sonucu almanız gerekir.Başka bir durumla karşılaşırsanız yeniden başlatmak için aşağıdaki komutu çalıştırın:fuser -k 8801/tcp 2>/dev/null || true cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/visual-director APP_URL=http://localhost:8801 nohup uv run uvicorn visual_director.fast_api_app:app --port 8801 > /tmp/visual-director.log 2>&1 & cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/pitch-generator sleep 10 curl -s -o /dev/null -w "visual director: %{http_code}\n" http://localhost:8801/a2a/visual_director/.well-known/agent-card.json - Önizlemeyi başlatın:
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/pitch-generator/pitch_generator agents-cli playground --port 8080 - Terminalin sağ üst kısmındaki göz simgesi olan Web önizlemesi'ni tıklayın ve 8080 bağlantı noktasında önizle'yi seçin.

- Temsilciyle sohbet etme arayüzünü görürsünüz. "Kediler için uçan kaykaylar" istemini göndermeyi deneyin.

İş akışının başlatıldığı ve her aracının çalıştığı tam etkileşimi görürsünüz. creative_directorkonsepti oluşturduktan sonra iş akışı onay adımında duraklatılır ve sizden şunu onaylamanız istenir: "Lütfen kampanya konseptini onaylayın (evet/hayır)." Devam etmek için giriş alanına "yes" (evet) yazın. Onaylandıktan sonra grafik açılır:visual-directoraracısının beceriyi yüklemeye ne zaman başladığını ve görüntü oluşturma işleminin ortasındacopywriteraracısının sosyal medya başlığını oluşturmayı ne zaman tamamladığını görebilirsiniz. Bu, her iki aracının da birbirini beklemeden paralel olarak çalıştığını gösterir. Her ikisi de tamamlandıktan sonraassembledüğümü,creative_directortarafından oluşturulan onaylı konseptle birlikte sonuçları birleştirerekpackageişlevinde şarkı önerisi içerik yayınını tamamlar.
8. Önemli görselleri Cloud Storage'da kalıcı hale getirme
Şimdiye kadar her önemli görsel hafızada kaldı. İşlem durduğu anda görüntü kaybolur. Bu durum, deneme alanı için sorun olmasa da kampanya için kullanışsızdır. Bu görevde, iş akışına yazılacak bir paket verir ve son görevde kullanacağınız bir BigQuery veri kümesi oluşturursunuz.
ADK, başlangıçta yapıtların nereye gideceğine karar verir. Oluşturulan app_utils/services.py, tek bir ortam değişkenini okur:
def get_artifact_service():
"""Process-wide artifact service: GCS when a bucket is set, else in-memory."""
if bucket := os.environ.get("LOGS_BUCKET_NAME"):
return GcsArtifactService(bucket_name=bucket)
return InMemoryArtifactService()
LOGS_BUCKET_NAME seçeneğini belirlerseniz her save_artifact görüşmesi bunun yerine Cloud Storage'da yer alır.

BigQuery veri kümesini oluşturma
- Cloud Shell'de, BigQuery veri kümesi oluşturmak için aşağıdaki komutu çalıştırın:
bq mk --dataset --location=<YOUR_REGION> --project_id=<YOUR_PROJECT_ID> bwg - Koordinatörün yapay ürün deposunu kovaya yönlendirin:
export LOGS_BUCKET_NAME="<YOUR_PROJECT_ID>-bwg"GcsArtifactService,gs://ön eki olmadan yalnızca paket adını alır. Diğer değişkenler gibi bu değişken de kabuğunuzda bulunur ve dağıtım görevi bunu Cloud Run'a iletir. - Bucket'ınızın içeriğini kontrol edin. Yeni bir tarayıcı sekmesinde şu URL'yi açın:
Paketi tıklayın. Geçmiş testlerinize bağlı olarak, daha önce oluşturulmuş resimler içerebilir.https://console.cloud.google.com/storage/browser?project=<YOUR_PROJECT_ID>
9. Visual Director aracısını Cloud Run'a dağıtma
Şimdiye kadar her şey tek bir makinede çalıştı ve Görsel Yönetmen'e localhost:8801 adresinden ulaşılabiliyordu. Bu görevde, Visual Director aracısını kendi Cloud Run hizmeti olarak dağıtacak ve Agent2Agent (A2A) protokolünü kullanarak ağ üzerinden şarkı önerisi oluşturucuyla iletişim kurmasına izin vereceksiniz.
Görsel Yönetmen gerçek bir https:// URL'si alır. Böylece, daha önce yazdığınız _cloud_run_client, None döndürmek yerine istekleri imzalamaya başlar. Ayrıca, Cloud Run dağıtımları varsayılan olarak özeldir.

Görsel Yönetmen'i dağıtma
- Yerel arka plan hizmeti ve oyun alanı hâlâ çalışıyorsa bunları durdurun:
fuser -k 8801/tcp 2>/dev/null || true fuser -k 8000/tcp 2>/dev/null || true - Ajanı dağıtın. Bu işlem, bir kapsayıcı oluşturur ve kapsayıcıyı gönderir.⏰ Bu işlem birkaç dakika sürer.
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/visual-director source .env agents-cli deploy \ --service-name visual-director \ --project <YOUR_PROJECT_ID> \ --region <YOUR_REGION> \ --no-confirm-project \ --labels dev-tutorial=bwg001-devlab-1 \ --update-env-vars "LOGS_BUCKET_NAME=$LOGS_BUCKET_NAME,GOOGLE_GENAI_USE_VERTEXAI=true,GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT,GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION,GOOGLE_CLOUD_REGION=$GOOGLE_CLOUD_REGION"
Cloud Run'a dağıtılan Visual Director'ı kullanan Şarkı Önerisi Üretici'yi çalıştırma
- Görsel Yönetmen URL'sini okuyun ve bu URL'yi kullanan Şarkı Önerisi Oluşturucu'yu çalıştırın:
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/pitch-generator source .env export VISUAL_DIRECTOR_URL=$(gcloud run services list \ --project <YOUR_PROJECT_ID> \ --region <YOUR_REGION> \ --flatten='spec.template.spec.containers[0].env' \ --filter='metadata.name=visual-director AND spec.template.spec.containers[0].env.name=APP_URL' \ --format='value(spec.template.spec.containers[0].env.value)') echo "Visual Director is at $VISUAL_DIRECTOR_URL" APP_URL=http://localhost:8000 nohup uv run uvicorn pitch_generator.fast_api_app:app --port 8000 > /tmp/visual-pitch_generator.log 2>&1 &
Dağıtılan iş akışını çağırma
Her iki aracı da A2A protokolünü desteklemelidir. Depoda, A2A aracılığıyla Pitch Generator'ı çağırmak için küçük bir istemci bulunur.
PITCH_GENERATOR_URL, yerel olarak çalışan Şarkı Önerisi Oluşturucu URL'sine ayarlanmalıdır. Bu sırada, Görsel Yönetmen Cloud Run'da çalışır ve Şarkı Önerisi Oluşturucu, A2A üzerinden Görsel Yönetmen ile iletişim kurar.
- İstemciyi projenize kopyalayın ve uygulayın:
İş akışında insan onayı aşaması olduğu için taslak konsept oluşturulduktan sonra komut dosyası duraklatılır:cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/pitch-generator cp ../solution/pitch-generator/call_agent.py . PITCH_GENERATOR_URL=http://localhost:8000 uv run python call_agent.py "Flying skateboards for cats" --save-image ./key_visual.png İş akışını onaylayıp devam ettirmek için=== HUMAN APPROVAL REQUIRED === [DRAFT CONCEPT] Concept Line: "Gravity is a Suggestion." ... Please approve the campaign concept (yes/no):yesyazıp Enter tuşuna basın. (Otomatik olarak onaylamak için-yveya--auto-approveparametrelerini de iletebilirsiniz). call_agent.pydosyasını açın vea2a-sdkkullanarak ajanla nasıl etkileşim kurduğunu inceleyin:ClientFactory, resmi bir A2AClienthedeflemehttps://SERVICE_URL/a2a/pitch_generatoroluşturur.generate_pitch_async, ilkSendMessageRequest'ı gönderir. YanıtTaskState.TASK_STATE_INPUT_REQUIREDile döndüğündeadk_request_inputbölümünü algılar, taslak konsepti gösterir, onayınızı alır ve yanıtınızı içeren bir özgeçmiş isteğini göreve geri gönderir.- Ayrıştırma döngüsü, tamamlanan görevin yapıtlarındaki
CONCEPT,COPYveART DIRECTIONbölümlerini okur ve ikili resmikey_visual.pngkonumuna kaydeder.
key_visual.pngkonumuna kaydedildiğini görmelisiniz.- BigQuery'nin işaret edebileceği bir ön ek altında, önemli resmi paketinize yükleyin:
gcloud storage cp ./key_visual.png gs://<YOUR_PROJECT_ID>-bwg/key-visuals/cats.png - Karşılaştırabileceğiniz bir içerik olması için ikinci bir şarkı önerisi oluşturun ve bunu da yükleyin:
PITCH_GENERATOR_URL=http://localhost:8000 uv run python call_agent.py "A commuter bike built for rainy cities" --save-image ./bike.png gcloud storage cp ./bike.png gs://<YOUR_PROJECT_ID>-bwg/key-visuals/bike.png
10. BigQuery'de marka uyumu için temel görsellere puan verme
Artık bir pakette resimleriniz ve bu resimlere şekil vermesi gereken marka kurallarınız var. Bu görevde, iki öğeyi bir araya getiriyorsunuz: BigQuery'deki resimlere referans verin, ardından bir Gemini modelinden her birini yönergelere göre derecelendirmesini isteyin. Bu sırada Cloud Storage'dan tek bir bayt bile taşımayın.
Bu işlem için iki BigQuery özelliği kullanılır:
ObjectRef, bir Cloud Storage nesnesini işaret eden bir değerdir.OBJ.MAKE_REF, URI'ye ek olarak BigQuery'ye pakete yetki verilmiş erişim izni veren bir bağlantıdan oluşturur. Kurulum komut dosyası tarafından oluşturulanpitch-connection, bu bağlantıdır ve Storage Object Viewer ile Agent Platform User rollerini zaten içerir.AI.SCORE, bir istemi alır veFLOAT64döndürür. İstemde,ObjectRefdeğerleriyle dizeler karıştırılabilir. Böylece model, puan anahtarınızı ve görüntüleri birlikte görür.

Önemli görsellerin tablosunu oluşturma
- BigQuery Studio'yu yeni bir tarayıcı sekmesinde açın:
https://console.cloud.google.com/bigquery?project=<YOUR_PROJECT_ID> - Yeni sorgu oluştur'u (+ simgesi) tıklayın, ardından aşağıdakileri yapıştırıp çalıştırın (
veyerine proje kimliğinizi ve bölgenizi girin). Her bir temel görsel için bir satır oluşturur ve kampanya konseptini resme referansla eşleştirir:SET @@location = '<YOUR_REGION>'; CREATE OR REPLACE TABLE bwg.key_visuals AS SELECT campaign, concept, OBJ.FETCH_METADATA( OBJ.MAKE_REF(uri, '<YOUR_REGION>.pitch-connection') ) AS key_visual FROM UNNEST([ STRUCT( 'cats' AS campaign, 'Flying skateboards for cats' AS concept, 'gs://<YOUR_PROJECT_ID>-bwg/key-visuals/cats.png' AS uri ), STRUCT( 'bike', 'A commuter bike built for rainy cities', 'gs://<YOUR_PROJECT_ID>-bwg/key-visuals/bike.png' ) ]);
OBJ.MAKE_REF, URI ve bağlantıdan referans oluşturur.OBJ.FETCH_METADATAardından Cloud Storage ile iletişime geçer ve nesnenin boyutunu, içerik türünü ve oluşturma zamanını doldurur. Bu ikinci arama, bağlantınızın çalıştığını kanıtlamanın en hızlı yoludur: İzinler yanlışsadetailsalanı, meta veriler yerine hatayı tutarak geri döner. - Depoladığınız öğeleri inceleyin. Önceki sorguyu bu sorguyla değiştirin ve çalıştırın:
Tabloda resim değil, bir işaretçi ve meta verileri bulunur. Baytlar hiçbir zaman paketten ayrılmadı.SELECT campaign, concept, key_visual.uri, key_visual.details FROM bwg.key_visuals;
Her resmi marka kurallarına göre derecelendirin.
Görsel yönetmene bir palete, bir ışık kuralına ve bir kompozisyon kuralına uyması söylendi. Bunun gerçekten yapılıp yapılmadığı bir değerlendirme konusudur ve AI.SCORE bu amaçla kullanılır.
- Aşağıdaki sorguyu çalıştırın (
yerine bölgenizi girin). İstem bir demettir: değerlendirme ölçütleriniz, kampanya konsepti ve resim içinObjectRef:SELECT campaign, concept, AI.SCORE( ('''You are the brand guardian reviewing a campaign key visual. Score the attached image from 1 to 10 on how closely it follows these house rules: - Palette: deep indigo and slate, with one warm accent of amber or terracotta. Nothing neon. - Light: one dominant low, raking source with long shadows. No flat overhead light. - Composition: subject off-center with generous empty negative space on the opposite side. - Subject: one subject only, photographic realism, shallow depth of field. - Never: text, logos, or watermarks anywhere in the frame. A 10 obeys every rule. A 1 ignores them. The campaign concept is: ''', concept, key_visual), connection_id => '<YOUR_REGION>.pitch-connection', endpoint => 'gemini-3.5-flash' ) AS brand_fit FROM bwg.key_visuals ORDER BY brand_fit DESC; - Puanı, ekibinizin harekete geçebileceği bir karara dönüştürün:
CREATE OR REPLACE TABLE bwg.brand_review AS SELECT campaign, concept, brand_fit, IF(brand_fit >= 7, 'on brand', 'needs another pass') AS verdict FROM ( SELECT campaign, concept, AI.SCORE( ('''Score this campaign key visual from 1 to 10 on how closely it follows the house brand rules: deep indigo and slate palette with a single warm accent and nothing neon; one low raking light source with long shadows; the subject off-center with empty negative space opposite; a single photographic subject; and no text, logos, or watermarks in the frame. The campaign concept is: ''', concept, key_visual), connection_id => '<YOUR_REGION>.pitch-connection', endpoint => 'gemini-3.5-flash' ) AS brand_fit FROM bwg.key_visuals ); SELECT * FROM bwg.brand_review ORDER BY brand_fit DESC;AI.SCOREyalnızcaFLOAT64değerini döndürür. Bu nedenle, eşik düz SQL'de bulunur ve isteme dokunmadan ayarlanabilir. Puanlama satır bazında yapılır. Bu nedenle, yalnızca burada oluşturduğunuz iki öğe değil, bir kampanyanın ürettiği her öğeye aynı değerlendirme ölçütü uygulanır.
11. Sonraki adımlar
Değerlendirme oluşturma
Ajan değerlendirmeleri veya "değerlendirmeler", bağımsız yapay zeka ajanlarının akıl yürütme, planlama, araç kullanma ve çok adımlı iş akışını tamamlama becerilerini ölçmek için kullanılan otomatik testlerdir. Bu testler, aracıların birim testine benzer ancak aracıların deterministik olmayan yapısını dikkate alır.
Temsilcilerimizden biri Human in the loop içerir. Bu, giriş beklediği anlamına gelir. Bu davranışın otomatik değerlendirmelerin önüne geçmemesi için Antigravity'nin mevcut kodda değişiklik yapmasına izin vermeniz gerekir.
Başlamanın en iyi yollarından biri Antigravity CLI'ya soru sormaktır.
KSA'yı başlatmak için Cloud Shell'e aşağıdakileri yazın:
cd ~/devrel-demos/codelabs/bwg-multi-agent-pitch-generator/
agy
Başlangıç istemi:
Explore this repository (`pitch-generator` and `visual-director`), including their agent instructions, tools, and `SKILL.md` files. Design and implement a creative `agents-cli eval` evaluation suite under `tests/eval/` that stress-tests the agent's behavior.
Değerlendirme örneğini ve bunları çalıştırma talimatlarını klonlanmış depoda da bulabilirsiniz.
12. Temizleme
Bu codelab'de kullanılan kaynaklar için Google Cloud hesabınızdan ücret alınmasını önlemek üzere projeyi (önerilir) veya codelab sırasında oluşturulan tek tek kaynakları silin:
gcloud run services delete visual-director --region=<YOUR_REGION> --project=<YOUR_PROJECT_ID> --quiet
bq rm -r -f -d <YOUR_PROJECT_ID>:bwg
bq rm --connection --location=<YOUR_REGION> --project_id=<YOUR_PROJECT_ID> pitch-connection
gcloud storage rm -r gs://<YOUR_PROJECT_ID>-bwg
13. Tebrikler!
Bu codelab'de, Agent Development Kit ile çoklu ajan içeren bir kampanya önerisi oluşturucu geliştirdiniz. Üç ajanı, deterministik bir grafik iş akışına bağladınız, marka kurallarını isteğe bağlı olarak yüklenen bir ajan becerisi olarak paketlediniz ve bir ajana, çıktısını bir çıktı olarak kaydeden bir görüntü üretme aracı verdiniz. Ardından, Görsel Yönetmen'i kendi A2A hizmetine böldünüz, uzaktan düğüm olarak grafiğe geri yerleştirdiniz, Cloud Run'a dağıttınız ve tüm iş akışını yerel olarak çalışan bir koordinatörden A2A üzerinden çağırdınız. Son olarak, BigQuery'den oluşturulan temel görsellere ObjectRef ile referans verdiniz ve bunları kendi marka kurallarınıza göre değerlendirmek için AI.SCORE kullandınız.